wlan_fidl_ext/
responder_ext.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::{SendResultExt, TryUnpack};
6use anyhow::format_err;
7use fidl_fuchsia_wlan_softmac as fidl_softmac;
8
9/// Defines an abstract ResponderExt trait usually implemented using the impl_responder_ext!() macro.
10pub trait ResponderExt {
11    type Response<'a>;
12    const REQUEST_NAME: &'static str;
13
14    fn send(self, response: Self::Response<'_>) -> Result<(), fidl::Error>;
15
16    /// Returns an success value containing all unpacked fields and the responder, or an error value
17    /// if any of the values in `fields` is missing.
18    ///
19    /// The last argument is a closure which will compute a `Self::Response`.  If any field is
20    /// missing a value, then this function will return an error and send the computed
21    /// `Self::Response`.
22    ///
23    /// Example Usage:
24    ///
25    /// ```
26    ///   enum Error {
27    ///       UnableToStart,
28    ///   }
29    ///   let ((status, id), responder) = responder.unpack_fields_or_else_send(
30    ///       (payload.status.with_name("status"), payload.id.with_name("id")),
31    ///       |e| (e.context(format_err!("Unable to start.")), Error::UnableToStart),
32    ///   )?;
33    /// ```
34    fn unpack_fields_or_else_send<'a, T, F>(
35        self,
36        fields: T,
37        f: F,
38    ) -> Result<(T::Unpacked, Self), anyhow::Error>
39    where
40        T: TryUnpack<Error = anyhow::Error>,
41        F: FnOnce() -> Self::Response<'a>,
42        Self: Sized,
43    {
44        match fields.try_unpack() {
45            Ok(values) => Ok((values, self)),
46            Err(error) => {
47                let error = error
48                    .context(format_err!("Missing required field(s) in {}.", Self::REQUEST_NAME));
49                match self.send(f()).format_send_err() {
50                    Ok(_) => Err(error),
51                    Err(send_error) => Err(send_error.context(error)),
52                }
53            }
54        }
55    }
56
57    fn unpack_fields_or_respond<T>(self, fields: T) -> Result<(T::Unpacked, Self), anyhow::Error>
58    where
59        T: TryUnpack<Error = anyhow::Error>,
60        Self: for<'a> ResponderExt<Response<'a> = ()> + Sized,
61    {
62        self.unpack_fields_or_else_send(fields, || ())
63    }
64}
65
66impl ResponderExt for fidl_fuchsia_wlan_device_service::DeviceMonitorCreateIfaceResponder {
67    type Response<'a> = Result<
68        &'a fidl_fuchsia_wlan_device_service::DeviceMonitorCreateIfaceResponse,
69        fidl_fuchsia_wlan_device_service::DeviceMonitorError,
70    >;
71    const REQUEST_NAME: &'static str =
72        stringify!(fidl_fuchsia_wlan_device_service::DeviceMonitorCreateIfaceRequest);
73
74    fn send(self, response: Self::Response<'_>) -> Result<(), fidl::Error> {
75        Self::send(self, response)
76    }
77}
78
79impl ResponderExt for fidl_softmac::WlanSoftmacIfcBridgeNotifyScanCompleteResponder {
80    type Response<'a> = ();
81    const REQUEST_NAME: &'static str =
82        stringify!(fidl_softmac::WlanSoftmacIfcBaseNotifyScanCompleteRequest);
83
84    fn send(self, _: Self::Response<'_>) -> Result<(), fidl::Error> {
85        Self::send(self)
86    }
87}
88
89impl ResponderExt for fidl_softmac::WlanSoftmacIfcBridgeReportTxResultResponder {
90    type Response<'a> = ();
91    const REQUEST_NAME: &'static str =
92        stringify!(fidl_softmac::WlanSoftmacIfcBaseReportTxResultRequest);
93
94    fn send(self, _: Self::Response<'_>) -> Result<(), fidl::Error> {
95        Self::send(self)
96    }
97}