fidl_fuchsia_net_multicast_ext/
lib.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
5//! Extension crate for the `fuchsia.net.multicast.admin` FIDL API.
6//!
7//! This crate provides types and traits to abstract the separate IPv4 and IPv6
8//! FIDL APIs onto a single API surface that is generic over IP version.
9
10use fidl_fuchsia_net_ext::IntoExt as _;
11use fidl_fuchsia_net_multicast_admin::{self as fnet_multicast_admin, TableControllerCloseReason};
12use futures::stream::TryStream;
13use futures::{Stream, StreamExt, TryFutureExt};
14use net_types::ip::{GenericOverIp, Ip, Ipv4, Ipv6};
15
16/// A type capable of responding to FIDL requests.
17pub trait FidlResponder<R> {
18    /// Try to send the given response over this responder.
19    fn try_send(self, response: R) -> Result<(), fidl::Error>;
20}
21
22/// A FIDL ControlHandle that can send a terminal event.
23pub trait TerminalEventControlHandle<E> {
24    /// Send the given terminal event
25    fn send_terminal_event(&self, terminal_event: E) -> Result<(), fidl::Error>;
26}
27
28/// A FIDL multicast routing table controller Proxy.
29///
30/// An IP generic abstraction over
31/// [`fnet_multicast_admin::Ipv4RoutingTableControllerProxy`], and
32/// [`fnet_multicast_admin::Ipv6RoutingTableControllerProxy`].
33pub trait TableControllerProxy<I: FidlMulticastAdminIpExt> {
34    fn take_event_stream(
35        &self,
36    ) -> impl Stream<Item = Result<TableControllerCloseReason, fidl::Error>> + std::marker::Unpin;
37
38    fn add_route(
39        &self,
40        addresses: UnicastSourceAndMulticastDestination<I>,
41        route: Route,
42    ) -> impl futures::Future<Output = Result<Result<(), AddRouteError>, fidl::Error>>;
43
44    fn del_route(
45        &self,
46        addresses: UnicastSourceAndMulticastDestination<I>,
47    ) -> impl futures::Future<Output = Result<Result<(), DelRouteError>, fidl::Error>>;
48
49    fn get_route_stats(
50        &self,
51        addresses: UnicastSourceAndMulticastDestination<I>,
52    ) -> impl futures::Future<
53        Output = Result<Result<fnet_multicast_admin::RouteStats, GetRouteStatsError>, fidl::Error>,
54    >;
55
56    fn watch_routing_events(
57        &self,
58    ) -> impl futures::Future<Output = Result<WatchRoutingEventsResponse<I>, fidl::Error>>;
59}
60
61/// An IP extension providing functionality for `fuchsia_net_multicast_admin`.
62pub trait FidlMulticastAdminIpExt: Ip {
63    /// Protocol Marker for the multicast routing table controller.
64    type TableControllerMarker: fidl::endpoints::DiscoverableProtocolMarker<
65        RequestStream = Self::TableControllerRequestStream,
66        Proxy = Self::TableControllerProxy,
67    >;
68    /// Request Stream for the multicast routing table controller.
69    type TableControllerRequestStream: fidl::endpoints::RequestStream<
70        Ok: Send + Into<TableControllerRequest<Self>>,
71        ControlHandle: Send + TerminalEventControlHandle<TableControllerCloseReason>,
72        Item = Result<
73            <Self::TableControllerRequestStream as TryStream>::Ok,
74            <Self::TableControllerRequestStream as TryStream>::Error,
75        >,
76    >;
77    type TableControllerProxy: fidl::endpoints::Proxy + TableControllerProxy<Self>;
78    /// The Unicast Source and Multicast Destination address tuple.
79    type Addresses: Into<UnicastSourceAndMulticastDestination<Self>>;
80    /// A [`FidlResponder`] for multicast routing table AddRoute requests.
81    type AddRouteResponder: FidlResponder<Result<(), AddRouteError>>;
82    /// A [`FidlResponder`] for multicast routing table DelRoute requests.
83    type DelRouteResponder: FidlResponder<Result<(), DelRouteError>>;
84    /// A [`FidlResponder`] for multicast routing table GetRouteStats requests.
85    type GetRouteStatsResponder: for<'a> FidlResponder<
86        Result<&'a fnet_multicast_admin::RouteStats, GetRouteStatsError>,
87    >;
88    /// A [`FidlResponder`] for multicast routing table WatchRoutingEvents
89    /// requests.
90    type WatchRoutingEventsResponder: FidlResponder<WatchRoutingEventsResponse<Self>>;
91}
92
93impl FidlMulticastAdminIpExt for Ipv4 {
94    type TableControllerMarker = fnet_multicast_admin::Ipv4RoutingTableControllerMarker;
95    type TableControllerRequestStream =
96        fnet_multicast_admin::Ipv4RoutingTableControllerRequestStream;
97    type TableControllerProxy = fnet_multicast_admin::Ipv4RoutingTableControllerProxy;
98    type Addresses = fnet_multicast_admin::Ipv4UnicastSourceAndMulticastDestination;
99    type AddRouteResponder = fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteResponder;
100    type DelRouteResponder = fnet_multicast_admin::Ipv4RoutingTableControllerDelRouteResponder;
101    type GetRouteStatsResponder =
102        fnet_multicast_admin::Ipv4RoutingTableControllerGetRouteStatsResponder;
103    type WatchRoutingEventsResponder =
104        fnet_multicast_admin::Ipv4RoutingTableControllerWatchRoutingEventsResponder;
105}
106
107impl FidlMulticastAdminIpExt for Ipv6 {
108    type TableControllerMarker = fnet_multicast_admin::Ipv6RoutingTableControllerMarker;
109    type TableControllerRequestStream =
110        fnet_multicast_admin::Ipv6RoutingTableControllerRequestStream;
111    type TableControllerProxy = fnet_multicast_admin::Ipv6RoutingTableControllerProxy;
112    type Addresses = fnet_multicast_admin::Ipv6UnicastSourceAndMulticastDestination;
113    type AddRouteResponder = fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteResponder;
114    type DelRouteResponder = fnet_multicast_admin::Ipv6RoutingTableControllerDelRouteResponder;
115    type GetRouteStatsResponder =
116        fnet_multicast_admin::Ipv6RoutingTableControllerGetRouteStatsResponder;
117    type WatchRoutingEventsResponder =
118        fnet_multicast_admin::Ipv6RoutingTableControllerWatchRoutingEventsResponder;
119}
120
121impl TerminalEventControlHandle<TableControllerCloseReason>
122    for fnet_multicast_admin::Ipv4RoutingTableControllerControlHandle
123{
124    fn send_terminal_event(
125        &self,
126        terminal_event: TableControllerCloseReason,
127    ) -> Result<(), fidl::Error> {
128        self.send_on_close(terminal_event)
129    }
130}
131
132impl TerminalEventControlHandle<TableControllerCloseReason>
133    for fnet_multicast_admin::Ipv6RoutingTableControllerControlHandle
134{
135    fn send_terminal_event(
136        &self,
137        terminal_event: TableControllerCloseReason,
138    ) -> Result<(), fidl::Error> {
139        self.send_on_close(terminal_event)
140    }
141}
142
143impl TableControllerProxy<Ipv4> for fnet_multicast_admin::Ipv4RoutingTableControllerProxy {
144    fn take_event_stream(
145        &self,
146    ) -> impl Stream<Item = Result<TableControllerCloseReason, fidl::Error>> {
147        self.take_event_stream().map(|e| {
148            e.map(|e| match e {
149                fnet_multicast_admin::Ipv4RoutingTableControllerEvent::OnClose { error } => error,
150            })
151        })
152    }
153
154    fn add_route(
155        &self,
156        addresses: UnicastSourceAndMulticastDestination<Ipv4>,
157        route: Route,
158    ) -> impl futures::Future<Output = Result<Result<(), AddRouteError>, fidl::Error>> {
159        self.add_route(&addresses.into(), &route.into())
160            .map_ok(|inner| inner.map_err(AddRouteError::from))
161    }
162
163    fn del_route(
164        &self,
165        addresses: UnicastSourceAndMulticastDestination<Ipv4>,
166    ) -> impl futures::Future<Output = Result<Result<(), DelRouteError>, fidl::Error>> {
167        self.del_route(&addresses.into()).map_ok(|inner| inner.map_err(DelRouteError::from))
168    }
169
170    fn get_route_stats(
171        &self,
172        addresses: UnicastSourceAndMulticastDestination<Ipv4>,
173    ) -> impl futures::Future<
174        Output = Result<Result<fnet_multicast_admin::RouteStats, GetRouteStatsError>, fidl::Error>,
175    > {
176        self.get_route_stats(&addresses.into())
177            .map_ok(|inner| inner.map_err(GetRouteStatsError::from))
178    }
179
180    fn watch_routing_events(
181        &self,
182    ) -> impl futures::Future<Output = Result<WatchRoutingEventsResponse<Ipv4>, fidl::Error>> {
183        self.watch_routing_events().map_ok(|(dropped_events, addresses, input_interface, event)| {
184            WatchRoutingEventsResponse {
185                dropped_events,
186                addresses: addresses.into(),
187                input_interface,
188                event,
189            }
190        })
191    }
192}
193
194impl TableControllerProxy<Ipv6> for fnet_multicast_admin::Ipv6RoutingTableControllerProxy {
195    fn take_event_stream(
196        &self,
197    ) -> impl Stream<Item = Result<TableControllerCloseReason, fidl::Error>> {
198        self.take_event_stream().map(|e| {
199            e.map(|e| match e {
200                fnet_multicast_admin::Ipv6RoutingTableControllerEvent::OnClose { error } => error,
201            })
202        })
203    }
204
205    fn add_route(
206        &self,
207        addresses: UnicastSourceAndMulticastDestination<Ipv6>,
208        route: Route,
209    ) -> impl futures::Future<Output = Result<Result<(), AddRouteError>, fidl::Error>> {
210        self.add_route(&addresses.into(), &route.into())
211            .map_ok(|inner| inner.map_err(AddRouteError::from))
212    }
213
214    fn del_route(
215        &self,
216        addresses: UnicastSourceAndMulticastDestination<Ipv6>,
217    ) -> impl futures::Future<Output = Result<Result<(), DelRouteError>, fidl::Error>> {
218        self.del_route(&addresses.into()).map_ok(|inner| inner.map_err(DelRouteError::from))
219    }
220
221    fn get_route_stats(
222        &self,
223        addresses: UnicastSourceAndMulticastDestination<Ipv6>,
224    ) -> impl futures::Future<
225        Output = Result<Result<fnet_multicast_admin::RouteStats, GetRouteStatsError>, fidl::Error>,
226    > {
227        self.get_route_stats(&addresses.into())
228            .map_ok(|inner| inner.map_err(GetRouteStatsError::from))
229    }
230
231    fn watch_routing_events(
232        &self,
233    ) -> impl futures::Future<Output = Result<WatchRoutingEventsResponse<Ipv6>, fidl::Error>> {
234        self.watch_routing_events().map_ok(|(dropped_events, addresses, input_interface, event)| {
235            WatchRoutingEventsResponse {
236                dropped_events,
237                addresses: addresses.into(),
238                input_interface,
239                event,
240            }
241        })
242    }
243}
244
245/// An IP generic version of
246/// [`fnet_multicast_admin::Ipv4RoutingTableControllerRequest`] and
247/// [`fnet_multicast_admin::Ipv6RoutingTableControllerRequest`].
248#[derive(Debug)]
249pub enum TableControllerRequest<I: FidlMulticastAdminIpExt> {
250    AddRoute {
251        addresses: UnicastSourceAndMulticastDestination<I>,
252        route: fnet_multicast_admin::Route,
253        responder: I::AddRouteResponder,
254    },
255    DelRoute {
256        addresses: UnicastSourceAndMulticastDestination<I>,
257        responder: I::DelRouteResponder,
258    },
259    GetRouteStats {
260        addresses: UnicastSourceAndMulticastDestination<I>,
261        responder: I::GetRouteStatsResponder,
262    },
263    WatchRoutingEvents {
264        responder: I::WatchRoutingEventsResponder,
265    },
266}
267
268impl From<fnet_multicast_admin::Ipv4RoutingTableControllerRequest>
269    for TableControllerRequest<Ipv4>
270{
271    fn from(request: fnet_multicast_admin::Ipv4RoutingTableControllerRequest) -> Self {
272        use fnet_multicast_admin::Ipv4RoutingTableControllerRequest as R;
273        match request {
274            R::AddRoute { addresses, route, responder } => {
275                TableControllerRequest::AddRoute { addresses: addresses.into(), route, responder }
276            }
277            R::DelRoute { addresses, responder } => {
278                TableControllerRequest::DelRoute { addresses: addresses.into(), responder }
279            }
280            R::GetRouteStats { addresses, responder } => {
281                TableControllerRequest::GetRouteStats { addresses: addresses.into(), responder }
282            }
283            R::WatchRoutingEvents { responder } => {
284                TableControllerRequest::WatchRoutingEvents { responder }
285            }
286        }
287    }
288}
289
290impl From<fnet_multicast_admin::Ipv6RoutingTableControllerRequest>
291    for TableControllerRequest<Ipv6>
292{
293    fn from(request: fnet_multicast_admin::Ipv6RoutingTableControllerRequest) -> Self {
294        use fnet_multicast_admin::Ipv6RoutingTableControllerRequest as R;
295        match request {
296            R::AddRoute { addresses, route, responder } => {
297                TableControllerRequest::AddRoute { addresses: addresses.into(), route, responder }
298            }
299            R::DelRoute { addresses, responder } => {
300                TableControllerRequest::DelRoute { addresses: addresses.into(), responder }
301            }
302            R::GetRouteStats { addresses, responder } => {
303                TableControllerRequest::GetRouteStats { addresses: addresses.into(), responder }
304            }
305            R::WatchRoutingEvents { responder } => {
306                TableControllerRequest::WatchRoutingEvents { responder }
307            }
308        }
309    }
310}
311
312/// An IP generic version of
313/// [`fnet_multicast_admin::Ipv4UnicastSourceAndMulticastDestination`] and
314/// [`fnet_multicast_admin::Ipv6UnicastSourceAndMulticastDestination`].
315#[derive(Debug, Clone, GenericOverIp, PartialEq)]
316#[generic_over_ip(I, Ip)]
317pub struct UnicastSourceAndMulticastDestination<I: Ip> {
318    pub unicast_source: I::Addr,
319    pub multicast_destination: I::Addr,
320}
321
322impl From<fnet_multicast_admin::Ipv4UnicastSourceAndMulticastDestination>
323    for UnicastSourceAndMulticastDestination<Ipv4>
324{
325    fn from(addresses: fnet_multicast_admin::Ipv4UnicastSourceAndMulticastDestination) -> Self {
326        let fnet_multicast_admin::Ipv4UnicastSourceAndMulticastDestination {
327            unicast_source,
328            multicast_destination,
329        } = addresses;
330        UnicastSourceAndMulticastDestination {
331            unicast_source: unicast_source.into_ext(),
332            multicast_destination: multicast_destination.into_ext(),
333        }
334    }
335}
336
337impl From<fnet_multicast_admin::Ipv6UnicastSourceAndMulticastDestination>
338    for UnicastSourceAndMulticastDestination<Ipv6>
339{
340    fn from(addresses: fnet_multicast_admin::Ipv6UnicastSourceAndMulticastDestination) -> Self {
341        let fnet_multicast_admin::Ipv6UnicastSourceAndMulticastDestination {
342            unicast_source,
343            multicast_destination,
344        } = addresses;
345        UnicastSourceAndMulticastDestination {
346            unicast_source: unicast_source.into_ext(),
347            multicast_destination: multicast_destination.into_ext(),
348        }
349    }
350}
351
352impl From<UnicastSourceAndMulticastDestination<Ipv4>>
353    for fnet_multicast_admin::Ipv4UnicastSourceAndMulticastDestination
354{
355    fn from(addresses: UnicastSourceAndMulticastDestination<Ipv4>) -> Self {
356        let UnicastSourceAndMulticastDestination { unicast_source, multicast_destination } =
357            addresses;
358        fnet_multicast_admin::Ipv4UnicastSourceAndMulticastDestination {
359            unicast_source: unicast_source.into_ext(),
360            multicast_destination: multicast_destination.into_ext(),
361        }
362    }
363}
364
365impl From<UnicastSourceAndMulticastDestination<Ipv6>>
366    for fnet_multicast_admin::Ipv6UnicastSourceAndMulticastDestination
367{
368    fn from(addresses: UnicastSourceAndMulticastDestination<Ipv6>) -> Self {
369        let UnicastSourceAndMulticastDestination { unicast_source, multicast_destination } =
370            addresses;
371        fnet_multicast_admin::Ipv6UnicastSourceAndMulticastDestination {
372            unicast_source: unicast_source.into_ext(),
373            multicast_destination: multicast_destination.into_ext(),
374        }
375    }
376}
377
378/// An IP generic version of
379/// [`fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteError`] and
380/// [`fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteError`].
381#[derive(Debug, Clone, PartialEq)]
382pub enum AddRouteError {
383    InvalidAddress,
384    RequiredRouteFieldsMissing,
385    InterfaceNotFound,
386    InputCannotBeOutput,
387    DuplicateOutput,
388}
389
390impl From<fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteError> for AddRouteError {
391    fn from(error: fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteError) -> Self {
392        use fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteError as E;
393        match error {
394            E::InvalidAddress => AddRouteError::InvalidAddress,
395            E::RequiredRouteFieldsMissing => AddRouteError::RequiredRouteFieldsMissing,
396            E::InterfaceNotFound => AddRouteError::InterfaceNotFound,
397            E::InputCannotBeOutput => AddRouteError::InputCannotBeOutput,
398            E::DuplicateOutput => AddRouteError::DuplicateOutput,
399        }
400    }
401}
402
403impl From<fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteError> for AddRouteError {
404    fn from(error: fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteError) -> Self {
405        use fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteError as E;
406        match error {
407            E::InvalidAddress => AddRouteError::InvalidAddress,
408            E::RequiredRouteFieldsMissing => AddRouteError::RequiredRouteFieldsMissing,
409            E::InterfaceNotFound => AddRouteError::InterfaceNotFound,
410            E::InputCannotBeOutput => AddRouteError::InputCannotBeOutput,
411            E::DuplicateOutput => AddRouteError::DuplicateOutput,
412        }
413    }
414}
415
416impl From<AddRouteError> for fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteError {
417    fn from(error: AddRouteError) -> Self {
418        use fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteError as E;
419        match error {
420            AddRouteError::InvalidAddress => E::InvalidAddress,
421            AddRouteError::RequiredRouteFieldsMissing => E::RequiredRouteFieldsMissing,
422            AddRouteError::InterfaceNotFound => E::InterfaceNotFound,
423            AddRouteError::InputCannotBeOutput => E::InputCannotBeOutput,
424            AddRouteError::DuplicateOutput => E::DuplicateOutput,
425        }
426    }
427}
428
429impl From<AddRouteError> for fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteError {
430    fn from(error: AddRouteError) -> Self {
431        use fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteError as E;
432        match error {
433            AddRouteError::InvalidAddress => E::InvalidAddress,
434            AddRouteError::RequiredRouteFieldsMissing => E::RequiredRouteFieldsMissing,
435            AddRouteError::InterfaceNotFound => E::InterfaceNotFound,
436            AddRouteError::InputCannotBeOutput => E::InputCannotBeOutput,
437            AddRouteError::DuplicateOutput => E::DuplicateOutput,
438        }
439    }
440}
441
442impl FidlResponder<Result<(), AddRouteError>>
443    for fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteResponder
444{
445    fn try_send(self, response: Result<(), AddRouteError>) -> Result<(), fidl::Error> {
446        self.send(response.map_err(Into::into))
447    }
448}
449
450impl FidlResponder<Result<(), AddRouteError>>
451    for fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteResponder
452{
453    fn try_send(self, response: Result<(), AddRouteError>) -> Result<(), fidl::Error> {
454        self.send(response.map_err(Into::into))
455    }
456}
457
458/// An IP generic version of
459/// [`fnet_multicast_admin::Ipv4RoutingTableControllerDelRouteError`] and
460/// [`fnet_multicast_admin::Ipv6RoutingTableControllerDelRouteError`].
461#[derive(Debug, Clone, PartialEq)]
462pub enum DelRouteError {
463    InvalidAddress,
464    NotFound,
465}
466
467impl From<fnet_multicast_admin::Ipv4RoutingTableControllerDelRouteError> for DelRouteError {
468    fn from(error: fnet_multicast_admin::Ipv4RoutingTableControllerDelRouteError) -> Self {
469        use fnet_multicast_admin::Ipv4RoutingTableControllerDelRouteError as E;
470        match error {
471            E::InvalidAddress => DelRouteError::InvalidAddress,
472            E::NotFound => DelRouteError::NotFound,
473        }
474    }
475}
476
477impl From<fnet_multicast_admin::Ipv6RoutingTableControllerDelRouteError> for DelRouteError {
478    fn from(error: fnet_multicast_admin::Ipv6RoutingTableControllerDelRouteError) -> Self {
479        use fnet_multicast_admin::Ipv6RoutingTableControllerDelRouteError as E;
480        match error {
481            E::InvalidAddress => DelRouteError::InvalidAddress,
482            E::NotFound => DelRouteError::NotFound,
483        }
484    }
485}
486
487impl From<DelRouteError> for fnet_multicast_admin::Ipv4RoutingTableControllerDelRouteError {
488    fn from(error: DelRouteError) -> Self {
489        use fnet_multicast_admin::Ipv4RoutingTableControllerDelRouteError as E;
490        match error {
491            DelRouteError::InvalidAddress => E::InvalidAddress,
492            DelRouteError::NotFound => E::NotFound,
493        }
494    }
495}
496
497impl From<DelRouteError> for fnet_multicast_admin::Ipv6RoutingTableControllerDelRouteError {
498    fn from(error: DelRouteError) -> Self {
499        use fnet_multicast_admin::Ipv6RoutingTableControllerDelRouteError as E;
500        match error {
501            DelRouteError::InvalidAddress => E::InvalidAddress,
502            DelRouteError::NotFound => E::NotFound,
503        }
504    }
505}
506
507impl FidlResponder<Result<(), DelRouteError>>
508    for fnet_multicast_admin::Ipv4RoutingTableControllerDelRouteResponder
509{
510    fn try_send(self, response: Result<(), DelRouteError>) -> Result<(), fidl::Error> {
511        self.send(response.map_err(Into::into))
512    }
513}
514
515impl FidlResponder<Result<(), DelRouteError>>
516    for fnet_multicast_admin::Ipv6RoutingTableControllerDelRouteResponder
517{
518    fn try_send(self, response: Result<(), DelRouteError>) -> Result<(), fidl::Error> {
519        self.send(response.map_err(Into::into))
520    }
521}
522
523/// An IP generic version of
524/// [`fnet_multicast_admin::Ipv4RoutingTableControllerGetRouteStatsError`] and
525/// [`fnet_multicast_admin::Ipv6RoutingTableControllerGetRouteStatsError`].
526#[derive(Debug, Clone, PartialEq)]
527pub enum GetRouteStatsError {
528    InvalidAddress,
529    NotFound,
530}
531
532impl From<GetRouteStatsError>
533    for fnet_multicast_admin::Ipv4RoutingTableControllerGetRouteStatsError
534{
535    fn from(error: GetRouteStatsError) -> Self {
536        use fnet_multicast_admin::Ipv4RoutingTableControllerGetRouteStatsError as E;
537        match error {
538            GetRouteStatsError::InvalidAddress => E::InvalidAddress,
539            GetRouteStatsError::NotFound => E::NotFound,
540        }
541    }
542}
543
544impl From<fnet_multicast_admin::Ipv4RoutingTableControllerGetRouteStatsError>
545    for GetRouteStatsError
546{
547    fn from(error: fnet_multicast_admin::Ipv4RoutingTableControllerGetRouteStatsError) -> Self {
548        use fnet_multicast_admin::Ipv4RoutingTableControllerGetRouteStatsError as E;
549        match error {
550            E::InvalidAddress => GetRouteStatsError::InvalidAddress,
551            E::NotFound => GetRouteStatsError::NotFound,
552        }
553    }
554}
555
556impl From<GetRouteStatsError>
557    for fnet_multicast_admin::Ipv6RoutingTableControllerGetRouteStatsError
558{
559    fn from(error: GetRouteStatsError) -> Self {
560        use fnet_multicast_admin::Ipv6RoutingTableControllerGetRouteStatsError as E;
561        match error {
562            GetRouteStatsError::InvalidAddress => E::InvalidAddress,
563            GetRouteStatsError::NotFound => E::NotFound,
564        }
565    }
566}
567
568impl From<fnet_multicast_admin::Ipv6RoutingTableControllerGetRouteStatsError>
569    for GetRouteStatsError
570{
571    fn from(error: fnet_multicast_admin::Ipv6RoutingTableControllerGetRouteStatsError) -> Self {
572        use fnet_multicast_admin::Ipv6RoutingTableControllerGetRouteStatsError as E;
573        match error {
574            E::InvalidAddress => GetRouteStatsError::InvalidAddress,
575            E::NotFound => GetRouteStatsError::NotFound,
576        }
577    }
578}
579
580impl FidlResponder<Result<&fnet_multicast_admin::RouteStats, GetRouteStatsError>>
581    for fnet_multicast_admin::Ipv4RoutingTableControllerGetRouteStatsResponder
582{
583    fn try_send(
584        self,
585        response: Result<&fnet_multicast_admin::RouteStats, GetRouteStatsError>,
586    ) -> Result<(), fidl::Error> {
587        self.send(response.map_err(Into::into))
588    }
589}
590
591impl FidlResponder<Result<&fnet_multicast_admin::RouteStats, GetRouteStatsError>>
592    for fnet_multicast_admin::Ipv6RoutingTableControllerGetRouteStatsResponder
593{
594    fn try_send(
595        self,
596        response: Result<&fnet_multicast_admin::RouteStats, GetRouteStatsError>,
597    ) -> Result<(), fidl::Error> {
598        self.send(response.map_err(Into::into))
599    }
600}
601
602/// An IP generic version of the fields accepted by an
603/// [`fnet_multicast_admin::Ipv4RoutingTableControllerWatchRoutingEventsResponder`] and
604/// [`fnet_multicast_admin::Ipv6RoutingTableControllerWatchRoutingEventsResponder`].
605#[derive(Debug)]
606pub struct WatchRoutingEventsResponse<I: FidlMulticastAdminIpExt> {
607    pub dropped_events: u64,
608    pub addresses: UnicastSourceAndMulticastDestination<I>,
609    pub input_interface: u64,
610    pub event: fnet_multicast_admin::RoutingEvent,
611}
612
613impl FidlResponder<WatchRoutingEventsResponse<Ipv4>>
614    for fnet_multicast_admin::Ipv4RoutingTableControllerWatchRoutingEventsResponder
615{
616    fn try_send(self, response: WatchRoutingEventsResponse<Ipv4>) -> Result<(), fidl::Error> {
617        let WatchRoutingEventsResponse { dropped_events, addresses, input_interface, event } =
618            response;
619        let addresses = addresses.into();
620        self.send(dropped_events, &addresses, input_interface, &event)
621    }
622}
623
624impl FidlResponder<WatchRoutingEventsResponse<Ipv6>>
625    for fnet_multicast_admin::Ipv6RoutingTableControllerWatchRoutingEventsResponder
626{
627    fn try_send(self, response: WatchRoutingEventsResponse<Ipv6>) -> Result<(), fidl::Error> {
628        let WatchRoutingEventsResponse { dropped_events, addresses, input_interface, event } =
629            response;
630        let addresses = addresses.into();
631        self.send(dropped_events, &addresses, input_interface, &event)
632    }
633}
634
635/// The types of errors that may occur when creating [`Route`] from FIDL.
636#[derive(Debug, PartialEq)]
637pub enum RouteConversionError {
638    RequiredFieldMissing,
639}
640
641impl From<RouteConversionError> for AddRouteError {
642    fn from(route_conversion_error: RouteConversionError) -> AddRouteError {
643        match route_conversion_error {
644            RouteConversionError::RequiredFieldMissing => AddRouteError::RequiredRouteFieldsMissing,
645        }
646    }
647}
648
649/// A sanitized `fnet_multicast_admin::Route`.
650///
651/// All required fields are verified to be present.
652#[derive(Debug, PartialEq)]
653pub struct Route {
654    pub expected_input_interface: u64,
655    pub action: fnet_multicast_admin::Action,
656}
657
658impl TryFrom<fnet_multicast_admin::Route> for Route {
659    type Error = RouteConversionError;
660    fn try_from(fidl: fnet_multicast_admin::Route) -> Result<Self, Self::Error> {
661        let fnet_multicast_admin::Route { expected_input_interface, action, __source_breaking } =
662            fidl;
663        if let (Some(expected_input_interface), Some(action)) = (expected_input_interface, action) {
664            Ok(Route { expected_input_interface, action })
665        } else {
666            Err(RouteConversionError::RequiredFieldMissing)
667        }
668    }
669}
670
671impl From<Route> for fnet_multicast_admin::Route {
672    fn from(route: Route) -> fnet_multicast_admin::Route {
673        let Route { expected_input_interface, action } = route;
674        fnet_multicast_admin::Route {
675            expected_input_interface: Some(expected_input_interface),
676            action: Some(action),
677            __source_breaking: fidl::marker::SourceBreaking,
678        }
679    }
680}
681
682#[cfg(test)]
683mod tests {
684    use super::*;
685
686    use net_declare::{fidl_ip_v4, fidl_ip_v6, net_ip_v4, net_ip_v6};
687    use test_case::test_case;
688
689    #[test]
690    fn ipv4_unicast_source_and_multicast_destination() {
691        let fidl_addrs = fnet_multicast_admin::Ipv4UnicastSourceAndMulticastDestination {
692            unicast_source: fidl_ip_v4!("192.0.2.1"),
693            multicast_destination: fidl_ip_v4!("224.0.0.1"),
694        };
695        let addrs = UnicastSourceAndMulticastDestination::<Ipv4> {
696            unicast_source: net_ip_v4!("192.0.2.1"),
697            multicast_destination: net_ip_v4!("224.0.0.1"),
698        };
699        assert_eq!(
700            fnet_multicast_admin::Ipv4UnicastSourceAndMulticastDestination::from(addrs.clone()),
701            fidl_addrs
702        );
703        assert_eq!(UnicastSourceAndMulticastDestination::<Ipv4>::from(fidl_addrs), addrs);
704    }
705
706    #[test]
707    fn ipv6_unicast_source_and_multicast_destination() {
708        let fidl_addrs = fnet_multicast_admin::Ipv6UnicastSourceAndMulticastDestination {
709            unicast_source: fidl_ip_v6!("2001:db8::1"),
710            multicast_destination: fidl_ip_v6!("ff00::1"),
711        };
712        let addrs = UnicastSourceAndMulticastDestination::<Ipv6> {
713            unicast_source: net_ip_v6!("2001:db8::1"),
714            multicast_destination: net_ip_v6!("ff00::1"),
715        };
716        assert_eq!(
717            fnet_multicast_admin::Ipv6UnicastSourceAndMulticastDestination::from(addrs.clone()),
718            fidl_addrs
719        );
720        assert_eq!(UnicastSourceAndMulticastDestination::<Ipv6>::from(fidl_addrs), addrs);
721    }
722
723    #[test_case(
724        AddRouteError::InvalidAddress,
725        fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteError::InvalidAddress;
726        "invalid_address"
727    )]
728    #[test_case(
729        AddRouteError::RequiredRouteFieldsMissing,
730        fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteError::RequiredRouteFieldsMissing;
731        "required_route_fields_missing"
732    )]
733    #[test_case(
734        AddRouteError::InterfaceNotFound,
735        fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteError::InterfaceNotFound;
736        "interface_not_found"
737    )]
738    #[test_case(
739        AddRouteError::InputCannotBeOutput,
740        fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteError::InputCannotBeOutput;
741        "input_cannot_be_output"
742    )]
743    #[test_case(
744        AddRouteError::DuplicateOutput,
745        fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteError::DuplicateOutput;
746        "duplicate_output"
747    )]
748    fn ipv4_add_route_error(
749        err: AddRouteError,
750        fidl: fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteError,
751    ) {
752        assert_eq!(
753            fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteError::from(err.clone()),
754            fidl
755        );
756        assert_eq!(AddRouteError::from(fidl), err);
757    }
758
759    #[test_case(
760        AddRouteError::InvalidAddress,
761        fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteError::InvalidAddress;
762        "invalid_address"
763    )]
764    #[test_case(
765        AddRouteError::RequiredRouteFieldsMissing,
766        fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteError::RequiredRouteFieldsMissing;
767        "required_route_fields_missing"
768    )]
769    #[test_case(
770        AddRouteError::InterfaceNotFound,
771        fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteError::InterfaceNotFound;
772        "interface_not_found"
773    )]
774    #[test_case(
775        AddRouteError::InputCannotBeOutput,
776        fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteError::InputCannotBeOutput;
777        "input_cannot_be_output"
778    )]
779    #[test_case(
780        AddRouteError::DuplicateOutput,
781        fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteError::DuplicateOutput;
782        "duplicate_output"
783    )]
784    fn ipv6_add_route_error(
785        err: AddRouteError,
786        fidl: fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteError,
787    ) {
788        assert_eq!(
789            fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteError::from(err.clone()),
790            fidl
791        );
792        assert_eq!(AddRouteError::from(fidl), err);
793    }
794
795    #[test_case(
796        DelRouteError::InvalidAddress,
797        fnet_multicast_admin::Ipv4RoutingTableControllerDelRouteError::InvalidAddress;
798        "invalid_address"
799    )]
800    #[test_case(
801        DelRouteError::NotFound,
802        fnet_multicast_admin::Ipv4RoutingTableControllerDelRouteError::NotFound;
803        "not_found"
804    )]
805    fn ipv4_del_route_error(
806        err: DelRouteError,
807        fidl: fnet_multicast_admin::Ipv4RoutingTableControllerDelRouteError,
808    ) {
809        assert_eq!(
810            fnet_multicast_admin::Ipv4RoutingTableControllerDelRouteError::from(err.clone()),
811            fidl
812        );
813        assert_eq!(DelRouteError::from(fidl), err);
814    }
815
816    #[test_case(
817        DelRouteError::InvalidAddress,
818        fnet_multicast_admin::Ipv6RoutingTableControllerDelRouteError::InvalidAddress;
819        "invalid_address"
820    )]
821    #[test_case(
822        DelRouteError::NotFound,
823        fnet_multicast_admin::Ipv6RoutingTableControllerDelRouteError::NotFound;
824        "not_found"
825    )]
826    fn ipv6_del_route_error(
827        err: DelRouteError,
828        fidl: fnet_multicast_admin::Ipv6RoutingTableControllerDelRouteError,
829    ) {
830        assert_eq!(
831            fnet_multicast_admin::Ipv6RoutingTableControllerDelRouteError::from(err.clone()),
832            fidl
833        );
834        assert_eq!(DelRouteError::from(fidl), err);
835    }
836
837    #[test_case(
838        GetRouteStatsError::InvalidAddress =>
839        fnet_multicast_admin::Ipv4RoutingTableControllerGetRouteStatsError::InvalidAddress;
840        "invalid_address"
841    )]
842    #[test_case(
843        GetRouteStatsError::NotFound =>
844        fnet_multicast_admin::Ipv4RoutingTableControllerGetRouteStatsError::NotFound;
845        "not_found"
846    )]
847    fn ipv4_get_route_stats_error(
848        err: GetRouteStatsError,
849    ) -> fnet_multicast_admin::Ipv4RoutingTableControllerGetRouteStatsError {
850        fnet_multicast_admin::Ipv4RoutingTableControllerGetRouteStatsError::from(err)
851    }
852
853    #[test_case(
854        GetRouteStatsError::InvalidAddress =>
855        fnet_multicast_admin::Ipv6RoutingTableControllerGetRouteStatsError::InvalidAddress;
856        "invalid_address"
857    )]
858    #[test_case(
859        GetRouteStatsError::NotFound =>
860        fnet_multicast_admin::Ipv6RoutingTableControllerGetRouteStatsError::NotFound;
861        "not_found"
862    )]
863    fn ipv6_get_route_stats_error(
864        err: GetRouteStatsError,
865    ) -> fnet_multicast_admin::Ipv6RoutingTableControllerGetRouteStatsError {
866        fnet_multicast_admin::Ipv6RoutingTableControllerGetRouteStatsError::from(err)
867    }
868
869    #[test_case(
870        fnet_multicast_admin::Route {
871            expected_input_interface: Some(1),
872            action: Some(fnet_multicast_admin::Action::OutgoingInterfaces(vec![])),
873            __source_breaking: fidl::marker::SourceBreaking,
874        },
875        Ok(Route {
876            expected_input_interface: 1,
877            action: fnet_multicast_admin::Action::OutgoingInterfaces(vec![]),
878        });
879        "success"
880    )]
881    #[test_case(
882        fnet_multicast_admin::Route {
883            expected_input_interface: None,
884            action: Some(fnet_multicast_admin::Action::OutgoingInterfaces(vec![])),
885            __source_breaking: fidl::marker::SourceBreaking,
886        },
887        Err(RouteConversionError::RequiredFieldMissing);
888        "missing input interface"
889    )]
890    #[test_case(
891        fnet_multicast_admin::Route {
892            expected_input_interface: Some(1),
893            action: None,
894            __source_breaking: fidl::marker::SourceBreaking,
895        },
896        Err(RouteConversionError::RequiredFieldMissing);
897        "missing action"
898    )]
899    fn route_conversion(
900        fidl: fnet_multicast_admin::Route,
901        expected_result: Result<Route, RouteConversionError>,
902    ) {
903        assert_eq!(Route::try_from(fidl.clone()), expected_result);
904        if let Ok(route) = expected_result {
905            assert_eq!(fnet_multicast_admin::Route::from(route), fidl);
906        }
907    }
908}