1use crate::error::ParseError;
2
3use super::{
4 ConstPackedSizeBytes, DateFormat, FromBytes, KissOfDeath, LeapIndicator, Mode, Packet,
5 PrimarySource, ReferenceIdentifier, ShortFormat, Stratum, TimestampFormat, ToBytes, Version,
6};
7
8impl FromBytes for ShortFormat {
9 fn from_bytes(buf: &[u8]) -> Result<(Self, usize), ParseError> {
10 if buf.len() < Self::PACKED_SIZE_BYTES {
11 return Err(ParseError::BufferTooShort {
12 needed: Self::PACKED_SIZE_BYTES,
13 available: buf.len(),
14 });
15 }
16 let seconds = u16::from_be_bytes([buf[0], buf[1]]);
17 let fraction = u16::from_be_bytes([buf[2], buf[3]]);
18 Ok((ShortFormat { seconds, fraction }, Self::PACKED_SIZE_BYTES))
19 }
20}
21
22impl FromBytes for TimestampFormat {
23 fn from_bytes(buf: &[u8]) -> Result<(Self, usize), ParseError> {
24 if buf.len() < Self::PACKED_SIZE_BYTES {
25 return Err(ParseError::BufferTooShort {
26 needed: Self::PACKED_SIZE_BYTES,
27 available: buf.len(),
28 });
29 }
30 let seconds = u32::from_be_bytes([buf[0], buf[1], buf[2], buf[3]]);
31 let fraction = u32::from_be_bytes([buf[4], buf[5], buf[6], buf[7]]);
32 Ok((
33 TimestampFormat { seconds, fraction },
34 Self::PACKED_SIZE_BYTES,
35 ))
36 }
37}
38
39impl FromBytes for DateFormat {
40 fn from_bytes(buf: &[u8]) -> Result<(Self, usize), ParseError> {
41 if buf.len() < Self::PACKED_SIZE_BYTES {
42 return Err(ParseError::BufferTooShort {
43 needed: Self::PACKED_SIZE_BYTES,
44 available: buf.len(),
45 });
46 }
47 let era_number = i32::from_be_bytes([buf[0], buf[1], buf[2], buf[3]]);
48 let era_offset = u32::from_be_bytes([buf[4], buf[5], buf[6], buf[7]]);
49 let fraction = u64::from_be_bytes([
50 buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],
51 ]);
52 Ok((
53 DateFormat {
54 era_number,
55 era_offset,
56 fraction,
57 },
58 Self::PACKED_SIZE_BYTES,
59 ))
60 }
61}
62
63impl FromBytes for Stratum {
64 fn from_bytes(buf: &[u8]) -> Result<(Self, usize), ParseError> {
65 if buf.is_empty() {
66 return Err(ParseError::BufferTooShort {
67 needed: 1,
68 available: 0,
69 });
70 }
71 Ok((Stratum(buf[0]), 1))
72 }
73}
74
75impl FromBytes for (LeapIndicator, Version, Mode) {
76 fn from_bytes(buf: &[u8]) -> Result<(Self, usize), ParseError> {
77 if buf.is_empty() {
78 return Err(ParseError::BufferTooShort {
79 needed: 1,
80 available: 0,
81 });
82 }
83 let li_vn_mode = buf[0];
84 let li_u8 = li_vn_mode >> 6;
85 let vn_u8 = (li_vn_mode >> 3) & 0b111;
86 let mode_u8 = li_vn_mode & 0b111;
87 let li = LeapIndicator::try_from(li_u8).map_err(|_| ParseError::InvalidField {
88 field: "leap indicator",
89 value: li_u8 as u32,
90 })?;
91 let vn = Version(vn_u8);
92 let mode = Mode::try_from(mode_u8).map_err(|_| ParseError::InvalidField {
93 field: "association mode",
94 value: mode_u8 as u32,
95 })?;
96 Ok(((li, vn, mode), 1))
97 }
98}
99
100impl ReferenceIdentifier {
101 pub fn from_bytes_with_stratum(bytes: [u8; 4], stratum: Stratum) -> Self {
109 let u = u32::from_be_bytes(bytes);
110 if stratum == Stratum::UNSPECIFIED {
111 match KissOfDeath::try_from(u) {
112 Ok(kod) => ReferenceIdentifier::KissOfDeath(kod),
113 Err(_) => ReferenceIdentifier::Unknown(bytes),
114 }
115 } else if stratum == Stratum::PRIMARY {
116 match PrimarySource::try_from(u) {
117 Ok(src) => ReferenceIdentifier::PrimarySource(src),
118 Err(_) => ReferenceIdentifier::Unknown(bytes),
119 }
120 } else if stratum.is_secondary() {
121 ReferenceIdentifier::SecondaryOrClient(bytes)
122 } else {
123 ReferenceIdentifier::Unknown(bytes)
124 }
125 }
126}
127
128impl FromBytes for Packet {
129 fn from_bytes(buf: &[u8]) -> Result<(Self, usize), ParseError> {
130 if buf.len() < Self::PACKED_SIZE_BYTES {
131 return Err(ParseError::BufferTooShort {
132 needed: Self::PACKED_SIZE_BYTES,
133 available: buf.len(),
134 });
135 }
136
137 let mut offset = 0;
138
139 let ((leap_indicator, version, mode), n) =
140 <(LeapIndicator, Version, Mode)>::from_bytes(&buf[offset..])?;
141 offset += n;
142
143 let (stratum, n) = Stratum::from_bytes(&buf[offset..])?;
144 offset += n;
145
146 let poll = buf[offset] as i8;
147 offset += 1;
148
149 let precision = buf[offset] as i8;
150 offset += 1;
151
152 let (root_delay, n) = ShortFormat::from_bytes(&buf[offset..])?;
153 offset += n;
154
155 let (root_dispersion, n) = ShortFormat::from_bytes(&buf[offset..])?;
156 offset += n;
157
158 let ref_id_bytes = [
159 buf[offset],
160 buf[offset + 1],
161 buf[offset + 2],
162 buf[offset + 3],
163 ];
164 let reference_id = ReferenceIdentifier::from_bytes_with_stratum(ref_id_bytes, stratum);
165 offset += 4;
166
167 let (reference_timestamp, n) = TimestampFormat::from_bytes(&buf[offset..])?;
168 offset += n;
169
170 let (origin_timestamp, n) = TimestampFormat::from_bytes(&buf[offset..])?;
171 offset += n;
172
173 let (receive_timestamp, n) = TimestampFormat::from_bytes(&buf[offset..])?;
174 offset += n;
175
176 let (transmit_timestamp, n) = TimestampFormat::from_bytes(&buf[offset..])?;
177 offset += n;
178
179 Ok((
180 Packet {
181 leap_indicator,
182 version,
183 mode,
184 stratum,
185 poll,
186 precision,
187 root_delay,
188 root_dispersion,
189 reference_id,
190 reference_timestamp,
191 origin_timestamp,
192 receive_timestamp,
193 transmit_timestamp,
194 },
195 offset,
196 ))
197 }
198}
199
200impl ToBytes for ShortFormat {
203 fn to_bytes(&self, buf: &mut [u8]) -> Result<usize, ParseError> {
204 if buf.len() < Self::PACKED_SIZE_BYTES {
205 return Err(ParseError::BufferTooShort {
206 needed: Self::PACKED_SIZE_BYTES,
207 available: buf.len(),
208 });
209 }
210 let s = self.seconds.to_be_bytes();
211 let f = self.fraction.to_be_bytes();
212 buf[0] = s[0];
213 buf[1] = s[1];
214 buf[2] = f[0];
215 buf[3] = f[1];
216 Ok(Self::PACKED_SIZE_BYTES)
217 }
218}
219
220impl ToBytes for TimestampFormat {
221 fn to_bytes(&self, buf: &mut [u8]) -> Result<usize, ParseError> {
222 if buf.len() < Self::PACKED_SIZE_BYTES {
223 return Err(ParseError::BufferTooShort {
224 needed: Self::PACKED_SIZE_BYTES,
225 available: buf.len(),
226 });
227 }
228 let s = self.seconds.to_be_bytes();
229 let f = self.fraction.to_be_bytes();
230 buf[..4].copy_from_slice(&s);
231 buf[4..8].copy_from_slice(&f);
232 Ok(Self::PACKED_SIZE_BYTES)
233 }
234}
235
236impl ToBytes for DateFormat {
237 fn to_bytes(&self, buf: &mut [u8]) -> Result<usize, ParseError> {
238 if buf.len() < Self::PACKED_SIZE_BYTES {
239 return Err(ParseError::BufferTooShort {
240 needed: Self::PACKED_SIZE_BYTES,
241 available: buf.len(),
242 });
243 }
244 buf[..4].copy_from_slice(&self.era_number.to_be_bytes());
245 buf[4..8].copy_from_slice(&self.era_offset.to_be_bytes());
246 buf[8..16].copy_from_slice(&self.fraction.to_be_bytes());
247 Ok(Self::PACKED_SIZE_BYTES)
248 }
249}
250
251impl ToBytes for Stratum {
252 fn to_bytes(&self, buf: &mut [u8]) -> Result<usize, ParseError> {
253 if buf.is_empty() {
254 return Err(ParseError::BufferTooShort {
255 needed: 1,
256 available: 0,
257 });
258 }
259 buf[0] = self.0;
260 Ok(1)
261 }
262}
263
264impl ToBytes for (LeapIndicator, Version, Mode) {
265 fn to_bytes(&self, buf: &mut [u8]) -> Result<usize, ParseError> {
266 if buf.is_empty() {
267 return Err(ParseError::BufferTooShort {
268 needed: 1,
269 available: 0,
270 });
271 }
272 let (li, vn, mode) = *self;
273 let mut li_vn_mode = 0u8;
274 li_vn_mode |= (li as u8) << 6;
275 li_vn_mode |= vn.0 << 3;
276 li_vn_mode |= mode as u8;
277 buf[0] = li_vn_mode;
278 Ok(1)
279 }
280}
281
282impl ToBytes for ReferenceIdentifier {
283 fn to_bytes(&self, buf: &mut [u8]) -> Result<usize, ParseError> {
284 if buf.len() < Self::PACKED_SIZE_BYTES {
285 return Err(ParseError::BufferTooShort {
286 needed: Self::PACKED_SIZE_BYTES,
287 available: buf.len(),
288 });
289 }
290 let bytes = self.as_bytes();
291 buf[..4].copy_from_slice(&bytes);
292 Ok(Self::PACKED_SIZE_BYTES)
293 }
294}
295
296impl ToBytes for Packet {
297 fn to_bytes(&self, buf: &mut [u8]) -> Result<usize, ParseError> {
298 if buf.len() < Self::PACKED_SIZE_BYTES {
299 return Err(ParseError::BufferTooShort {
300 needed: Self::PACKED_SIZE_BYTES,
301 available: buf.len(),
302 });
303 }
304
305 let mut offset = 0;
306
307 let li_vn_mode = (self.leap_indicator, self.version, self.mode);
308 offset += li_vn_mode.to_bytes(&mut buf[offset..])?;
309 offset += self.stratum.to_bytes(&mut buf[offset..])?;
310 buf[offset] = self.poll as u8;
311 offset += 1;
312 buf[offset] = self.precision as u8;
313 offset += 1;
314 offset += self.root_delay.to_bytes(&mut buf[offset..])?;
315 offset += self.root_dispersion.to_bytes(&mut buf[offset..])?;
316 offset += self.reference_id.to_bytes(&mut buf[offset..])?;
317 offset += self.reference_timestamp.to_bytes(&mut buf[offset..])?;
318 offset += self.origin_timestamp.to_bytes(&mut buf[offset..])?;
319 offset += self.receive_timestamp.to_bytes(&mut buf[offset..])?;
320 offset += self.transmit_timestamp.to_bytes(&mut buf[offset..])?;
321
322 Ok(offset)
323 }
324}