fidl_fuchsia_time_test/
fidl_fuchsia_time_test.rs

1// WARNING: This file is machine generated by fidlgen.
2
3#![warn(clippy::all)]
4#![allow(unused_parens, unused_mut, unused_imports, nonstandard_style)]
5
6use bitflags::bitflags;
7use fidl::client::QueryResponseFut;
8use fidl::encoding::{MessageBufFor, ProxyChannelBox, ResourceDialect};
9use fidl::endpoints::{ControlHandle as _, Responder as _};
10use futures::future::{self, MaybeDone, TryFutureExt};
11use zx_status;
12
13/// The error type returned from the methods of the [RTC] protocol.
14#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
15pub enum Error {
16    /// Something unspecified went wrong. Check the Timekeeper component logs
17    /// for possible clues.
18    ///
19    /// If more specific error messages are needed, extend the [Error] enum.
20    Internal,
21    #[doc(hidden)]
22    __SourceBreaking { unknown_ordinal: i32 },
23}
24
25/// Pattern that matches an unknown `Error` member.
26#[macro_export]
27macro_rules! ErrorUnknown {
28    () => {
29        _
30    };
31}
32
33impl Error {
34    #[inline]
35    pub fn from_primitive(prim: i32) -> Option<Self> {
36        match prim {
37            1 => Some(Self::Internal),
38            _ => None,
39        }
40    }
41
42    #[inline]
43    pub fn from_primitive_allow_unknown(prim: i32) -> Self {
44        match prim {
45            1 => Self::Internal,
46            unknown_ordinal => Self::__SourceBreaking { unknown_ordinal },
47        }
48    }
49
50    #[inline]
51    pub fn unknown() -> Self {
52        Self::__SourceBreaking { unknown_ordinal: 0x7fffffff }
53    }
54
55    #[inline]
56    pub const fn into_primitive(self) -> i32 {
57        match self {
58            Self::Internal => 1,
59            Self::__SourceBreaking { unknown_ordinal } => unknown_ordinal,
60        }
61    }
62
63    #[inline]
64    pub fn is_unknown(&self) -> bool {
65        match self {
66            Self::__SourceBreaking { unknown_ordinal: _ } => true,
67            _ => false,
68        }
69    }
70}
71
72#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
73pub struct RtcMarker;
74
75impl fidl::endpoints::ProtocolMarker for RtcMarker {
76    type Proxy = RtcProxy;
77    type RequestStream = RtcRequestStream;
78    #[cfg(target_os = "fuchsia")]
79    type SynchronousProxy = RtcSynchronousProxy;
80
81    const DEBUG_NAME: &'static str = "fuchsia.time.test.Rtc";
82}
83impl fidl::endpoints::DiscoverableProtocolMarker for RtcMarker {}
84pub type RtcPersistentDisableResult = Result<(), Error>;
85pub type RtcPersistentEnableResult = Result<(), Error>;
86
87pub trait RtcProxyInterface: Send + Sync {
88    type PersistentDisableResponseFut: std::future::Future<Output = Result<RtcPersistentDisableResult, fidl::Error>>
89        + Send;
90    fn r#persistent_disable(&self) -> Self::PersistentDisableResponseFut;
91    type PersistentEnableResponseFut: std::future::Future<Output = Result<RtcPersistentEnableResult, fidl::Error>>
92        + Send;
93    fn r#persistent_enable(&self) -> Self::PersistentEnableResponseFut;
94}
95#[derive(Debug)]
96#[cfg(target_os = "fuchsia")]
97pub struct RtcSynchronousProxy {
98    client: fidl::client::sync::Client,
99}
100
101#[cfg(target_os = "fuchsia")]
102impl fidl::endpoints::SynchronousProxy for RtcSynchronousProxy {
103    type Proxy = RtcProxy;
104    type Protocol = RtcMarker;
105
106    fn from_channel(inner: fidl::Channel) -> Self {
107        Self::new(inner)
108    }
109
110    fn into_channel(self) -> fidl::Channel {
111        self.client.into_channel()
112    }
113
114    fn as_channel(&self) -> &fidl::Channel {
115        self.client.as_channel()
116    }
117}
118
119#[cfg(target_os = "fuchsia")]
120impl RtcSynchronousProxy {
121    pub fn new(channel: fidl::Channel) -> Self {
122        let protocol_name = <RtcMarker as fidl::endpoints::ProtocolMarker>::DEBUG_NAME;
123        Self { client: fidl::client::sync::Client::new(channel, protocol_name) }
124    }
125
126    pub fn into_channel(self) -> fidl::Channel {
127        self.client.into_channel()
128    }
129
130    /// Waits until an event arrives and returns it. It is safe for other
131    /// threads to make concurrent requests while waiting for an event.
132    pub fn wait_for_event(&self, deadline: zx::MonotonicInstant) -> Result<RtcEvent, fidl::Error> {
133        RtcEvent::decode(self.client.wait_for_event(deadline)?)
134    }
135
136    /// Call [PersistentDisable] to instruct Timekeeper not to update the RTC with
137    /// the latest UTC clock estimate. Once a reply is received, the Timekeeper
138    /// will not update the RTC.
139    ///
140    /// This is useful in tests that exercise the RTC and must therefore write
141    /// to it exclusively, possibly entering a race with Timekeeper's own
142    /// RTC updates.
143    ///
144    /// NOTE: The setting persists across reboots, due to the testing
145    /// persistence requirements. Implementations should have a way to
146    /// limit the number of reboots for which this setting takes effect. This
147    /// is to avoid a lasting behavior change resulting from problems in the
148    /// test fixture.
149    pub fn r#persistent_disable(
150        &self,
151        ___deadline: zx::MonotonicInstant,
152    ) -> Result<RtcPersistentDisableResult, fidl::Error> {
153        let _response = self.client.send_query::<
154            fidl::encoding::EmptyPayload,
155            fidl::encoding::ResultType<fidl::encoding::EmptyStruct, Error>,
156        >(
157            (),
158            0x5773843d951f61c4,
159            fidl::encoding::DynamicFlags::empty(),
160            ___deadline,
161        )?;
162        Ok(_response.map(|x| x))
163    }
164
165    /// Undoes the effects of [PersistentDisable].
166    ///
167    /// The test fixture should always attempt to call this method, and have it
168    /// succeed. See also the `NOTE` section on [PersistentDisable].
169    pub fn r#persistent_enable(
170        &self,
171        ___deadline: zx::MonotonicInstant,
172    ) -> Result<RtcPersistentEnableResult, fidl::Error> {
173        let _response = self.client.send_query::<
174            fidl::encoding::EmptyPayload,
175            fidl::encoding::ResultType<fidl::encoding::EmptyStruct, Error>,
176        >(
177            (),
178            0x6fca18e78537c228,
179            fidl::encoding::DynamicFlags::empty(),
180            ___deadline,
181        )?;
182        Ok(_response.map(|x| x))
183    }
184}
185
186#[derive(Debug, Clone)]
187pub struct RtcProxy {
188    client: fidl::client::Client<fidl::encoding::DefaultFuchsiaResourceDialect>,
189}
190
191impl fidl::endpoints::Proxy for RtcProxy {
192    type Protocol = RtcMarker;
193
194    fn from_channel(inner: ::fidl::AsyncChannel) -> Self {
195        Self::new(inner)
196    }
197
198    fn into_channel(self) -> Result<::fidl::AsyncChannel, Self> {
199        self.client.into_channel().map_err(|client| Self { client })
200    }
201
202    fn as_channel(&self) -> &::fidl::AsyncChannel {
203        self.client.as_channel()
204    }
205}
206
207impl RtcProxy {
208    /// Create a new Proxy for fuchsia.time.test/Rtc.
209    pub fn new(channel: ::fidl::AsyncChannel) -> Self {
210        let protocol_name = <RtcMarker as fidl::endpoints::ProtocolMarker>::DEBUG_NAME;
211        Self { client: fidl::client::Client::new(channel, protocol_name) }
212    }
213
214    /// Get a Stream of events from the remote end of the protocol.
215    ///
216    /// # Panics
217    ///
218    /// Panics if the event stream was already taken.
219    pub fn take_event_stream(&self) -> RtcEventStream {
220        RtcEventStream { event_receiver: self.client.take_event_receiver() }
221    }
222
223    /// Call [PersistentDisable] to instruct Timekeeper not to update the RTC with
224    /// the latest UTC clock estimate. Once a reply is received, the Timekeeper
225    /// will not update the RTC.
226    ///
227    /// This is useful in tests that exercise the RTC and must therefore write
228    /// to it exclusively, possibly entering a race with Timekeeper's own
229    /// RTC updates.
230    ///
231    /// NOTE: The setting persists across reboots, due to the testing
232    /// persistence requirements. Implementations should have a way to
233    /// limit the number of reboots for which this setting takes effect. This
234    /// is to avoid a lasting behavior change resulting from problems in the
235    /// test fixture.
236    pub fn r#persistent_disable(
237        &self,
238    ) -> fidl::client::QueryResponseFut<
239        RtcPersistentDisableResult,
240        fidl::encoding::DefaultFuchsiaResourceDialect,
241    > {
242        RtcProxyInterface::r#persistent_disable(self)
243    }
244
245    /// Undoes the effects of [PersistentDisable].
246    ///
247    /// The test fixture should always attempt to call this method, and have it
248    /// succeed. See also the `NOTE` section on [PersistentDisable].
249    pub fn r#persistent_enable(
250        &self,
251    ) -> fidl::client::QueryResponseFut<
252        RtcPersistentEnableResult,
253        fidl::encoding::DefaultFuchsiaResourceDialect,
254    > {
255        RtcProxyInterface::r#persistent_enable(self)
256    }
257}
258
259impl RtcProxyInterface for RtcProxy {
260    type PersistentDisableResponseFut = fidl::client::QueryResponseFut<
261        RtcPersistentDisableResult,
262        fidl::encoding::DefaultFuchsiaResourceDialect,
263    >;
264    fn r#persistent_disable(&self) -> Self::PersistentDisableResponseFut {
265        fn _decode(
266            mut _buf: Result<<fidl::encoding::DefaultFuchsiaResourceDialect as fidl::encoding::ResourceDialect>::MessageBufEtc, fidl::Error>,
267        ) -> Result<RtcPersistentDisableResult, fidl::Error> {
268            let _response = fidl::client::decode_transaction_body::<
269                fidl::encoding::ResultType<fidl::encoding::EmptyStruct, Error>,
270                fidl::encoding::DefaultFuchsiaResourceDialect,
271                0x5773843d951f61c4,
272            >(_buf?)?;
273            Ok(_response.map(|x| x))
274        }
275        self.client
276            .send_query_and_decode::<fidl::encoding::EmptyPayload, RtcPersistentDisableResult>(
277                (),
278                0x5773843d951f61c4,
279                fidl::encoding::DynamicFlags::empty(),
280                _decode,
281            )
282    }
283
284    type PersistentEnableResponseFut = fidl::client::QueryResponseFut<
285        RtcPersistentEnableResult,
286        fidl::encoding::DefaultFuchsiaResourceDialect,
287    >;
288    fn r#persistent_enable(&self) -> Self::PersistentEnableResponseFut {
289        fn _decode(
290            mut _buf: Result<<fidl::encoding::DefaultFuchsiaResourceDialect as fidl::encoding::ResourceDialect>::MessageBufEtc, fidl::Error>,
291        ) -> Result<RtcPersistentEnableResult, fidl::Error> {
292            let _response = fidl::client::decode_transaction_body::<
293                fidl::encoding::ResultType<fidl::encoding::EmptyStruct, Error>,
294                fidl::encoding::DefaultFuchsiaResourceDialect,
295                0x6fca18e78537c228,
296            >(_buf?)?;
297            Ok(_response.map(|x| x))
298        }
299        self.client
300            .send_query_and_decode::<fidl::encoding::EmptyPayload, RtcPersistentEnableResult>(
301                (),
302                0x6fca18e78537c228,
303                fidl::encoding::DynamicFlags::empty(),
304                _decode,
305            )
306    }
307}
308
309pub struct RtcEventStream {
310    event_receiver: fidl::client::EventReceiver<fidl::encoding::DefaultFuchsiaResourceDialect>,
311}
312
313impl std::marker::Unpin for RtcEventStream {}
314
315impl futures::stream::FusedStream for RtcEventStream {
316    fn is_terminated(&self) -> bool {
317        self.event_receiver.is_terminated()
318    }
319}
320
321impl futures::Stream for RtcEventStream {
322    type Item = Result<RtcEvent, fidl::Error>;
323
324    fn poll_next(
325        mut self: std::pin::Pin<&mut Self>,
326        cx: &mut std::task::Context<'_>,
327    ) -> std::task::Poll<Option<Self::Item>> {
328        match futures::ready!(futures::stream::StreamExt::poll_next_unpin(
329            &mut self.event_receiver,
330            cx
331        )?) {
332            Some(buf) => std::task::Poll::Ready(Some(RtcEvent::decode(buf))),
333            None => std::task::Poll::Ready(None),
334        }
335    }
336}
337
338#[derive(Debug)]
339pub enum RtcEvent {}
340
341impl RtcEvent {
342    /// Decodes a message buffer as a [`RtcEvent`].
343    fn decode(
344        mut buf: <fidl::encoding::DefaultFuchsiaResourceDialect as fidl::encoding::ResourceDialect>::MessageBufEtc,
345    ) -> Result<RtcEvent, fidl::Error> {
346        let (bytes, _handles) = buf.split_mut();
347        let (tx_header, _body_bytes) = fidl::encoding::decode_transaction_header(bytes)?;
348        debug_assert_eq!(tx_header.tx_id, 0);
349        match tx_header.ordinal {
350            _ => Err(fidl::Error::UnknownOrdinal {
351                ordinal: tx_header.ordinal,
352                protocol_name: <RtcMarker as fidl::endpoints::ProtocolMarker>::DEBUG_NAME,
353            }),
354        }
355    }
356}
357
358/// A Stream of incoming requests for fuchsia.time.test/Rtc.
359pub struct RtcRequestStream {
360    inner: std::sync::Arc<fidl::ServeInner<fidl::encoding::DefaultFuchsiaResourceDialect>>,
361    is_terminated: bool,
362}
363
364impl std::marker::Unpin for RtcRequestStream {}
365
366impl futures::stream::FusedStream for RtcRequestStream {
367    fn is_terminated(&self) -> bool {
368        self.is_terminated
369    }
370}
371
372impl fidl::endpoints::RequestStream for RtcRequestStream {
373    type Protocol = RtcMarker;
374    type ControlHandle = RtcControlHandle;
375
376    fn from_channel(channel: ::fidl::AsyncChannel) -> Self {
377        Self { inner: std::sync::Arc::new(fidl::ServeInner::new(channel)), is_terminated: false }
378    }
379
380    fn control_handle(&self) -> Self::ControlHandle {
381        RtcControlHandle { inner: self.inner.clone() }
382    }
383
384    fn into_inner(
385        self,
386    ) -> (::std::sync::Arc<fidl::ServeInner<fidl::encoding::DefaultFuchsiaResourceDialect>>, bool)
387    {
388        (self.inner, self.is_terminated)
389    }
390
391    fn from_inner(
392        inner: std::sync::Arc<fidl::ServeInner<fidl::encoding::DefaultFuchsiaResourceDialect>>,
393        is_terminated: bool,
394    ) -> Self {
395        Self { inner, is_terminated }
396    }
397}
398
399impl futures::Stream for RtcRequestStream {
400    type Item = Result<RtcRequest, fidl::Error>;
401
402    fn poll_next(
403        mut self: std::pin::Pin<&mut Self>,
404        cx: &mut std::task::Context<'_>,
405    ) -> std::task::Poll<Option<Self::Item>> {
406        let this = &mut *self;
407        if this.inner.check_shutdown(cx) {
408            this.is_terminated = true;
409            return std::task::Poll::Ready(None);
410        }
411        if this.is_terminated {
412            panic!("polled RtcRequestStream after completion");
413        }
414        fidl::encoding::with_tls_decode_buf::<_, fidl::encoding::DefaultFuchsiaResourceDialect>(
415            |bytes, handles| {
416                match this.inner.channel().read_etc(cx, bytes, handles) {
417                    std::task::Poll::Ready(Ok(())) => {}
418                    std::task::Poll::Pending => return std::task::Poll::Pending,
419                    std::task::Poll::Ready(Err(zx_status::Status::PEER_CLOSED)) => {
420                        this.is_terminated = true;
421                        return std::task::Poll::Ready(None);
422                    }
423                    std::task::Poll::Ready(Err(e)) => {
424                        return std::task::Poll::Ready(Some(Err(fidl::Error::ServerRequestRead(
425                            e.into(),
426                        ))))
427                    }
428                }
429
430                // A message has been received from the channel
431                let (header, _body_bytes) = fidl::encoding::decode_transaction_header(bytes)?;
432
433                std::task::Poll::Ready(Some(match header.ordinal {
434                    0x5773843d951f61c4 => {
435                        header.validate_request_tx_id(fidl::MethodType::TwoWay)?;
436                        let mut req = fidl::new_empty!(
437                            fidl::encoding::EmptyPayload,
438                            fidl::encoding::DefaultFuchsiaResourceDialect
439                        );
440                        fidl::encoding::Decoder::<fidl::encoding::DefaultFuchsiaResourceDialect>::decode_into::<fidl::encoding::EmptyPayload>(&header, _body_bytes, handles, &mut req)?;
441                        let control_handle = RtcControlHandle { inner: this.inner.clone() };
442                        Ok(RtcRequest::PersistentDisable {
443                            responder: RtcPersistentDisableResponder {
444                                control_handle: std::mem::ManuallyDrop::new(control_handle),
445                                tx_id: header.tx_id,
446                            },
447                        })
448                    }
449                    0x6fca18e78537c228 => {
450                        header.validate_request_tx_id(fidl::MethodType::TwoWay)?;
451                        let mut req = fidl::new_empty!(
452                            fidl::encoding::EmptyPayload,
453                            fidl::encoding::DefaultFuchsiaResourceDialect
454                        );
455                        fidl::encoding::Decoder::<fidl::encoding::DefaultFuchsiaResourceDialect>::decode_into::<fidl::encoding::EmptyPayload>(&header, _body_bytes, handles, &mut req)?;
456                        let control_handle = RtcControlHandle { inner: this.inner.clone() };
457                        Ok(RtcRequest::PersistentEnable {
458                            responder: RtcPersistentEnableResponder {
459                                control_handle: std::mem::ManuallyDrop::new(control_handle),
460                                tx_id: header.tx_id,
461                            },
462                        })
463                    }
464                    _ => Err(fidl::Error::UnknownOrdinal {
465                        ordinal: header.ordinal,
466                        protocol_name: <RtcMarker as fidl::endpoints::ProtocolMarker>::DEBUG_NAME,
467                    }),
468                }))
469            },
470        )
471    }
472}
473
474/// Connect to the RTC protocol to send messages to Timekeeper instructing it
475/// to modify its default behavior for testing purposes.
476///
477/// On devices that do not have a real time clock, this protocol is not useful.
478#[derive(Debug)]
479pub enum RtcRequest {
480    /// Call [PersistentDisable] to instruct Timekeeper not to update the RTC with
481    /// the latest UTC clock estimate. Once a reply is received, the Timekeeper
482    /// will not update the RTC.
483    ///
484    /// This is useful in tests that exercise the RTC and must therefore write
485    /// to it exclusively, possibly entering a race with Timekeeper's own
486    /// RTC updates.
487    ///
488    /// NOTE: The setting persists across reboots, due to the testing
489    /// persistence requirements. Implementations should have a way to
490    /// limit the number of reboots for which this setting takes effect. This
491    /// is to avoid a lasting behavior change resulting from problems in the
492    /// test fixture.
493    PersistentDisable { responder: RtcPersistentDisableResponder },
494    /// Undoes the effects of [PersistentDisable].
495    ///
496    /// The test fixture should always attempt to call this method, and have it
497    /// succeed. See also the `NOTE` section on [PersistentDisable].
498    PersistentEnable { responder: RtcPersistentEnableResponder },
499}
500
501impl RtcRequest {
502    #[allow(irrefutable_let_patterns)]
503    pub fn into_persistent_disable(self) -> Option<(RtcPersistentDisableResponder)> {
504        if let RtcRequest::PersistentDisable { responder } = self {
505            Some((responder))
506        } else {
507            None
508        }
509    }
510
511    #[allow(irrefutable_let_patterns)]
512    pub fn into_persistent_enable(self) -> Option<(RtcPersistentEnableResponder)> {
513        if let RtcRequest::PersistentEnable { responder } = self {
514            Some((responder))
515        } else {
516            None
517        }
518    }
519
520    /// Name of the method defined in FIDL
521    pub fn method_name(&self) -> &'static str {
522        match *self {
523            RtcRequest::PersistentDisable { .. } => "persistent_disable",
524            RtcRequest::PersistentEnable { .. } => "persistent_enable",
525        }
526    }
527}
528
529#[derive(Debug, Clone)]
530pub struct RtcControlHandle {
531    inner: std::sync::Arc<fidl::ServeInner<fidl::encoding::DefaultFuchsiaResourceDialect>>,
532}
533
534impl fidl::endpoints::ControlHandle for RtcControlHandle {
535    fn shutdown(&self) {
536        self.inner.shutdown()
537    }
538    fn shutdown_with_epitaph(&self, status: zx_status::Status) {
539        self.inner.shutdown_with_epitaph(status)
540    }
541
542    fn is_closed(&self) -> bool {
543        self.inner.channel().is_closed()
544    }
545    fn on_closed(&self) -> fidl::OnSignalsRef<'_> {
546        self.inner.channel().on_closed()
547    }
548
549    #[cfg(target_os = "fuchsia")]
550    fn signal_peer(
551        &self,
552        clear_mask: zx::Signals,
553        set_mask: zx::Signals,
554    ) -> Result<(), zx_status::Status> {
555        use fidl::Peered;
556        self.inner.channel().signal_peer(clear_mask, set_mask)
557    }
558}
559
560impl RtcControlHandle {}
561
562#[must_use = "FIDL methods require a response to be sent"]
563#[derive(Debug)]
564pub struct RtcPersistentDisableResponder {
565    control_handle: std::mem::ManuallyDrop<RtcControlHandle>,
566    tx_id: u32,
567}
568
569/// Set the the channel to be shutdown (see [`RtcControlHandle::shutdown`])
570/// if the responder is dropped without sending a response, so that the client
571/// doesn't hang. To prevent this behavior, call `drop_without_shutdown`.
572impl std::ops::Drop for RtcPersistentDisableResponder {
573    fn drop(&mut self) {
574        self.control_handle.shutdown();
575        // Safety: drops once, never accessed again
576        unsafe { std::mem::ManuallyDrop::drop(&mut self.control_handle) };
577    }
578}
579
580impl fidl::endpoints::Responder for RtcPersistentDisableResponder {
581    type ControlHandle = RtcControlHandle;
582
583    fn control_handle(&self) -> &RtcControlHandle {
584        &self.control_handle
585    }
586
587    fn drop_without_shutdown(mut self) {
588        // Safety: drops once, never accessed again due to mem::forget
589        unsafe { std::mem::ManuallyDrop::drop(&mut self.control_handle) };
590        // Prevent Drop from running (which would shut down the channel)
591        std::mem::forget(self);
592    }
593}
594
595impl RtcPersistentDisableResponder {
596    /// Sends a response to the FIDL transaction.
597    ///
598    /// Sets the channel to shutdown if an error occurs.
599    pub fn send(self, mut result: Result<(), Error>) -> Result<(), fidl::Error> {
600        let _result = self.send_raw(result);
601        if _result.is_err() {
602            self.control_handle.shutdown();
603        }
604        self.drop_without_shutdown();
605        _result
606    }
607
608    /// Similar to "send" but does not shutdown the channel if an error occurs.
609    pub fn send_no_shutdown_on_err(self, mut result: Result<(), Error>) -> Result<(), fidl::Error> {
610        let _result = self.send_raw(result);
611        self.drop_without_shutdown();
612        _result
613    }
614
615    fn send_raw(&self, mut result: Result<(), Error>) -> Result<(), fidl::Error> {
616        self.control_handle
617            .inner
618            .send::<fidl::encoding::ResultType<fidl::encoding::EmptyStruct, Error>>(
619                result,
620                self.tx_id,
621                0x5773843d951f61c4,
622                fidl::encoding::DynamicFlags::empty(),
623            )
624    }
625}
626
627#[must_use = "FIDL methods require a response to be sent"]
628#[derive(Debug)]
629pub struct RtcPersistentEnableResponder {
630    control_handle: std::mem::ManuallyDrop<RtcControlHandle>,
631    tx_id: u32,
632}
633
634/// Set the the channel to be shutdown (see [`RtcControlHandle::shutdown`])
635/// if the responder is dropped without sending a response, so that the client
636/// doesn't hang. To prevent this behavior, call `drop_without_shutdown`.
637impl std::ops::Drop for RtcPersistentEnableResponder {
638    fn drop(&mut self) {
639        self.control_handle.shutdown();
640        // Safety: drops once, never accessed again
641        unsafe { std::mem::ManuallyDrop::drop(&mut self.control_handle) };
642    }
643}
644
645impl fidl::endpoints::Responder for RtcPersistentEnableResponder {
646    type ControlHandle = RtcControlHandle;
647
648    fn control_handle(&self) -> &RtcControlHandle {
649        &self.control_handle
650    }
651
652    fn drop_without_shutdown(mut self) {
653        // Safety: drops once, never accessed again due to mem::forget
654        unsafe { std::mem::ManuallyDrop::drop(&mut self.control_handle) };
655        // Prevent Drop from running (which would shut down the channel)
656        std::mem::forget(self);
657    }
658}
659
660impl RtcPersistentEnableResponder {
661    /// Sends a response to the FIDL transaction.
662    ///
663    /// Sets the channel to shutdown if an error occurs.
664    pub fn send(self, mut result: Result<(), Error>) -> Result<(), fidl::Error> {
665        let _result = self.send_raw(result);
666        if _result.is_err() {
667            self.control_handle.shutdown();
668        }
669        self.drop_without_shutdown();
670        _result
671    }
672
673    /// Similar to "send" but does not shutdown the channel if an error occurs.
674    pub fn send_no_shutdown_on_err(self, mut result: Result<(), Error>) -> Result<(), fidl::Error> {
675        let _result = self.send_raw(result);
676        self.drop_without_shutdown();
677        _result
678    }
679
680    fn send_raw(&self, mut result: Result<(), Error>) -> Result<(), fidl::Error> {
681        self.control_handle
682            .inner
683            .send::<fidl::encoding::ResultType<fidl::encoding::EmptyStruct, Error>>(
684                result,
685                self.tx_id,
686                0x6fca18e78537c228,
687                fidl::encoding::DynamicFlags::empty(),
688            )
689    }
690}
691
692mod internal {
693    use super::*;
694    unsafe impl fidl::encoding::TypeMarker for Error {
695        type Owned = Self;
696
697        #[inline(always)]
698        fn inline_align(_context: fidl::encoding::Context) -> usize {
699            std::mem::align_of::<i32>()
700        }
701
702        #[inline(always)]
703        fn inline_size(_context: fidl::encoding::Context) -> usize {
704            std::mem::size_of::<i32>()
705        }
706
707        #[inline(always)]
708        fn encode_is_copy() -> bool {
709            false
710        }
711
712        #[inline(always)]
713        fn decode_is_copy() -> bool {
714            false
715        }
716    }
717
718    impl fidl::encoding::ValueTypeMarker for Error {
719        type Borrowed<'a> = Self;
720        #[inline(always)]
721        fn borrow(value: &<Self as fidl::encoding::TypeMarker>::Owned) -> Self::Borrowed<'_> {
722            *value
723        }
724    }
725
726    unsafe impl<D: fidl::encoding::ResourceDialect> fidl::encoding::Encode<Self, D> for Error {
727        #[inline]
728        unsafe fn encode(
729            self,
730            encoder: &mut fidl::encoding::Encoder<'_, D>,
731            offset: usize,
732            _depth: fidl::encoding::Depth,
733        ) -> fidl::Result<()> {
734            encoder.debug_check_bounds::<Self>(offset);
735            encoder.write_num(self.into_primitive(), offset);
736            Ok(())
737        }
738    }
739
740    impl<D: fidl::encoding::ResourceDialect> fidl::encoding::Decode<Self, D> for Error {
741        #[inline(always)]
742        fn new_empty() -> Self {
743            Self::unknown()
744        }
745
746        #[inline]
747        unsafe fn decode(
748            &mut self,
749            decoder: &mut fidl::encoding::Decoder<'_, D>,
750            offset: usize,
751            _depth: fidl::encoding::Depth,
752        ) -> fidl::Result<()> {
753            decoder.debug_check_bounds::<Self>(offset);
754            let prim = decoder.read_num::<i32>(offset);
755
756            *self = Self::from_primitive_allow_unknown(prim);
757            Ok(())
758        }
759    }
760}