Skip to main content

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    InvalidTtl,
389}
390
391impl From<fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteError> for AddRouteError {
392    fn from(error: fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteError) -> Self {
393        use fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteError as E;
394        match error {
395            E::InvalidAddress => AddRouteError::InvalidAddress,
396            E::RequiredRouteFieldsMissing => AddRouteError::RequiredRouteFieldsMissing,
397            E::InterfaceNotFound => AddRouteError::InterfaceNotFound,
398            E::InputCannotBeOutput => AddRouteError::InputCannotBeOutput,
399            E::DuplicateOutput => AddRouteError::DuplicateOutput,
400            E::InvalidTtl => AddRouteError::InvalidTtl,
401        }
402    }
403}
404
405impl From<fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteError> for AddRouteError {
406    fn from(error: fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteError) -> Self {
407        use fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteError as E;
408        match error {
409            E::InvalidAddress => AddRouteError::InvalidAddress,
410            E::RequiredRouteFieldsMissing => AddRouteError::RequiredRouteFieldsMissing,
411            E::InterfaceNotFound => AddRouteError::InterfaceNotFound,
412            E::InputCannotBeOutput => AddRouteError::InputCannotBeOutput,
413            E::DuplicateOutput => AddRouteError::DuplicateOutput,
414            E::InvalidTtl => AddRouteError::InvalidTtl,
415        }
416    }
417}
418
419impl From<AddRouteError> for fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteError {
420    fn from(error: AddRouteError) -> Self {
421        use fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteError as E;
422        match error {
423            AddRouteError::InvalidAddress => E::InvalidAddress,
424            AddRouteError::RequiredRouteFieldsMissing => E::RequiredRouteFieldsMissing,
425            AddRouteError::InterfaceNotFound => E::InterfaceNotFound,
426            AddRouteError::InputCannotBeOutput => E::InputCannotBeOutput,
427            AddRouteError::DuplicateOutput => E::DuplicateOutput,
428            AddRouteError::InvalidTtl => E::InvalidTtl,
429        }
430    }
431}
432
433impl From<AddRouteError> for fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteError {
434    fn from(error: AddRouteError) -> Self {
435        use fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteError as E;
436        match error {
437            AddRouteError::InvalidAddress => E::InvalidAddress,
438            AddRouteError::RequiredRouteFieldsMissing => E::RequiredRouteFieldsMissing,
439            AddRouteError::InterfaceNotFound => E::InterfaceNotFound,
440            AddRouteError::InputCannotBeOutput => E::InputCannotBeOutput,
441            AddRouteError::DuplicateOutput => E::DuplicateOutput,
442            AddRouteError::InvalidTtl => E::InvalidTtl,
443        }
444    }
445}
446
447impl FidlResponder<Result<(), AddRouteError>>
448    for fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteResponder
449{
450    fn try_send(self, response: Result<(), AddRouteError>) -> Result<(), fidl::Error> {
451        self.send(response.map_err(Into::into))
452    }
453}
454
455impl FidlResponder<Result<(), AddRouteError>>
456    for fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteResponder
457{
458    fn try_send(self, response: Result<(), AddRouteError>) -> Result<(), fidl::Error> {
459        self.send(response.map_err(Into::into))
460    }
461}
462
463/// An IP generic version of
464/// [`fnet_multicast_admin::Ipv4RoutingTableControllerDelRouteError`] and
465/// [`fnet_multicast_admin::Ipv6RoutingTableControllerDelRouteError`].
466#[derive(Debug, Clone, PartialEq)]
467pub enum DelRouteError {
468    InvalidAddress,
469    NotFound,
470}
471
472impl From<fnet_multicast_admin::Ipv4RoutingTableControllerDelRouteError> for DelRouteError {
473    fn from(error: fnet_multicast_admin::Ipv4RoutingTableControllerDelRouteError) -> Self {
474        use fnet_multicast_admin::Ipv4RoutingTableControllerDelRouteError as E;
475        match error {
476            E::InvalidAddress => DelRouteError::InvalidAddress,
477            E::NotFound => DelRouteError::NotFound,
478        }
479    }
480}
481
482impl From<fnet_multicast_admin::Ipv6RoutingTableControllerDelRouteError> for DelRouteError {
483    fn from(error: fnet_multicast_admin::Ipv6RoutingTableControllerDelRouteError) -> Self {
484        use fnet_multicast_admin::Ipv6RoutingTableControllerDelRouteError as E;
485        match error {
486            E::InvalidAddress => DelRouteError::InvalidAddress,
487            E::NotFound => DelRouteError::NotFound,
488        }
489    }
490}
491
492impl From<DelRouteError> for fnet_multicast_admin::Ipv4RoutingTableControllerDelRouteError {
493    fn from(error: DelRouteError) -> Self {
494        use fnet_multicast_admin::Ipv4RoutingTableControllerDelRouteError as E;
495        match error {
496            DelRouteError::InvalidAddress => E::InvalidAddress,
497            DelRouteError::NotFound => E::NotFound,
498        }
499    }
500}
501
502impl From<DelRouteError> for fnet_multicast_admin::Ipv6RoutingTableControllerDelRouteError {
503    fn from(error: DelRouteError) -> Self {
504        use fnet_multicast_admin::Ipv6RoutingTableControllerDelRouteError as E;
505        match error {
506            DelRouteError::InvalidAddress => E::InvalidAddress,
507            DelRouteError::NotFound => E::NotFound,
508        }
509    }
510}
511
512impl FidlResponder<Result<(), DelRouteError>>
513    for fnet_multicast_admin::Ipv4RoutingTableControllerDelRouteResponder
514{
515    fn try_send(self, response: Result<(), DelRouteError>) -> Result<(), fidl::Error> {
516        self.send(response.map_err(Into::into))
517    }
518}
519
520impl FidlResponder<Result<(), DelRouteError>>
521    for fnet_multicast_admin::Ipv6RoutingTableControllerDelRouteResponder
522{
523    fn try_send(self, response: Result<(), DelRouteError>) -> Result<(), fidl::Error> {
524        self.send(response.map_err(Into::into))
525    }
526}
527
528/// An IP generic version of
529/// [`fnet_multicast_admin::Ipv4RoutingTableControllerGetRouteStatsError`] and
530/// [`fnet_multicast_admin::Ipv6RoutingTableControllerGetRouteStatsError`].
531#[derive(Debug, Clone, PartialEq)]
532pub enum GetRouteStatsError {
533    InvalidAddress,
534    NotFound,
535}
536
537impl From<GetRouteStatsError>
538    for fnet_multicast_admin::Ipv4RoutingTableControllerGetRouteStatsError
539{
540    fn from(error: GetRouteStatsError) -> Self {
541        use fnet_multicast_admin::Ipv4RoutingTableControllerGetRouteStatsError as E;
542        match error {
543            GetRouteStatsError::InvalidAddress => E::InvalidAddress,
544            GetRouteStatsError::NotFound => E::NotFound,
545        }
546    }
547}
548
549impl From<fnet_multicast_admin::Ipv4RoutingTableControllerGetRouteStatsError>
550    for GetRouteStatsError
551{
552    fn from(error: fnet_multicast_admin::Ipv4RoutingTableControllerGetRouteStatsError) -> Self {
553        use fnet_multicast_admin::Ipv4RoutingTableControllerGetRouteStatsError as E;
554        match error {
555            E::InvalidAddress => GetRouteStatsError::InvalidAddress,
556            E::NotFound => GetRouteStatsError::NotFound,
557        }
558    }
559}
560
561impl From<GetRouteStatsError>
562    for fnet_multicast_admin::Ipv6RoutingTableControllerGetRouteStatsError
563{
564    fn from(error: GetRouteStatsError) -> Self {
565        use fnet_multicast_admin::Ipv6RoutingTableControllerGetRouteStatsError as E;
566        match error {
567            GetRouteStatsError::InvalidAddress => E::InvalidAddress,
568            GetRouteStatsError::NotFound => E::NotFound,
569        }
570    }
571}
572
573impl From<fnet_multicast_admin::Ipv6RoutingTableControllerGetRouteStatsError>
574    for GetRouteStatsError
575{
576    fn from(error: fnet_multicast_admin::Ipv6RoutingTableControllerGetRouteStatsError) -> Self {
577        use fnet_multicast_admin::Ipv6RoutingTableControllerGetRouteStatsError as E;
578        match error {
579            E::InvalidAddress => GetRouteStatsError::InvalidAddress,
580            E::NotFound => GetRouteStatsError::NotFound,
581        }
582    }
583}
584
585impl FidlResponder<Result<&fnet_multicast_admin::RouteStats, GetRouteStatsError>>
586    for fnet_multicast_admin::Ipv4RoutingTableControllerGetRouteStatsResponder
587{
588    fn try_send(
589        self,
590        response: Result<&fnet_multicast_admin::RouteStats, GetRouteStatsError>,
591    ) -> Result<(), fidl::Error> {
592        self.send(response.map_err(Into::into))
593    }
594}
595
596impl FidlResponder<Result<&fnet_multicast_admin::RouteStats, GetRouteStatsError>>
597    for fnet_multicast_admin::Ipv6RoutingTableControllerGetRouteStatsResponder
598{
599    fn try_send(
600        self,
601        response: Result<&fnet_multicast_admin::RouteStats, GetRouteStatsError>,
602    ) -> Result<(), fidl::Error> {
603        self.send(response.map_err(Into::into))
604    }
605}
606
607/// An IP generic version of the fields accepted by an
608/// [`fnet_multicast_admin::Ipv4RoutingTableControllerWatchRoutingEventsResponder`] and
609/// [`fnet_multicast_admin::Ipv6RoutingTableControllerWatchRoutingEventsResponder`].
610#[derive(Debug)]
611pub struct WatchRoutingEventsResponse<I: FidlMulticastAdminIpExt> {
612    pub dropped_events: u64,
613    pub addresses: UnicastSourceAndMulticastDestination<I>,
614    pub input_interface: u64,
615    pub event: fnet_multicast_admin::RoutingEvent,
616}
617
618impl FidlResponder<WatchRoutingEventsResponse<Ipv4>>
619    for fnet_multicast_admin::Ipv4RoutingTableControllerWatchRoutingEventsResponder
620{
621    fn try_send(self, response: WatchRoutingEventsResponse<Ipv4>) -> Result<(), fidl::Error> {
622        let WatchRoutingEventsResponse { dropped_events, addresses, input_interface, event } =
623            response;
624        let addresses = addresses.into();
625        self.send(dropped_events, &addresses, input_interface, &event)
626    }
627}
628
629impl FidlResponder<WatchRoutingEventsResponse<Ipv6>>
630    for fnet_multicast_admin::Ipv6RoutingTableControllerWatchRoutingEventsResponder
631{
632    fn try_send(self, response: WatchRoutingEventsResponse<Ipv6>) -> Result<(), fidl::Error> {
633        let WatchRoutingEventsResponse { dropped_events, addresses, input_interface, event } =
634            response;
635        let addresses = addresses.into();
636        self.send(dropped_events, &addresses, input_interface, &event)
637    }
638}
639
640/// The types of errors that may occur when creating [`Route`] from FIDL.
641#[derive(Debug, PartialEq)]
642pub enum RouteConversionError {
643    RequiredFieldMissing,
644}
645
646impl From<RouteConversionError> for AddRouteError {
647    fn from(route_conversion_error: RouteConversionError) -> AddRouteError {
648        match route_conversion_error {
649            RouteConversionError::RequiredFieldMissing => AddRouteError::RequiredRouteFieldsMissing,
650        }
651    }
652}
653
654/// A sanitized `fnet_multicast_admin::Route`.
655///
656/// All required fields are verified to be present.
657#[derive(Debug, PartialEq)]
658pub struct Route {
659    pub expected_input_interface: u64,
660    pub action: fnet_multicast_admin::Action,
661}
662
663impl TryFrom<fnet_multicast_admin::Route> for Route {
664    type Error = RouteConversionError;
665    fn try_from(fidl: fnet_multicast_admin::Route) -> Result<Self, Self::Error> {
666        let fnet_multicast_admin::Route { expected_input_interface, action, __source_breaking } =
667            fidl;
668        if let (Some(expected_input_interface), Some(action)) = (expected_input_interface, action) {
669            Ok(Route { expected_input_interface, action })
670        } else {
671            Err(RouteConversionError::RequiredFieldMissing)
672        }
673    }
674}
675
676impl From<Route> for fnet_multicast_admin::Route {
677    fn from(route: Route) -> fnet_multicast_admin::Route {
678        let Route { expected_input_interface, action } = route;
679        fnet_multicast_admin::Route {
680            expected_input_interface: Some(expected_input_interface),
681            action: Some(action),
682            __source_breaking: fidl::marker::SourceBreaking,
683        }
684    }
685}
686
687#[cfg(test)]
688mod tests {
689    use super::*;
690
691    use net_declare::{fidl_ip_v4, fidl_ip_v6, net_ip_v4, net_ip_v6};
692    use test_case::test_case;
693
694    #[test]
695    fn ipv4_unicast_source_and_multicast_destination() {
696        let fidl_addrs = fnet_multicast_admin::Ipv4UnicastSourceAndMulticastDestination {
697            unicast_source: fidl_ip_v4!("192.0.2.1"),
698            multicast_destination: fidl_ip_v4!("224.0.0.1"),
699        };
700        let addrs = UnicastSourceAndMulticastDestination::<Ipv4> {
701            unicast_source: net_ip_v4!("192.0.2.1"),
702            multicast_destination: net_ip_v4!("224.0.0.1"),
703        };
704        assert_eq!(
705            fnet_multicast_admin::Ipv4UnicastSourceAndMulticastDestination::from(addrs.clone()),
706            fidl_addrs
707        );
708        assert_eq!(UnicastSourceAndMulticastDestination::<Ipv4>::from(fidl_addrs), addrs);
709    }
710
711    #[test]
712    fn ipv6_unicast_source_and_multicast_destination() {
713        let fidl_addrs = fnet_multicast_admin::Ipv6UnicastSourceAndMulticastDestination {
714            unicast_source: fidl_ip_v6!("2001:db8::1"),
715            multicast_destination: fidl_ip_v6!("ff00::1"),
716        };
717        let addrs = UnicastSourceAndMulticastDestination::<Ipv6> {
718            unicast_source: net_ip_v6!("2001:db8::1"),
719            multicast_destination: net_ip_v6!("ff00::1"),
720        };
721        assert_eq!(
722            fnet_multicast_admin::Ipv6UnicastSourceAndMulticastDestination::from(addrs.clone()),
723            fidl_addrs
724        );
725        assert_eq!(UnicastSourceAndMulticastDestination::<Ipv6>::from(fidl_addrs), addrs);
726    }
727
728    #[test_case(
729        AddRouteError::InvalidAddress,
730        fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteError::InvalidAddress;
731        "invalid_address"
732    )]
733    #[test_case(
734        AddRouteError::RequiredRouteFieldsMissing,
735        fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteError::RequiredRouteFieldsMissing;
736        "required_route_fields_missing"
737    )]
738    #[test_case(
739        AddRouteError::InterfaceNotFound,
740        fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteError::InterfaceNotFound;
741        "interface_not_found"
742    )]
743    #[test_case(
744        AddRouteError::InputCannotBeOutput,
745        fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteError::InputCannotBeOutput;
746        "input_cannot_be_output"
747    )]
748    #[test_case(
749        AddRouteError::DuplicateOutput,
750        fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteError::DuplicateOutput;
751        "duplicate_output"
752    )]
753    fn ipv4_add_route_error(
754        err: AddRouteError,
755        fidl: fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteError,
756    ) {
757        assert_eq!(
758            fnet_multicast_admin::Ipv4RoutingTableControllerAddRouteError::from(err.clone()),
759            fidl
760        );
761        assert_eq!(AddRouteError::from(fidl), err);
762    }
763
764    #[test_case(
765        AddRouteError::InvalidAddress,
766        fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteError::InvalidAddress;
767        "invalid_address"
768    )]
769    #[test_case(
770        AddRouteError::RequiredRouteFieldsMissing,
771        fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteError::RequiredRouteFieldsMissing;
772        "required_route_fields_missing"
773    )]
774    #[test_case(
775        AddRouteError::InterfaceNotFound,
776        fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteError::InterfaceNotFound;
777        "interface_not_found"
778    )]
779    #[test_case(
780        AddRouteError::InputCannotBeOutput,
781        fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteError::InputCannotBeOutput;
782        "input_cannot_be_output"
783    )]
784    #[test_case(
785        AddRouteError::DuplicateOutput,
786        fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteError::DuplicateOutput;
787        "duplicate_output"
788    )]
789    fn ipv6_add_route_error(
790        err: AddRouteError,
791        fidl: fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteError,
792    ) {
793        assert_eq!(
794            fnet_multicast_admin::Ipv6RoutingTableControllerAddRouteError::from(err.clone()),
795            fidl
796        );
797        assert_eq!(AddRouteError::from(fidl), err);
798    }
799
800    #[test_case(
801        DelRouteError::InvalidAddress,
802        fnet_multicast_admin::Ipv4RoutingTableControllerDelRouteError::InvalidAddress;
803        "invalid_address"
804    )]
805    #[test_case(
806        DelRouteError::NotFound,
807        fnet_multicast_admin::Ipv4RoutingTableControllerDelRouteError::NotFound;
808        "not_found"
809    )]
810    fn ipv4_del_route_error(
811        err: DelRouteError,
812        fidl: fnet_multicast_admin::Ipv4RoutingTableControllerDelRouteError,
813    ) {
814        assert_eq!(
815            fnet_multicast_admin::Ipv4RoutingTableControllerDelRouteError::from(err.clone()),
816            fidl
817        );
818        assert_eq!(DelRouteError::from(fidl), err);
819    }
820
821    #[test_case(
822        DelRouteError::InvalidAddress,
823        fnet_multicast_admin::Ipv6RoutingTableControllerDelRouteError::InvalidAddress;
824        "invalid_address"
825    )]
826    #[test_case(
827        DelRouteError::NotFound,
828        fnet_multicast_admin::Ipv6RoutingTableControllerDelRouteError::NotFound;
829        "not_found"
830    )]
831    fn ipv6_del_route_error(
832        err: DelRouteError,
833        fidl: fnet_multicast_admin::Ipv6RoutingTableControllerDelRouteError,
834    ) {
835        assert_eq!(
836            fnet_multicast_admin::Ipv6RoutingTableControllerDelRouteError::from(err.clone()),
837            fidl
838        );
839        assert_eq!(DelRouteError::from(fidl), err);
840    }
841
842    #[test_case(
843        GetRouteStatsError::InvalidAddress =>
844        fnet_multicast_admin::Ipv4RoutingTableControllerGetRouteStatsError::InvalidAddress;
845        "invalid_address"
846    )]
847    #[test_case(
848        GetRouteStatsError::NotFound =>
849        fnet_multicast_admin::Ipv4RoutingTableControllerGetRouteStatsError::NotFound;
850        "not_found"
851    )]
852    fn ipv4_get_route_stats_error(
853        err: GetRouteStatsError,
854    ) -> fnet_multicast_admin::Ipv4RoutingTableControllerGetRouteStatsError {
855        fnet_multicast_admin::Ipv4RoutingTableControllerGetRouteStatsError::from(err)
856    }
857
858    #[test_case(
859        GetRouteStatsError::InvalidAddress =>
860        fnet_multicast_admin::Ipv6RoutingTableControllerGetRouteStatsError::InvalidAddress;
861        "invalid_address"
862    )]
863    #[test_case(
864        GetRouteStatsError::NotFound =>
865        fnet_multicast_admin::Ipv6RoutingTableControllerGetRouteStatsError::NotFound;
866        "not_found"
867    )]
868    fn ipv6_get_route_stats_error(
869        err: GetRouteStatsError,
870    ) -> fnet_multicast_admin::Ipv6RoutingTableControllerGetRouteStatsError {
871        fnet_multicast_admin::Ipv6RoutingTableControllerGetRouteStatsError::from(err)
872    }
873
874    #[test_case(
875        fnet_multicast_admin::Route {
876            expected_input_interface: Some(1),
877            action: Some(fnet_multicast_admin::Action::OutgoingInterfaces(vec![])),
878            __source_breaking: fidl::marker::SourceBreaking,
879        },
880        Ok(Route {
881            expected_input_interface: 1,
882            action: fnet_multicast_admin::Action::OutgoingInterfaces(vec![]),
883        });
884        "success"
885    )]
886    #[test_case(
887        fnet_multicast_admin::Route {
888            expected_input_interface: None,
889            action: Some(fnet_multicast_admin::Action::OutgoingInterfaces(vec![])),
890            __source_breaking: fidl::marker::SourceBreaking,
891        },
892        Err(RouteConversionError::RequiredFieldMissing);
893        "missing input interface"
894    )]
895    #[test_case(
896        fnet_multicast_admin::Route {
897            expected_input_interface: Some(1),
898            action: None,
899            __source_breaking: fidl::marker::SourceBreaking,
900        },
901        Err(RouteConversionError::RequiredFieldMissing);
902        "missing action"
903    )]
904    fn route_conversion(
905        fidl: fnet_multicast_admin::Route,
906        expected_result: Result<Route, RouteConversionError>,
907    ) {
908        assert_eq!(Route::try_from(fidl.clone()), expected_result);
909        if let Ok(route) = expected_result {
910            assert_eq!(fnet_multicast_admin::Route::from(route), fidl);
911        }
912    }
913}