leodos_protocols/network/isl/
address.rs1use zerocopy::FromBytes;
2use zerocopy::Immutable;
3use zerocopy::IntoBytes;
4use zerocopy::KnownLayout;
5use zerocopy::Unaligned;
6use zerocopy::network_endian::U32;
7
8use crate::network::isl::torus::Point;
9
10#[repr(transparent)]
11#[derive(
12 Copy, Clone, Debug, PartialEq, Eq, Hash, FromBytes, IntoBytes, Immutable, KnownLayout, Unaligned,
13)]
14pub struct SpacecraftId(pub U32);
16
17impl SpacecraftId {
18 pub const fn new(id: u32) -> Self {
20 Self(U32::new(id))
21 }
22
23 pub fn get(&self) -> u32 {
25 self.0.get()
26 }
27
28 pub fn encode(orb: u8, sat: u8, num_sats: u8) -> Self {
30 Self::new((orb as u32 + 1) * num_sats as u32 + sat as u32)
31 }
32
33 pub fn to_address(&self, num_sats: u8) -> Address {
35 let n = num_sats as u32;
36 let orb = self.get() / n;
37 let sat = self.get() % n;
38 if orb == 0 {
39 Address::Ground { station: sat as u8 }
40 } else {
41 Address::Satellite(Point {
42 orb: (orb - 1) as u8,
43 sat: sat as u8,
44 })
45 }
46 }
47}
48
49#[repr(C)]
50#[derive(
51 FromBytes, IntoBytes, Unaligned, KnownLayout, Immutable, Copy, Clone, Debug, PartialEq, Eq, Hash,
52)]
53pub struct RawAddress {
55 ground_or_orb: u8,
56 station_or_sat: u8,
57}
58
59#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
61pub enum Address {
62 Ground {
64 station: u8,
66 },
67 Satellite(Point),
69 ServiceArea {
71 orb: u8,
73 },
74}
75
76impl RawAddress {
77 pub fn parse(&self) -> Address {
79 if self.ground_or_orb == 0 {
80 Address::Ground {
81 station: self.station_or_sat,
82 }
83 } else if self.station_or_sat == 0 {
84 Address::ServiceArea {
85 orb: self.ground_or_orb - 1,
86 }
87 } else {
88 Address::Satellite(Point {
89 orb: self.ground_or_orb - 1,
90 sat: self.station_or_sat - 1,
91 })
92 }
93 }
94}
95
96impl From<Address> for RawAddress {
97 fn from(addr: Address) -> Self {
98 match addr {
99 Address::Ground { station } => Self {
100 ground_or_orb: 0,
101 station_or_sat: station,
102 },
103 Address::Satellite(Point { orb, sat }) => Self {
104 ground_or_orb: orb + 1,
105 station_or_sat: sat + 1,
106 },
107 Address::ServiceArea { orb } => Self {
108 ground_or_orb: orb + 1,
109 station_or_sat: 0,
110 },
111 }
112 }
113}
114
115impl Address {
116 pub fn ground(station: u8) -> Self {
118 Self::Ground { station: station }
119 }
120
121 pub fn satellite(orb: u8, sat: u8) -> Self {
123 Self::Satellite(Point { orb, sat })
124 }
125
126 pub fn service_area(orb: u8) -> Self {
128 Self::ServiceArea { orb }
129 }
130
131 pub fn is_valid_source(&self) -> bool {
133 !matches!(self, Address::ServiceArea { .. })
134 }
135
136 pub fn is_in_service_area(&self, min_sat: u8, max_sat: u8) -> bool {
138 match self {
139 Address::Satellite(Point { sat, .. }) => {
140 if min_sat <= max_sat {
141 (min_sat..=max_sat).contains(sat)
142 } else {
143 (min_sat..).contains(sat) || (..=max_sat).contains(sat)
144 }
145 }
146 _ => false,
147 }
148 }
149}
150
151impl From<Address> for Point {
152 fn from(addr: Address) -> Self {
153 match addr {
154 Address::Satellite(Point { orb, sat }) => Point::new(sat, orb),
155 Address::ServiceArea { orb } => Point::new(0, orb),
156 Address::Ground { .. } => Point::new(0, 0),
157 }
158 }
159}
160
161impl From<Point> for Address {
162 fn from(point: Point) -> Self {
163 Address::Satellite(Point {
164 orb: point.orb,
165 sat: point.sat,
166 })
167 }
168}