Skip to main content

ndn_tlv/
tlv.rs

1use std::io::Read;
2
3use bytes::{Buf, BufMut, Bytes, BytesMut};
4
5use crate::{TlvDecode, TlvEncode, TlvError, VarNum};
6
7/// A TLV record
8pub trait Tlv {
9    /// The assigned type number for this TLV record
10    const TYP: usize;
11
12    /// The size of the payload contained within this TLV
13    ///
14    /// Does not include the bytes used for type and length and should be equal to the length value
15    /// in the packet.
16    fn inner_size(&self) -> usize;
17
18    /// Whether the TLV is critical, see [`tlv_critical`]
19    fn critical() -> bool {
20        tlv_critical::<Self>()
21    }
22
23    /// Read a TLV from a type implementing `Read`
24    fn from_reader(mut reader: impl Read) -> Result<Self, TlvError>
25    where
26        Self: TlvDecode,
27    {
28        let mut header_buf = [0; 18];
29        let bytes_read = reader.read(&mut header_buf).map_err(TlvError::IOError)?;
30        let mut header_bytes = Bytes::copy_from_slice(&header_buf);
31
32        let typ = VarNum::decode(&mut header_bytes)?;
33        if typ.value() as usize != Self::TYP {
34            // Technically not necessary, but we can exit early here
35            return Err(TlvError::TypeMismatch {
36                expected: Self::TYP,
37                found: typ.value() as usize,
38            });
39        }
40
41        let len = VarNum::decode(&mut header_bytes)?;
42        let total_len = typ.size() + len.size() + len.value() as usize;
43
44        let mut bytes = BytesMut::with_capacity(total_len);
45        bytes.put(&header_buf[0..bytes_read]);
46
47        let mut left_to_read = total_len - bytes_read;
48        let mut buf = [0; 1024];
49        while left_to_read > 0 {
50            let bytes_read = reader
51                .read(&mut buf[0..left_to_read])
52                .map_err(TlvError::IOError)?;
53            bytes.put(&buf[..left_to_read]);
54            left_to_read -= bytes_read;
55        }
56
57        Self::decode(&mut bytes.freeze())
58    }
59}
60
61/// Returns whether a TLV is "critical"
62///
63/// An unknown or out-of-order non-critical TLV can be safely ignored, while a critical TLV must
64/// lead to an error
65pub const fn tlv_critical<T: Tlv + ?Sized>() -> bool {
66    tlv_typ_critical(T::TYP)
67}
68
69/// Returns whether a TLV with a given type `typ` is "critical"
70///
71/// An unknown or out-of-order non-critical TLV can be safely ignored, while a critical TLV must
72/// lead to an error
73pub const fn tlv_typ_critical(typ: usize) -> bool {
74    typ < 32 || typ & 1 == 1
75}
76
77/// A generic TLV record whose type is only known at runtime
78#[derive(Debug, Clone, PartialEq, Eq, Hash)]
79pub struct GenericTlv<T> {
80    /// TLV-TYPE
81    pub typ: VarNum,
82    /// TLV-LENGTH
83    pub len: VarNum,
84    /// Actual content of the TLV record
85    pub content: T,
86}
87
88impl<T> TlvDecode for GenericTlv<T>
89where
90    T: TlvDecode,
91{
92    fn decode(bytes: &mut Bytes) -> crate::Result<Self> {
93        let typ = VarNum::decode(bytes)?.into();
94        let len = VarNum::decode(bytes)?;
95
96        if bytes.remaining() < len.into() {
97            return Err(TlvError::UnexpectedEndOfStream);
98        }
99
100        let mut inner_data = bytes.split_to(len.into());
101        Ok(Self {
102            typ,
103            len,
104            content: T::decode(&mut inner_data)?,
105        })
106    }
107}
108
109impl<T> TlvEncode for GenericTlv<T>
110where
111    T: TlvEncode,
112{
113    fn encode(&self) -> Bytes {
114        let mut bytes = BytesMut::with_capacity(self.size());
115        bytes.put(self.typ.encode());
116        bytes.put(self.len.encode());
117
118        let mut content = self.content.encode();
119        content.truncate(self.len.into());
120        if content.len() != self.len.into() {
121            panic!("GenericTLV length longer than encoded content");
122        }
123        bytes.put(content);
124        bytes.freeze()
125    }
126
127    fn size(&self) -> usize {
128        self.typ.size() + self.len.size() + self.content.size()
129    }
130}
131
132#[cfg(test)]
133mod tests {
134    use bytes::{Buf, BufMut, Bytes, BytesMut};
135
136    use crate::tests::GenericNameComponent;
137    use crate::{error::TlvError, Result, TlvDecode, TlvEncode, VarNum};
138
139    use super::*;
140
141    #[derive(Debug)]
142    struct Name {
143        components: Vec<GenericNameComponent>,
144    }
145
146    impl Tlv for Name {
147        const TYP: usize = 7;
148
149        fn inner_size(&self) -> usize {
150            self.components.size()
151        }
152    }
153
154    impl TlvDecode for Name {
155        fn decode(mut bytes: &mut Bytes) -> Result<Self> {
156            let typ = VarNum::decode(&mut bytes)?;
157            if usize::from(typ) != Self::TYP {
158                return Err(TlvError::TypeMismatch {
159                    expected: Self::TYP,
160                    found: typ.into(),
161                });
162            }
163            let length = VarNum::decode(&mut bytes)?;
164            let mut inner_data = bytes.copy_to_bytes(length.into());
165            let components = Vec::<GenericNameComponent>::decode(&mut inner_data)?;
166
167            Ok(Self { components })
168        }
169    }
170
171    impl TlvEncode for Name {
172        fn encode(&self) -> Bytes {
173            let mut bytes = BytesMut::with_capacity(self.size());
174            bytes.put(VarNum::from(Self::TYP).encode());
175            bytes.put(VarNum::from(self.inner_size()).encode());
176            bytes.put(self.components.encode());
177
178            bytes.freeze()
179        }
180
181        fn size(&self) -> usize {
182            VarNum::from(Self::TYP).size()
183                + VarNum::from(self.inner_size()).size()
184                + self.components.size()
185        }
186    }
187
188    #[test]
189    fn wrong_type() {
190        let mut data = Bytes::from(&[9, 5, b'h', b'e', b'l', b'l', b'o', 255, 255, 255][..]);
191        let component = GenericNameComponent::decode(&mut data);
192
193        assert!(component.is_err());
194        let error = component.unwrap_err();
195
196        assert_eq!(
197            error,
198            TlvError::TypeMismatch {
199                expected: 8,
200                found: 9
201            }
202        );
203    }
204
205    #[test]
206    fn name() {
207        let mut data = Bytes::from(
208            &[
209                7, 14, 8, 5, b'h', b'e', b'l', b'l', b'o', 8, 5, b'w', b'o', b'r', b'l', b'd', 255,
210                255, 255,
211            ][..],
212        );
213        let name = Name::decode(&mut data).unwrap();
214
215        assert_eq!(data.remaining(), 3);
216        assert_eq!(name.components.len(), 2);
217        assert_eq!(name.components[0].name, &b"hello"[..]);
218        assert_eq!(name.components[1].name, &b"world"[..]);
219    }
220}