endhost_api_protobuf/
convert.rs

1// Copyright 2025 Anapaya Systems
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//   http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//! Conversions between endhost API protobuf types and endhost API models.
15
16use scion_proto::path::convert::segment::InvalidSegmentError;
17
18use crate::endhost::api_service::v1::{
19    ListSegmentsResponse, ListUnderlaysResponse, Router, Snap, SnapUnderlay, UdpUnderlay,
20};
21
22impl From<endhost_api_models::underlays::Underlays> for ListUnderlaysResponse {
23    fn from(underlays: endhost_api_models::underlays::Underlays) -> Self {
24        ListUnderlaysResponse {
25            udp: Some(UdpUnderlay::from(underlays.udp_underlay)),
26            snap: Some(SnapUnderlay::from(underlays.snap_underlay)),
27        }
28    }
29}
30
31impl TryFrom<ListUnderlaysResponse> for endhost_api_models::underlays::Underlays {
32    type Error = url::ParseError;
33    fn try_from(response: ListUnderlaysResponse) -> Result<Self, Self::Error> {
34        Ok(endhost_api_models::underlays::Underlays {
35            udp_underlay: match response.udp {
36                Some(udp) => udp.routers.into_iter().map(Into::into).collect(),
37                None => Vec::new(),
38            },
39            snap_underlay: match response.snap {
40                Some(snap) => {
41                    snap.snaps
42                        .into_iter()
43                        .map(TryInto::try_into)
44                        .collect::<Result<_, _>>()?
45                }
46                None => Vec::new(),
47            },
48        })
49    }
50}
51
52impl From<Vec<endhost_api_models::underlays::ScionRouter>> for UdpUnderlay {
53    fn from(routers: Vec<endhost_api_models::underlays::ScionRouter>) -> Self {
54        UdpUnderlay {
55            routers: routers.into_iter().map(Into::into).collect(),
56        }
57    }
58}
59
60impl From<UdpUnderlay> for Vec<endhost_api_models::underlays::ScionRouter> {
61    fn from(udp: UdpUnderlay) -> Self {
62        udp.routers.into_iter().map(Into::into).collect()
63    }
64}
65
66impl From<endhost_api_models::underlays::ScionRouter> for Router {
67    fn from(r: endhost_api_models::underlays::ScionRouter) -> Self {
68        Router {
69            isd_as: r.isd_as.into(),
70            address: r.internal_interface.to_string(),
71            // XXX(bunert): protobuf doesn't support u16
72            interfaces: r.interfaces.into_iter().map(|i| i as u32).collect(),
73        }
74    }
75}
76
77impl From<Router> for endhost_api_models::underlays::ScionRouter {
78    fn from(r: Router) -> Self {
79        endhost_api_models::underlays::ScionRouter {
80            isd_as: r.isd_as.into(),
81            internal_interface: r.address.parse().unwrap(),
82            interfaces: r.interfaces.into_iter().map(|i| i as u16).collect(),
83        }
84    }
85}
86
87impl From<Vec<endhost_api_models::underlays::Snap>> for SnapUnderlay {
88    fn from(snaps: Vec<endhost_api_models::underlays::Snap>) -> Self {
89        SnapUnderlay {
90            snaps: snaps.into_iter().map(Into::into).collect(),
91        }
92    }
93}
94
95impl TryFrom<SnapUnderlay> for Vec<endhost_api_models::underlays::Snap> {
96    type Error = url::ParseError;
97    fn try_from(snap: SnapUnderlay) -> Result<Self, Self::Error> {
98        snap.snaps.into_iter().map(TryFrom::try_from).collect()
99    }
100}
101
102impl From<endhost_api_models::underlays::Snap> for Snap {
103    fn from(s: endhost_api_models::underlays::Snap) -> Self {
104        Snap {
105            address: s.address.to_string(),
106            isd_ases: s.isd_ases.into_iter().map(Into::into).collect(),
107        }
108    }
109}
110
111impl TryFrom<Snap> for endhost_api_models::underlays::Snap {
112    type Error = url::ParseError;
113    fn try_from(s: Snap) -> Result<Self, Self::Error> {
114        Ok(endhost_api_models::underlays::Snap {
115            address: s.address.parse()?,
116            isd_ases: s.isd_ases.into_iter().map(Into::into).collect(),
117        })
118    }
119}
120
121impl From<scion_proto::path::segment::Segments> for ListSegmentsResponse {
122    fn from(segments: scion_proto::path::segment::Segments) -> Self {
123        Self {
124            up_segments: segments.up_segments.into_iter().map(Into::into).collect(),
125            down_segments: segments.down_segments.into_iter().map(Into::into).collect(),
126            core_segments: segments.core_segments.into_iter().map(Into::into).collect(),
127            next_page_token: segments.next_page_token,
128        }
129    }
130}
131
132impl TryFrom<ListSegmentsResponse> for scion_proto::path::segment::Segments {
133    type Error = InvalidSegmentError;
134    fn try_from(response: ListSegmentsResponse) -> Result<Self, Self::Error> {
135        let convert = |segs: Vec<_>| {
136            segs.into_iter()
137                .map(scion_proto::path::PathSegment::try_from)
138                .collect::<Result<_, _>>()
139        };
140        Ok(scion_proto::path::segment::Segments {
141            up_segments: convert(response.up_segments)?,
142            down_segments: convert(response.down_segments)?,
143            core_segments: convert(response.core_segments)?,
144            next_page_token: response.next_page_token,
145        })
146    }
147}