1#[cfg(not(feature = "std"))]
2use alloc::sync::Arc;
3#[cfg(feature = "std")]
4use std::sync::Arc;
5
6#[cfg(not(feature = "std"))]
7use core::cell::OnceCell as OnceLock;
8#[cfg(feature = "std")]
9use std::sync::OnceLock;
10
11use bytes::Bytes;
12
13use crate::tlv_type;
14use crate::{MetaInfo, Name, PacketError, SignatureInfo};
15use ndn_tlv::TlvReader;
16
17#[derive(Debug)]
23pub struct Data {
24 pub(crate) raw: Bytes,
26
27 signed_start: usize,
29 signed_end: usize,
30
31 sig_value_start: usize,
33 sig_value_end: usize,
34
35 pub name: Arc<Name>,
37
38 meta_info: OnceLock<Option<MetaInfo>>,
40
41 content: OnceLock<Option<Bytes>>,
43
44 sig_info: OnceLock<Option<SignatureInfo>>,
46}
47
48impl Data {
49 pub fn decode(raw: Bytes) -> Result<Self, PacketError> {
51 let mut reader = TlvReader::new(raw.clone());
52 let (typ, value) = reader.read_tlv()?;
53 if typ != tlv_type::DATA {
54 return Err(PacketError::UnknownPacketType(typ));
55 }
56
57 let outer_header_len = raw.len() - value.len();
61 let signed_start = outer_header_len;
62
63 let mut inner = TlvReader::new(value.clone());
64 let (name_typ, name_val) = inner.read_tlv()?;
65 if name_typ != tlv_type::NAME {
66 return Err(PacketError::UnknownPacketType(name_typ));
67 }
68 let name = Name::decode(name_val)?;
69
70 if name.is_empty() {
71 return Err(PacketError::MalformedPacket(
72 "Data Name must have at least one component".into(),
73 ));
74 }
75
76 let mut sig_value_start = 0;
78 let mut sig_value_end = 0;
79 let _ = scan_for_sig_value(
80 &raw,
81 outer_header_len,
82 &mut sig_value_start,
83 &mut sig_value_end,
84 );
85 let signed_end = if sig_value_start > 0 {
86 sig_value_start
87 } else {
88 raw.len()
89 };
90
91 Ok(Self {
92 raw,
93 signed_start,
94 signed_end,
95 sig_value_start,
96 sig_value_end,
97 name: Arc::new(name),
98 meta_info: OnceLock::new(),
99 content: OnceLock::new(),
100 sig_info: OnceLock::new(),
101 })
102 }
103
104 pub fn signed_region(&self) -> &[u8] {
106 &self.raw[self.signed_start..self.signed_end]
107 }
108
109 pub fn sig_value(&self) -> &[u8] {
114 if self.sig_value_start == 0 || self.sig_value_end == 0 {
115 return &[];
116 }
117 let sig_tlv = self.raw.slice(self.sig_value_start..self.sig_value_end);
119 let mut r = TlvReader::new(sig_tlv);
120 match r.read_tlv() {
121 Ok((_, val)) => {
122 let val_start = self.sig_value_end - val.len();
123 &self.raw[val_start..self.sig_value_end]
124 }
125 Err(_) => &[],
126 }
127 }
128
129 pub fn raw(&self) -> &Bytes {
130 &self.raw
131 }
132
133 #[cfg(feature = "std")]
137 pub fn implicit_digest(&self) -> ring::digest::Digest {
138 ring::digest::digest(&ring::digest::SHA256, &self.raw)
139 }
140
141 pub fn content(&self) -> Option<&Bytes> {
142 self.content
143 .get_or_init(|| decode_content(&self.raw).ok().flatten())
144 .as_ref()
145 }
146
147 pub fn meta_info(&self) -> Option<&MetaInfo> {
148 self.meta_info
149 .get_or_init(|| decode_meta_info(&self.raw).ok().flatten())
150 .as_ref()
151 }
152
153 pub fn sig_info(&self) -> Option<&SignatureInfo> {
154 self.sig_info
155 .get_or_init(|| decode_sig_info(&self.raw).ok().flatten())
156 .as_ref()
157 }
158
159 #[cfg(feature = "std")]
165 pub fn link_delegations(&self) -> Option<Vec<Arc<Name>>> {
166 let mi = self.meta_info()?;
167 if mi.content_type != crate::meta_info::ContentType::Link {
168 return None;
169 }
170 let content = self.content()?;
171 let mut reader = TlvReader::new(content.clone());
172 let mut names = Vec::new();
173 while !reader.is_empty() {
174 let (typ, val) = reader.read_tlv().ok()?;
175 if typ == tlv_type::NAME {
176 names.push(Arc::new(Name::decode(val).ok()?));
177 }
178 }
179 if names.is_empty() { None } else { Some(names) }
180 }
181}
182
183fn scan_for_sig_value(
184 raw: &Bytes,
185 start: usize,
186 sig_start: &mut usize,
187 sig_end: &mut usize,
188) -> Result<(), PacketError> {
189 let mut reader = TlvReader::new(raw.slice(start..));
190 while !reader.is_empty() {
191 let pos = start + reader.position();
192 let (typ, val) = reader.read_tlv()?;
193 if typ == tlv_type::SIGNATURE_VALUE {
194 *sig_start = pos;
195 *sig_end = start + reader.position();
196 return Ok(());
197 }
198 let _ = val;
199 }
200 Ok(())
201}
202
203fn decode_content(raw: &Bytes) -> Result<Option<Bytes>, PacketError> {
204 let mut reader = TlvReader::new(raw.clone());
205 let (_, value) = reader.read_tlv()?;
206 let mut inner = TlvReader::new(value);
207 while !inner.is_empty() {
208 let (typ, val) = inner.read_tlv()?;
209 if typ == tlv_type::CONTENT {
210 return Ok(Some(val));
211 }
212 }
213 Ok(None)
214}
215
216fn decode_meta_info(raw: &Bytes) -> Result<Option<MetaInfo>, PacketError> {
217 let mut reader = TlvReader::new(raw.clone());
218 let (_, value) = reader.read_tlv()?;
219 let mut inner = TlvReader::new(value);
220 while !inner.is_empty() {
221 let (typ, val) = inner.read_tlv()?;
222 if typ == tlv_type::META_INFO {
223 return Ok(Some(MetaInfo::decode(val)?));
224 }
225 }
226 Ok(None)
227}
228
229#[cfg(test)]
230pub(crate) fn build_data_packet(
231 components: &[&[u8]],
232 content: &[u8],
233 freshness_ms: Option<u64>,
234 sig_type_code: u8,
235 sig_value: &[u8],
236) -> Bytes {
237 let mut w = ndn_tlv::TlvWriter::new();
238 w.write_nested(tlv_type::DATA, |w| {
239 w.write_nested(tlv_type::NAME, |w| {
240 for comp in components {
241 w.write_tlv(tlv_type::NAME_COMPONENT, comp);
242 }
243 });
244 if let Some(ms) = freshness_ms {
245 w.write_nested(tlv_type::META_INFO, |w| {
246 w.write_tlv(tlv_type::FRESHNESS_PERIOD, &ms.to_be_bytes());
247 });
248 }
249 w.write_tlv(tlv_type::CONTENT, content);
250 w.write_nested(tlv_type::SIGNATURE_INFO, |w| {
251 w.write_tlv(tlv_type::SIGNATURE_TYPE, &[sig_type_code]);
252 });
253 w.write_tlv(tlv_type::SIGNATURE_VALUE, sig_value);
254 });
255 w.finish()
256}
257
258fn decode_sig_info(raw: &Bytes) -> Result<Option<SignatureInfo>, PacketError> {
259 let mut reader = TlvReader::new(raw.clone());
260 let (_, value) = reader.read_tlv()?;
261 let mut inner = TlvReader::new(value);
262 while !inner.is_empty() {
263 let (typ, val) = inner.read_tlv()?;
264 if typ == tlv_type::SIGNATURE_INFO {
265 return Ok(Some(SignatureInfo::decode(val)?));
266 }
267 }
268 Ok(None)
269}
270
271#[cfg(test)]
272mod tests {
273 use super::*;
274
275 #[test]
278 fn decode_name() {
279 let raw = build_data_packet(&[b"edu", b"ucla"], b"hello", None, 5, &[0xAB]);
280 let d = Data::decode(raw).unwrap();
281 assert_eq!(d.name.len(), 2);
282 assert_eq!(d.name.components()[0].value.as_ref(), b"edu");
283 assert_eq!(d.name.components()[1].value.as_ref(), b"ucla");
284 }
285
286 #[test]
289 fn decode_content() {
290 let raw = build_data_packet(&[b"test"], b"payload", None, 0, &[0x00]);
291 let d = Data::decode(raw).unwrap();
292 let content = d.content().expect("content present");
293 assert_eq!(content.as_ref(), b"payload");
294 }
295
296 #[test]
297 fn decode_empty_content() {
298 let raw = build_data_packet(&[b"test"], b"", None, 0, &[0x00]);
299 let d = Data::decode(raw).unwrap();
300 let content = d.content().expect("content present");
302 assert_eq!(content.len(), 0);
303 }
304
305 #[test]
308 fn decode_meta_info_freshness() {
309 let raw = build_data_packet(&[b"test"], b"", Some(5000), 5, &[0x00]);
310 let d = Data::decode(raw).unwrap();
311 let mi = d.meta_info().expect("meta_info present");
312 assert_eq!(
313 mi.freshness_period,
314 Some(std::time::Duration::from_millis(5000))
315 );
316 }
317
318 #[test]
319 fn decode_no_meta_info() {
320 let raw = build_data_packet(&[b"test"], b"data", None, 0, &[0x00]);
321 let d = Data::decode(raw).unwrap();
322 assert!(d.meta_info().is_none());
323 }
324
325 #[test]
328 fn decode_sig_info_type() {
329 let raw = build_data_packet(&[b"test"], b"", None, 5, &[0xAB]);
330 let d = Data::decode(raw).unwrap();
331 let si = d.sig_info().expect("sig_info present");
332 assert_eq!(si.sig_type, crate::SignatureType::SignatureEd25519);
333 }
334
335 #[test]
338 fn signed_region_excludes_sig_value() {
339 let sig_bytes: &[u8] = &[0xDE, 0xAD, 0xBE, 0xEF];
340 let raw = build_data_packet(&[b"test"], b"content", None, 5, sig_bytes);
341 let d = Data::decode(raw.clone()).unwrap();
342
343 let region = d.signed_region();
344 assert!(!region.is_empty());
346 assert!(!region.ends_with(sig_bytes));
350 }
351
352 #[test]
353 fn sig_value_correct_bytes() {
354 let sig_bytes: &[u8] = &[0x11, 0x22, 0x33, 0x44];
355 let raw = build_data_packet(&[b"test"], b"content", None, 5, sig_bytes);
356 let d = Data::decode(raw).unwrap();
357 assert_eq!(d.sig_value(), sig_bytes);
359 }
360
361 #[test]
362 fn signed_end_equals_sig_value_start() {
363 let raw = build_data_packet(&[b"n"], b"x", None, 0, &[0xAB, 0xCD]);
366 let d = Data::decode(raw).unwrap();
367 assert_eq!(d.signed_end, d.sig_value_start);
368 }
369
370 #[test]
373 fn raw_field_is_full_wire_bytes() {
374 let raw = build_data_packet(&[b"test"], b"hi", None, 0, &[0x00]);
375 let d = Data::decode(raw.clone()).unwrap();
376 assert_eq!(d.raw(), &raw);
377 }
378
379 fn build_link_data(name_comps: &[&[u8]], delegations: &[&[&[u8]]]) -> Bytes {
382 let mut content_w = ndn_tlv::TlvWriter::new();
383 for del in delegations {
384 content_w.write_nested(tlv_type::NAME, |w| {
385 for comp in *del {
386 w.write_tlv(tlv_type::NAME_COMPONENT, comp);
387 }
388 });
389 }
390 let content_bytes = content_w.finish();
391
392 let mut w = ndn_tlv::TlvWriter::new();
393 w.write_nested(tlv_type::DATA, |w| {
394 w.write_nested(tlv_type::NAME, |w| {
395 for comp in name_comps {
396 w.write_tlv(tlv_type::NAME_COMPONENT, comp);
397 }
398 });
399 w.write_nested(tlv_type::META_INFO, |w| {
400 w.write_tlv(tlv_type::CONTENT_TYPE, &[1]); });
402 w.write_tlv(tlv_type::CONTENT, &content_bytes);
403 w.write_nested(tlv_type::SIGNATURE_INFO, |w| {
404 w.write_tlv(tlv_type::SIGNATURE_TYPE, &[0]);
405 });
406 w.write_tlv(tlv_type::SIGNATURE_VALUE, &[0x00]);
407 });
408 w.finish()
409 }
410
411 #[test]
412 fn link_delegations_parsed() {
413 let raw = build_link_data(
414 &[b"link"],
415 &[&[b"ndn", b"gateway1"], &[b"ndn", b"gateway2"]],
416 );
417 let d = Data::decode(raw).unwrap();
418 let dels = d.link_delegations().expect("delegations present");
419 assert_eq!(dels.len(), 2);
420 assert_eq!(dels[0].components()[1].value.as_ref(), b"gateway1");
421 assert_eq!(dels[1].components()[1].value.as_ref(), b"gateway2");
422 }
423
424 #[test]
425 fn non_link_data_has_no_delegations() {
426 let raw = build_data_packet(&[b"test"], b"payload", None, 5, &[0x00]);
427 let d = Data::decode(raw).unwrap();
428 assert!(d.link_delegations().is_none());
429 }
430
431 #[test]
434 fn implicit_digest_is_sha256_of_raw() {
435 let raw = build_data_packet(&[b"test"], b"content", None, 5, &[0xAB]);
436 let d = Data::decode(raw.clone()).unwrap();
437 let expected = ring::digest::digest(&ring::digest::SHA256, &raw);
438 assert_eq!(d.implicit_digest().as_ref(), expected.as_ref());
439 }
440
441 #[test]
444 fn decode_wrong_type_errors() {
445 let mut w = ndn_tlv::TlvWriter::new();
446 w.write_nested(0x05, |w| {
447 w.write_nested(crate::tlv_type::NAME, |w| {
449 w.write_tlv(crate::tlv_type::NAME_COMPONENT, b"test");
450 });
451 });
452 assert!(matches!(
453 Data::decode(w.finish()).unwrap_err(),
454 crate::PacketError::UnknownPacketType(0x05)
455 ));
456 }
457}