Skip to main content

fdomain_client/
fidl.rs

1// Copyright 2024 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::{
6    AnyHandle, AsHandleRef, Channel, ChannelMessageStream, ChannelWriter, Error, Handle,
7    HandleBased, HandleInfo, MessageBuf,
8};
9use fidl::epitaph::ChannelEpitaphExt;
10use fidl_fuchsia_fdomain as proto;
11use fuchsia_sync::Mutex;
12use futures::{Stream, StreamExt, TryStream};
13use std::cell::RefCell;
14use std::marker::PhantomData;
15use std::sync::Arc;
16use std::task::Poll;
17
18pub trait FDomainFlexibleIntoResult<T> {
19    fn into_result_fdomain<P: ProtocolMarker>(
20        self,
21        method_name: &'static str,
22    ) -> Result<T, fidl::Error>;
23}
24
25impl<T> FDomainFlexibleIntoResult<T> for fidl::encoding::Flexible<T> {
26    fn into_result_fdomain<P: ProtocolMarker>(
27        self,
28        method_name: &'static str,
29    ) -> Result<T, fidl::Error> {
30        match self {
31            fidl::encoding::Flexible::Ok(ok) => Ok(ok),
32            fidl::encoding::Flexible::FrameworkErr(fidl::encoding::FrameworkErr::UnknownMethod) => {
33                Err(fidl::Error::UnsupportedMethod { method_name, protocol_name: P::DEBUG_NAME })
34            }
35        }
36    }
37}
38
39impl<T, E> FDomainFlexibleIntoResult<Result<T, E>> for fidl::encoding::FlexibleResult<T, E> {
40    fn into_result_fdomain<P: ProtocolMarker>(
41        self,
42        method_name: &'static str,
43    ) -> Result<Result<T, E>, fidl::Error> {
44        match self {
45            fidl::encoding::FlexibleResult::Ok(ok) => Ok(Ok(ok)),
46            fidl::encoding::FlexibleResult::DomainErr(err) => Ok(Err(err)),
47            fidl::encoding::FlexibleResult::FrameworkErr(
48                fidl::encoding::FrameworkErr::UnknownMethod,
49            ) => Err(fidl::Error::UnsupportedMethod { method_name, protocol_name: P::DEBUG_NAME }),
50        }
51    }
52}
53
54#[derive(Debug)]
55pub struct FDomainProxyChannel(Mutex<ChannelMessageStream>, ChannelWriter);
56
57impl FDomainProxyChannel {
58    pub fn on_closed(&self) -> crate::OnFDomainSignals {
59        self.1.as_channel().on_closed()
60    }
61
62    pub fn read_etc(
63        &self,
64        ctx: &mut std::task::Context<'_>,
65        bytes: &mut Vec<u8>,
66        handles: &mut Vec<HandleInfo>,
67    ) -> Poll<Result<(), Option<crate::Error>>> {
68        let Some(got) = std::task::ready!(self.0.lock().poll_next_unpin(ctx)) else {
69            return Poll::Ready(Err(Some(Error::StreamingAborted)));
70        };
71
72        match got {
73            Ok(got) => {
74                *bytes = got.bytes;
75                *handles = got.handles;
76                Poll::Ready(Ok(()))
77            }
78            Err(Error::FDomain(proto::Error::TargetError(i)))
79                if i == fidl::Status::PEER_CLOSED.into_raw() =>
80            {
81                Poll::Ready(Err(None))
82            }
83            Err(e) => Poll::Ready(Err(Some(e))),
84        }
85    }
86}
87
88impl ::fidl::encoding::ProxyChannelBox<FDomainResourceDialect> for FDomainProxyChannel {
89    fn recv_etc_from(
90        &self,
91        ctx: &mut std::task::Context<'_>,
92        buf: &mut MessageBuf,
93    ) -> Poll<Result<(), Option<Error>>> {
94        let Some(got) = std::task::ready!(self.0.lock().poll_next_unpin(ctx)) else {
95            return Poll::Ready(Err(Some(Error::StreamingAborted)));
96        };
97
98        match got {
99            Ok(got) => {
100                *buf = got;
101                Poll::Ready(Ok(()))
102            }
103            Err(Error::FDomain(proto::Error::TargetError(i)))
104                if i == fidl::Status::PEER_CLOSED.into_raw() =>
105            {
106                Poll::Ready(Err(None))
107            }
108            Err(e) => Poll::Ready(Err(Some(e))),
109        }
110    }
111
112    fn write_etc(&self, bytes: &[u8], handles: &mut [HandleInfo]) -> Result<(), Option<Error>> {
113        let mut handle_ops = Vec::new();
114        for handle in handles {
115            handle_ops.push(crate::channel::HandleOp::Move(
116                std::mem::replace(&mut handle.handle, AnyHandle::invalid()).into(),
117                handle.rights,
118            ));
119        }
120        let _ = self.1.fdomain_write_etc(bytes, handle_ops);
121        Ok(())
122    }
123
124    fn is_closed(&self) -> bool {
125        self.0.lock().is_closed()
126    }
127
128    fn unbox(self) -> Channel {
129        self.0.into_inner().rejoin(self.1)
130    }
131
132    fn as_channel(&self) -> &Channel {
133        self.1.as_channel()
134    }
135}
136
137#[derive(Debug, Copy, Clone, Default)]
138pub struct FDomainResourceDialect;
139impl ::fidl::encoding::ResourceDialect for FDomainResourceDialect {
140    type Handle = Handle;
141    type MessageBufEtc = MessageBuf;
142    type ProxyChannel = Channel;
143
144    #[inline]
145    fn with_tls_buf<R>(f: impl FnOnce(&mut ::fidl::encoding::TlsBuf<Self>) -> R) -> R {
146        thread_local!(static TLS_BUF: RefCell<::fidl::encoding::TlsBuf<FDomainResourceDialect>> =
147            RefCell::new(::fidl::encoding::TlsBuf::default()));
148        TLS_BUF.with(|buf| f(&mut buf.borrow_mut()))
149    }
150}
151
152impl ::fidl::encoding::MessageBufFor<FDomainResourceDialect> for MessageBuf {
153    fn new() -> MessageBuf {
154        MessageBuf { bytes: Vec::new(), handles: Vec::new() }
155    }
156
157    fn split_mut(&mut self) -> (&mut Vec<u8>, &mut Vec<HandleInfo>) {
158        (&mut self.bytes, &mut self.handles)
159    }
160}
161
162impl Into<::fidl::TransportError> for Error {
163    fn into(self) -> ::fidl::TransportError {
164        match self {
165            Error::FDomain(proto::Error::TargetError(i)) => {
166                ::fidl::TransportError::Status(fidl::Status::err_from_raw(i))
167            }
168            Error::SocketWrite(proto::WriteSocketError {
169                error: proto::Error::TargetError(i),
170                ..
171            }) => ::fidl::TransportError::Status(fidl::Status::err_from_raw(i)),
172            Error::ChannelWrite(proto::WriteChannelError::Error(proto::Error::TargetError(i))) => {
173                ::fidl::TransportError::Status(fidl::Status::err_from_raw(i))
174            }
175            Error::ChannelWrite(proto::WriteChannelError::OpErrors(ops)) => {
176                let Some(op) = ops.into_iter().find_map(|x| x) else {
177                    let err = Box::<dyn std::error::Error + Send + Sync>::from(
178                        "Channel write handle operation reported failure with no status!"
179                            .to_owned(),
180                    );
181                    return ::fidl::TransportError::Other(err.into());
182                };
183                let op = *op;
184                Error::FDomain(op).into()
185            }
186            other => ::fidl::TransportError::Other(std::sync::Arc::new(other)),
187        }
188    }
189}
190
191impl ::fidl::encoding::ProxyChannelFor<FDomainResourceDialect> for Channel {
192    type Boxed = FDomainProxyChannel;
193    type Error = Error;
194    type HandleDisposition = HandleInfo;
195
196    fn boxed(self) -> Self::Boxed {
197        let (a, b, _) = self.force_stream();
198        FDomainProxyChannel(Mutex::new(a), b)
199    }
200
201    fn write_etc(&self, bytes: &[u8], handles: &mut [HandleInfo]) -> Result<(), Option<Error>> {
202        let mut handle_ops = Vec::new();
203        for handle in handles {
204            handle_ops.push(crate::channel::HandleOp::Move(
205                std::mem::replace(&mut handle.handle, AnyHandle::invalid()).into(),
206                handle.rights,
207            ));
208        }
209        let _ = self.fdomain_write_etc(bytes, handle_ops);
210        Ok(())
211    }
212}
213
214impl ::fidl::epitaph::ChannelLike for Channel {
215    fn write_epitaph(&self, bytes: &[u8]) -> Result<(), ::fidl::TransportError> {
216        let _ = self.write(bytes, vec![]);
217        Ok(())
218    }
219}
220
221impl ::fidl::encoding::HandleFor<FDomainResourceDialect> for Handle {
222    // This has to be static, so we can't encode a duplicate operation here
223    // anyway. So use HandleInfo.
224    type HandleInfo = HandleInfo;
225
226    fn invalid() -> Self {
227        Handle::invalid()
228    }
229
230    fn is_invalid(&self) -> bool {
231        self.client.upgrade().is_none()
232    }
233}
234
235impl ::fidl::encoding::HandleDispositionFor<FDomainResourceDialect> for HandleInfo {
236    fn from_handle(handle: Handle, object_type: fidl::ObjectType, rights: fidl::Rights) -> Self {
237        HandleInfo { handle: AnyHandle::from_handle(handle, object_type), rights }
238    }
239}
240
241impl ::fidl::encoding::HandleInfoFor<FDomainResourceDialect> for HandleInfo {
242    fn consume(
243        &mut self,
244        expected_object_type: fidl::ObjectType,
245        expected_rights: fidl::Rights,
246    ) -> Result<Handle, ::fidl::Error> {
247        let handle_info = std::mem::replace(
248            self,
249            HandleInfo {
250                handle: crate::AnyHandle::Unknown(Handle::invalid(), fidl::ObjectType::NONE),
251                rights: fidl::Rights::empty(),
252            },
253        );
254        let received_object_type = handle_info.handle.object_type();
255        if expected_object_type != fidl::ObjectType::NONE
256            && received_object_type != fidl::ObjectType::NONE
257            && expected_object_type != received_object_type
258        {
259            return Err(fidl::Error::IncorrectHandleSubtype {
260                // TODO: Find a way to put something better in here, either by
261                // expanding what FIDL can return or casting the protocol values
262                // to something FIDL can read.
263                expected: fidl::ObjectType::NONE,
264                received: fidl::ObjectType::NONE,
265            });
266        }
267
268        let received_rights = handle_info.rights;
269        if expected_rights != fidl::Rights::SAME_RIGHTS
270            && received_rights != fidl::Rights::SAME_RIGHTS
271            && expected_rights != received_rights
272        {
273            if !received_rights.contains(expected_rights) {
274                return Err(fidl::Error::MissingExpectedHandleRights {
275                    // TODO: As above, report something better here.
276                    missing_rights: fidl::Rights::empty(),
277                });
278            }
279
280            // TODO: The normal FIDL bindings call zx_handle_replace here to
281            // forcibly downgrade the handle rights. That's a whole IO operation
282            // for us so we won't bother, but maybe we should do something else?
283        }
284        Ok(handle_info.handle.into())
285    }
286
287    fn drop_in_place(&mut self) {
288        *self = HandleInfo {
289            handle: crate::AnyHandle::Unknown(Handle::invalid(), fidl::ObjectType::NONE),
290            rights: fidl::Rights::empty(),
291        };
292    }
293}
294
295impl ::fidl::encoding::EncodableAsHandle for crate::Event {
296    type Dialect = FDomainResourceDialect;
297}
298
299impl ::fidl::encoding::EncodableAsHandle for crate::EventPair {
300    type Dialect = FDomainResourceDialect;
301}
302
303impl ::fidl::encoding::EncodableAsHandle for crate::Socket {
304    type Dialect = FDomainResourceDialect;
305}
306
307impl ::fidl::encoding::EncodableAsHandle for crate::Channel {
308    type Dialect = FDomainResourceDialect;
309}
310
311impl ::fidl::encoding::EncodableAsHandle for crate::Vmo {
312    type Dialect = FDomainResourceDialect;
313}
314
315impl ::fidl::encoding::EncodableAsHandle for crate::Handle {
316    type Dialect = FDomainResourceDialect;
317}
318
319impl<T: ProtocolMarker> ::fidl::encoding::EncodableAsHandle for ClientEnd<T> {
320    type Dialect = FDomainResourceDialect;
321}
322
323impl<T: ProtocolMarker> ::fidl::encoding::EncodableAsHandle for ServerEnd<T> {
324    type Dialect = FDomainResourceDialect;
325}
326
327/// Implementations of this trait can be used to manufacture instances of a FIDL
328/// protocol and get metadata about a particular protocol.
329pub trait ProtocolMarker: Sized + Send + Sync + 'static {
330    /// The type of the structure against which FIDL requests are made.
331    /// Queries made against the proxy are sent to the paired `ServerEnd`.
332    type Proxy: Proxy<Protocol = Self>;
333
334    /// The type of the stream of requests coming into a server.
335    type RequestStream: RequestStream<Protocol = Self>;
336
337    /// The name of the protocol suitable for debug purposes.
338    ///
339    /// For discoverable protocols, this should be identical to
340    /// `<Self as DiscoverableProtocolMarker>::PROTOCOL_NAME`.
341    const DEBUG_NAME: &'static str;
342}
343
344/// A marker for a particular FIDL protocol that is also discoverable.
345///
346/// Discoverable protocols may be referred to by a string name, and can be
347/// conveniently exported in a service directory via an entry of that name.
348///
349/// If you get an error about this trait not being implemented, you probably
350/// need to add the `@discoverable` attribute to the FIDL protocol, like this:
351///
352/// ```fidl
353/// @discoverable
354/// protocol MyProtocol { ... };
355/// ```
356pub trait DiscoverableProtocolMarker: ProtocolMarker {
357    /// The name of the protocol (to be used for service lookup and discovery).
358    const PROTOCOL_NAME: &'static str = <Self as ProtocolMarker>::DEBUG_NAME;
359}
360
361/// A type which allows querying a remote FIDL server over a channel.
362pub trait Proxy: Sized + Send + Sync {
363    /// The protocol which this `Proxy` controls.
364    type Protocol: ProtocolMarker<Proxy = Self>;
365
366    /// Create a proxy over the given channel.
367    fn from_channel(inner: Channel) -> Self;
368
369    /// Attempt to convert the proxy back into a channel.
370    ///
371    /// This will only succeed if there are no active clones of this proxy
372    /// and no currently-alive `EventStream` or response futures that came from
373    /// this proxy.
374    fn into_channel(self) -> Result<Channel, Self>;
375
376    /// Attempt to convert the proxy back into a client end.
377    ///
378    /// This will only succeed if there are no active clones of this proxy
379    /// and no currently-alive `EventStream` or response futures that came from
380    /// this proxy.
381    fn into_client_end(self) -> Result<ClientEnd<Self::Protocol>, Self> {
382        match self.into_channel() {
383            Ok(channel) => Ok(ClientEnd::new(channel)),
384            Err(proxy) => Err(proxy),
385        }
386    }
387
388    /// Get a reference to the proxy's underlying channel.
389    ///
390    /// This should only be used for non-effectful operations. Reading or
391    /// writing to the channel is unsafe because the proxy assumes it has
392    /// exclusive control over these operations.
393    fn as_channel(&self) -> &Channel;
394
395    /// Get the client supporting this proxy. We call this a "domain" here because:
396    /// * Client is especially overloaded in contexts where this is useful.
397    /// * We simulate this call for target-side FIDL proxies, so it isn't always
398    ///   really a client.
399    fn domain(&self) -> Arc<crate::Client> {
400        self.as_channel().domain()
401    }
402
403    /// Returns a future that completes when the server receives the
404    /// `PEER_CLOSED` signal.
405    fn on_closed(&self) -> crate::OnFDomainSignals {
406        self.as_channel().on_closed()
407    }
408}
409
410/// A stream of requests coming into a FIDL server over a channel.
411pub trait RequestStream: Sized + Send + Stream + TryStream<Error = fidl::Error> + Unpin {
412    /// The protocol which this `RequestStream` serves.
413    type Protocol: ProtocolMarker<RequestStream = Self>;
414
415    /// The control handle for this `RequestStream`.
416    type ControlHandle: ControlHandle;
417
418    /// Returns a copy of the `ControlHandle` for the given stream.
419    /// This handle can be used to send events or shut down the request stream.
420    fn control_handle(&self) -> Self::ControlHandle;
421
422    /// Create a request stream from the given channel.
423    fn from_channel(inner: Channel) -> Self;
424
425    /// Convert to a `ServeInner`
426    fn into_inner(self) -> (std::sync::Arc<fidl::ServeInner<FDomainResourceDialect>>, bool);
427
428    /// Convert from a `ServeInner`
429    fn from_inner(
430        inner: std::sync::Arc<fidl::ServeInner<FDomainResourceDialect>>,
431        is_terminated: bool,
432    ) -> Self;
433}
434
435/// A type associated with a `RequestStream` that can be used to send FIDL
436/// events or to shut down the request stream.
437pub trait ControlHandle {
438    /// Set the server to shutdown. The underlying channel is only closed the
439    /// next time the stream is polled.
440    fn shutdown(&self);
441
442    /// Sets the server to shutdown with an epitaph. The underlying channel is
443    /// only closed the next time the stream is polled.
444    fn shutdown_with_epitaph(&self, status: fidl::Epitaph);
445
446    /// Returns true if the server has received the `PEER_CLOSED` signal.
447    fn is_closed(&self) -> bool;
448
449    /// Returns a future that completes when the server receives the
450    /// `PEER_CLOSED` signal.
451    fn on_closed(&self) -> crate::OnFDomainSignals;
452}
453
454/// A type associated with a particular two-way FIDL method, used by servers to
455/// send a response to the client.
456pub trait Responder {
457    /// The control handle for this protocol.
458    type ControlHandle: ControlHandle;
459
460    /// Returns the `ControlHandle` for this protocol.
461    fn control_handle(&self) -> &Self::ControlHandle;
462
463    /// Drops the responder without setting the channel to shutdown.
464    ///
465    /// This method shouldn't normally be used. Instead, send a response to
466    /// prevent the channel from shutting down.
467    fn drop_without_shutdown(self);
468}
469
470/// The Request type associated with a Marker.
471pub type Request<Marker> = <<Marker as ProtocolMarker>::RequestStream as futures::TryStream>::Ok;
472
473/// The `Client` end of a FIDL connection.
474#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
475pub struct ClientEnd<T: ProtocolMarker> {
476    inner: Channel,
477    phantom: PhantomData<T>,
478}
479
480impl<T: ProtocolMarker> ClientEnd<T> {
481    /// Create a new client from the provided channel.
482    pub fn new(inner: Channel) -> Self {
483        ClientEnd { inner, phantom: PhantomData }
484    }
485
486    /// Get a reference to the underlying channel
487    pub fn channel(&self) -> &Channel {
488        &self.inner
489    }
490
491    /// Extract the underlying channel.
492    pub fn into_channel(self) -> Channel {
493        self.inner
494    }
495
496    /// Create an invalid client end.
497    pub fn invalid() -> Self {
498        ClientEnd { inner: Channel::invalid(), phantom: PhantomData }
499    }
500
501    /// Check whether this handle is valid.
502    pub fn is_invalid(&self) -> bool {
503        self.inner.is_invalid()
504    }
505}
506
507impl<'c, T: ProtocolMarker> ClientEnd<T> {
508    /// Convert the `ClientEnd` into a `Proxy` through which FIDL calls may be made.
509    pub fn into_proxy(self) -> T::Proxy {
510        T::Proxy::from_channel(self.inner)
511    }
512}
513
514impl<T: ProtocolMarker> From<ClientEnd<T>> for Handle {
515    fn from(client: ClientEnd<T>) -> Handle {
516        client.into_channel().into()
517    }
518}
519
520impl<T: ProtocolMarker> From<Handle> for ClientEnd<T> {
521    fn from(handle: Handle) -> Self {
522        ClientEnd { inner: handle.into(), phantom: PhantomData }
523    }
524}
525
526impl<T: ProtocolMarker> From<Channel> for ClientEnd<T> {
527    fn from(chan: Channel) -> Self {
528        ClientEnd { inner: chan, phantom: PhantomData }
529    }
530}
531
532impl<T: ProtocolMarker> AsHandleRef for ClientEnd<T> {
533    fn as_handle_ref(&self) -> crate::HandleRef<'_> {
534        AsHandleRef::as_handle_ref(&self.inner)
535    }
536
537    fn object_type() -> fidl::ObjectType {
538        <Channel as AsHandleRef>::object_type()
539    }
540}
541
542impl<T: ProtocolMarker> HandleBased for ClientEnd<T> {
543    fn close(self) -> impl Future<Output = Result<(), Error>> {
544        let h = <Self as Into<Handle>>::into(self);
545        Handle::close(h)
546    }
547
548    fn duplicate_handle(&self, rights: fidl::Rights) -> impl Future<Output = Result<Self, Error>> {
549        let fut = self.as_handle_ref().duplicate(rights);
550        async move { fut.await.map(|handle| Self::from(handle)) }
551    }
552
553    fn replace_handle(self, rights: fidl::Rights) -> impl Future<Output = Result<Self, Error>> {
554        let h = <Self as Into<Handle>>::into(self);
555        async move { h.replace(rights).await.map(|handle| Self::from(handle)) }
556    }
557
558    fn into_handle(self) -> Handle {
559        self.into()
560    }
561
562    fn from_handle(handle: Handle) -> Self {
563        Self::from(handle)
564    }
565
566    fn into_handle_based<H: HandleBased>(self) -> H {
567        H::from_handle(self.into_handle())
568    }
569
570    fn from_handle_based<H: HandleBased>(h: H) -> Self {
571        Self::from_handle(h.into_handle())
572    }
573
574    fn invalidate(&mut self) {
575        self.inner.invalidate();
576    }
577}
578
579/// The `Server` end of a FIDL connection.
580#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
581pub struct ServerEnd<T: ProtocolMarker> {
582    inner: Channel,
583    phantom: PhantomData<T>,
584}
585
586impl<T: ProtocolMarker> ServerEnd<T> {
587    /// Create a new `ServerEnd` from the provided channel.
588    pub fn new(inner: Channel) -> ServerEnd<T> {
589        ServerEnd { inner, phantom: PhantomData }
590    }
591
592    /// Get a reference to the underlying channel
593    pub fn channel(&self) -> &Channel {
594        &self.inner
595    }
596
597    /// Extract the inner channel.
598    pub fn into_channel(self) -> Channel {
599        self.inner
600    }
601
602    /// Create a stream of requests off of the channel.
603    pub fn into_stream(self) -> T::RequestStream
604    where
605        T: ProtocolMarker,
606    {
607        T::RequestStream::from_channel(self.inner)
608    }
609
610    /// Create a stream of requests and an event-sending handle
611    /// from the channel.
612    pub fn into_stream_and_control_handle(
613        self,
614    ) -> (T::RequestStream, <T::RequestStream as RequestStream>::ControlHandle)
615    where
616        T: ProtocolMarker,
617    {
618        let stream = self.into_stream();
619        let control_handle = stream.control_handle();
620        (stream, control_handle)
621    }
622
623    /// Writes an epitaph into the underlying channel before closing it.
624    pub fn close_with_epitaph(
625        self,
626        status: impl Into<Result<(), fidl::Status>>,
627    ) -> Result<(), fidl::Error> {
628        self.inner.close_with_epitaph(status)
629    }
630
631    /// Create an invalid server end.
632    pub fn invalid() -> Self {
633        ServerEnd { inner: Channel::invalid(), phantom: PhantomData }
634    }
635
636    /// Check whether this handle is valid.
637    pub fn is_invalid(&self) -> bool {
638        self.inner.is_invalid()
639    }
640}
641
642impl<T: ProtocolMarker> From<ServerEnd<T>> for Handle {
643    fn from(server: ServerEnd<T>) -> Handle {
644        server.into_channel().into()
645    }
646}
647
648impl<T: ProtocolMarker> From<Handle> for ServerEnd<T> {
649    fn from(handle: Handle) -> Self {
650        ServerEnd { inner: handle.into(), phantom: PhantomData }
651    }
652}
653
654impl<T: ProtocolMarker> From<Channel> for ServerEnd<T> {
655    fn from(chan: Channel) -> Self {
656        ServerEnd { inner: chan, phantom: PhantomData }
657    }
658}
659
660impl<T: ProtocolMarker> AsHandleRef for ServerEnd<T> {
661    fn as_handle_ref(&self) -> crate::HandleRef<'_> {
662        AsHandleRef::as_handle_ref(&self.inner)
663    }
664
665    fn object_type() -> fidl::ObjectType {
666        <Channel as AsHandleRef>::object_type()
667    }
668}
669
670impl<T: ProtocolMarker> HandleBased for ServerEnd<T> {
671    fn close(self) -> impl Future<Output = Result<(), Error>> {
672        let h = <Self as Into<Handle>>::into(self);
673        Handle::close(h)
674    }
675
676    fn duplicate_handle(&self, rights: fidl::Rights) -> impl Future<Output = Result<Self, Error>> {
677        let fut = self.as_handle_ref().duplicate(rights);
678        async move { fut.await.map(|handle| Self::from(handle)) }
679    }
680
681    fn replace_handle(self, rights: fidl::Rights) -> impl Future<Output = Result<Self, Error>> {
682        let h = <Self as Into<Handle>>::into(self);
683        async move { h.replace(rights).await.map(|handle| Self::from(handle)) }
684    }
685
686    fn into_handle(self) -> Handle {
687        self.into()
688    }
689
690    fn from_handle(handle: Handle) -> Self {
691        Self::from(handle)
692    }
693
694    fn into_handle_based<H: HandleBased>(self) -> H {
695        H::from_handle(self.into_handle())
696    }
697
698    fn from_handle_based<H: HandleBased>(h: H) -> Self {
699        Self::from_handle(h.into_handle())
700    }
701
702    fn invalidate(&mut self) {
703        self.inner.invalidate();
704    }
705}