Newer
Older
#[derive(Debug, PartialEq, Eq, Clone)]
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
pub struct Route {
pub max_hops: u8,
path: ArrayVec<u8, 254>,
has_future: bool,
}
impl Route {
pub fn new(max_hops: u8) -> Self {
let path = ArrayVec::new();
Self {
max_hops,
path,
has_future: false,
}
}
/// Returns `None` if there isn't enough space for the callsign
/// Returns `None` if attempting to pushed is_used=true after an existing is_used=false
/// is_future=false when this callsign has digipeated
/// is_future=true when this callsign is expected to be part of the route, but isn't yet
/// see the specs for more information
pub fn push_callsign(&mut self, callsign: &str, ssid: u8, is_future: bool) -> Option<()> {
let len = callsign.as_bytes().len() + 2;
let free_space = self.path.capacity() - self.path.len();
if len > free_space {
return None;
}
self.has_future = self.has_future || is_future;
if self.has_future && !is_future {
return None;
}
// safe to unwrap since we already did a length check
self.path
.try_extend_from_slice(callsign.as_bytes())
.unwrap();
self.path.push(if is_future { 0xFD } else { 0xFF });
self.path.push(ssid);
Some(())
}
/// Returns `None` if there isn't enough space
pub fn push_internet(&mut self) -> Option<()> {
let free_space = self.path.capacity() - self.path.len();
if free_space < 1 {
return None;
}
self.path.push(0xFE);
Some(())
}
pub fn iter(&'_ self) -> RouteIter<'_> {
RouteIter::new(self)
}
pub fn encode<'a>(&self, buf: &'a mut [u8]) -> Option<&'a [u8]> {
let packet_len = self.path.len() + 1;
let buf = buf.get_mut(0..(packet_len + 1))?;
buf[0] = packet_len.try_into().unwrap();
buf[1] = self.max_hops;
buf[2..(packet_len + 1)].copy_from_slice(&self.path);
Some(buf)
}
// TODO reject packets that have a 0xFF anywhere after an FD
pub fn decode(data: &[u8]) -> Option<Self> {
let len: usize = (*data.first()?).into();
let data = data.get(1..(len + 1))?;
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
let mut path = ArrayVec::new();
path.try_extend_from_slice(&data[1..]).unwrap();
let has_future = data[1..].iter().any(|x| *x == 0xFD);
Some(Self {
max_hops,
path,
has_future,
})
}
}
#[derive(Debug, Eq, PartialEq)]
pub enum RouteNode<'a> {
Internet,
Identity(&'a str, u8, bool),
}
#[derive(Debug)]
pub struct RouteIter<'a> {
route: &'a Route,
i: usize,
}
impl<'a> RouteIter<'a> {
fn new(route: &'a Route) -> Self {
Self { route, i: 0 }
}
}
impl<'a> Iterator for RouteIter<'a> {
type Item = RouteNode<'a>;
fn next(&mut self) -> Option<Self::Item> {
if self.i == self.route.path.len() {
return None;
}
let i_start = self.i;
self.i += 1;
if self.route.path[i_start] == 0xFE {
return Some(RouteNode::Internet);
}
while self.route.path[self.i] != 0xFD && self.route.path[self.i] != 0xFF {
self.i += 1;
}
let callsign = core::str::from_utf8(&self.route.path[i_start..self.i]).unwrap();
let is_future = self.route.path[self.i] == 0xFD;
self.i += 1;
let ssid = self.route.path[self.i];
self.i += 1;
Some(RouteNode::Identity(callsign, ssid, is_future))
}
}