1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// Copyright 2024 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use crate::{SendResultExt, TryUnpack};
use anyhow::format_err;
use fidl_fuchsia_wlan_softmac as fidl_softmac;

/// Defines an abstract ResponderExt trait usually implemented using the impl_responder_ext!() macro.
pub trait ResponderExt {
    type Response;
    const REQUEST_NAME: &'static str;

    fn send(self, response: Self::Response) -> Result<(), fidl::Error>;

    /// Returns an success value containing all unpacked fields and the responder, or an error value
    /// if any of the values in `fields` is missing.
    ///
    /// The last argument is a closure which will compute a `Self::Response`.  If any field is
    /// missing a value, then this function will return an error and send the computed
    /// `Self::Response`.
    ///
    /// Example Usage:
    ///
    /// ```
    ///   enum Error {
    ///       UnableToStart,
    ///   }
    ///   let ((status, id), responder) = responder.unpack_fields_or_else_send(
    ///       (payload.status.with_name("status"), payload.id.with_name("id")),
    ///       |e| (e.context(format_err!("Unable to start.")), Error::UnableToStart),
    ///   )?;
    /// ```
    fn unpack_fields_or_else_send<T, F>(
        self,
        fields: T,
        f: F,
    ) -> Result<(T::Unpacked, Self), anyhow::Error>
    where
        T: TryUnpack<Error = anyhow::Error>,
        F: FnOnce() -> Self::Response,
        Self: Sized,
    {
        match fields.try_unpack() {
            Ok(values) => Ok((values, self)),
            Err(error) => {
                let error = error
                    .context(format_err!("Missing required field(s) in {}.", Self::REQUEST_NAME));
                match self.send(f()).format_send_err() {
                    Ok(_) => Err(error),
                    Err(send_error) => Err(send_error.context(error)),
                }
            }
        }
    }

    fn unpack_fields_or_respond<T>(self, fields: T) -> Result<(T::Unpacked, Self), anyhow::Error>
    where
        T: TryUnpack<Error = anyhow::Error>,
        Self: ResponderExt<Response = ()> + Sized,
    {
        self.unpack_fields_or_else_send(fields, || ())
    }
}

impl ResponderExt for fidl_softmac::WlanSoftmacIfcBridgeNotifyScanCompleteResponder {
    type Response = ();
    const REQUEST_NAME: &'static str =
        stringify!(fidl_softmac::WlanSoftmacIfcBaseNotifyScanCompleteRequest);

    fn send(self, _: Self::Response) -> Result<(), fidl::Error> {
        Self::send(self)
    }
}

impl ResponderExt for fidl_softmac::WlanSoftmacIfcBridgeReportTxResultResponder {
    type Response = ();
    const REQUEST_NAME: &'static str =
        stringify!(fidl_softmac::WlanSoftmacIfcBaseReportTxResultRequest);

    fn send(self, _: Self::Response) -> Result<(), fidl::Error> {
        Self::send(self)
    }
}