Skip to main content

moq_transport/coding/
tuple.rs

1use super::{Decode, DecodeError, Encode, EncodeError};
2use core::hash::{Hash, Hasher};
3
4/// Tuple Field
5#[derive(Clone, Debug, Default, Eq, PartialEq)]
6pub struct TupleField {
7    pub value: Vec<u8>,
8}
9
10impl TupleField {
11    // Tuples are in MOQ are only used for TrackNamespace. The RFC limits the
12    // total size of the Tracknamespace + TrackName to be 4096 bytes.  So an
13    // individual field should never be larger than 4096 bytes.
14    pub const MAX_VALUE_SIZE: usize = 4096;
15}
16
17impl Hash for TupleField {
18    fn hash<H: Hasher>(&self, state: &mut H) {
19        self.value.hash(state);
20    }
21}
22
23impl Decode for TupleField {
24    fn decode<R: bytes::Buf>(r: &mut R) -> Result<Self, DecodeError> {
25        let size = usize::decode(r)?;
26        if size > Self::MAX_VALUE_SIZE {
27            return Err(DecodeError::FieldBoundsExceeded("TupleField".to_string()));
28        }
29        Self::decode_remaining(r, size)?;
30        let mut buf = vec![0; size];
31        r.copy_to_slice(&mut buf);
32        Ok(Self { value: buf })
33    }
34}
35
36impl Encode for TupleField {
37    fn encode<W: bytes::BufMut>(&self, w: &mut W) -> Result<(), EncodeError> {
38        if self.value.len() > Self::MAX_VALUE_SIZE {
39            return Err(EncodeError::FieldBoundsExceeded("TupleField".to_string()));
40        }
41        self.value.len().encode(w)?;
42        Self::encode_remaining(w, self.value.len())?;
43        w.put_slice(&self.value);
44        Ok(())
45    }
46}
47
48impl TupleField {
49    pub fn new() -> Self {
50        Self::default()
51    }
52
53    pub fn from_utf8(path: &str) -> Self {
54        let mut field = TupleField::new();
55        field.value = path.as_bytes().to_vec();
56        field
57    }
58
59    /// Allow an encodable structure (ie. implements the Encode trait) to be set as the value.
60    // TODO SLG - is this really useful?
61    pub fn set<P: Encode>(&mut self, p: P) -> Result<(), EncodeError> {
62        let mut value = Vec::new();
63        p.encode(&mut value)?;
64        self.value = value;
65        Ok(())
66    }
67
68    /// Try to decode the value as the specified Decodable structure (ie. implements the Decode trait).
69    // TODO SLG - is this really useful?
70    pub fn get<P: Decode>(&self) -> Result<P, DecodeError> {
71        P::decode(&mut bytes::Bytes::from(self.value.clone()))
72    }
73}
74
75/// Tuple
76#[derive(Clone, Debug, Default, Eq, PartialEq)]
77pub struct Tuple {
78    pub fields: Vec<TupleField>,
79}
80
81impl Hash for Tuple {
82    fn hash<H: Hasher>(&self, state: &mut H) {
83        self.fields.hash(state);
84    }
85}
86
87impl Decode for Tuple {
88    fn decode<R: bytes::Buf>(r: &mut R) -> Result<Self, DecodeError> {
89        let count = usize::decode(r)?;
90        let mut fields = Vec::new();
91        for _ in 0..count {
92            fields.push(TupleField::decode(r)?);
93        }
94        Ok(Self { fields })
95    }
96}
97
98impl Encode for Tuple {
99    fn encode<W: bytes::BufMut>(&self, w: &mut W) -> Result<(), EncodeError> {
100        self.fields.len().encode(w)?;
101        for field in &self.fields {
102            field.encode(w)?;
103        }
104        Ok(())
105    }
106}
107
108impl Tuple {
109    pub fn new() -> Self {
110        Self::default()
111    }
112
113    pub fn add(&mut self, field: TupleField) {
114        self.fields.push(field);
115    }
116
117    pub fn set(&mut self, index: usize, f: TupleField) -> Result<(), EncodeError> {
118        self.fields[index].set(f)
119    }
120
121    pub fn get(&self, index: usize) -> Result<TupleField, DecodeError> {
122        self.fields[index].get()
123    }
124
125    pub fn clear(&mut self) {
126        self.fields.clear();
127    }
128
129    pub fn from_utf8_path(path: &str) -> Self {
130        let mut tuple = Tuple::new();
131        for part in path.split('/') {
132            tuple.add(TupleField::from_utf8(part));
133        }
134        tuple
135    }
136
137    pub fn to_utf8_path(&self) -> String {
138        let mut path = String::new();
139        for field in &self.fields {
140            path.push('/');
141            path.push_str(&String::from_utf8_lossy(&field.value));
142        }
143        path
144    }
145}
146
147#[cfg(test)]
148mod tests {
149    use super::*;
150    use bytes::Bytes;
151    use bytes::BytesMut;
152
153    #[test]
154    fn encode_decode() {
155        let mut buf = BytesMut::new();
156
157        let t = Tuple::from_utf8_path("test/path/to/resource");
158        t.encode(&mut buf).unwrap();
159        #[rustfmt::skip]
160        assert_eq!(
161            buf.to_vec(),
162            vec![
163                0x04, // 4 tuple fields
164                // Field 1: "test"
165                0x04, 0x74, 0x65, 0x73, 0x74,
166                // Field 2: "path"
167                0x04, 0x70, 0x61, 0x74, 0x68,
168                // Field 3: "to"
169                0x02, 0x74, 0x6f,
170                // Field 4: "resource"
171                0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65
172            ]
173        );
174        let decoded = Tuple::decode(&mut buf).unwrap();
175        assert_eq!(decoded, t);
176
177        // Alternate construction
178        let mut t = Tuple::new();
179        t.add(TupleField::from_utf8("test"));
180        t.encode(&mut buf).unwrap();
181        assert_eq!(
182            buf.to_vec(),
183            vec![
184                0x01, // 1 tuple field
185                0x04, 0x74, 0x65, 0x73, 0x74
186            ]
187        ); // Field 1: "test"
188        let decoded = Tuple::decode(&mut buf).unwrap();
189        assert_eq!(decoded, t);
190    }
191
192    #[test]
193    fn encode_tuplefield_too_large() {
194        let mut buf = BytesMut::new();
195
196        let t = TupleField {
197            value: vec![0; TupleField::MAX_VALUE_SIZE + 1], // Create a field larger than the max size
198        };
199
200        let encoded = t.encode(&mut buf);
201        assert!(matches!(
202            encoded.unwrap_err(),
203            EncodeError::FieldBoundsExceeded(_)
204        ));
205    }
206
207    #[test]
208    fn decode_tuplefield_too_large() {
209        let mut data: Vec<u8> = vec![0x00; TupleField::MAX_VALUE_SIZE + 1]; // Create a vector with 256 bytes
210                                                                            // 4097 encoded as VarInt
211        data[0] = 0x50;
212        data[1] = 0x01;
213        let mut buf: Bytes = data.into();
214        let decoded = TupleField::decode(&mut buf);
215        assert!(matches!(
216            decoded.unwrap_err(),
217            DecodeError::FieldBoundsExceeded(_)
218        ));
219    }
220}