Skip to main content

moq_transport/coding/
bounded_string.rs

1use super::{Decode, DecodeError, Encode, EncodeError};
2
3macro_rules! bounded_string {
4    ($name:ident, $max_len:expr) => {
5        #[derive(Clone, Debug, Default, Eq, PartialEq)]
6        pub struct $name(pub String);
7
8        impl $name {
9            pub const MAX_LEN: usize = $max_len;
10        }
11
12        impl Encode for $name {
13            fn encode<W: bytes::BufMut>(&self, w: &mut W) -> Result<(), EncodeError> {
14                if self.0.len() > Self::MAX_LEN {
15                    return Err(EncodeError::FieldBoundsExceeded(
16                        stringify!($name).to_string(),
17                    ));
18                }
19                self.0.len().encode(w)?;
20                Self::encode_remaining(w, self.0.len())?;
21                w.put(self.0.as_ref());
22                Ok(())
23            }
24        }
25
26        impl Decode for $name {
27            fn decode<R: bytes::Buf>(r: &mut R) -> Result<Self, DecodeError> {
28                let size = usize::decode(r)?;
29                if size > Self::MAX_LEN {
30                    return Err(DecodeError::FieldBoundsExceeded(
31                        stringify!($name).to_string(),
32                    ));
33                }
34                Self::decode_remaining(r, size)?;
35                let mut buf = vec![0; size];
36                r.copy_to_slice(&mut buf);
37                Ok($name(String::from_utf8(buf)?))
38            }
39        }
40    };
41}
42
43// Implementations of bounded strings
44bounded_string!(ReasonPhrase, 1024);
45bounded_string!(SessionUri, 8192);
46
47#[cfg(test)]
48mod tests {
49    use super::*;
50    use bytes::Bytes;
51    use bytes::BytesMut;
52
53    #[test]
54    fn encode_decode() {
55        let mut buf = BytesMut::new();
56
57        let r = ReasonPhrase("testreason".to_string());
58        r.encode(&mut buf).unwrap();
59        assert_eq!(
60            buf.to_vec(),
61            vec![
62                0x0a, // Length of "testreason" is 10
63                0x74, 0x65, 0x73, 0x74, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e
64            ]
65        );
66        let decoded = ReasonPhrase::decode(&mut buf).unwrap();
67        assert_eq!(decoded, r);
68    }
69
70    #[test]
71    fn encode_too_large() {
72        let mut buf = BytesMut::new();
73
74        let r = ReasonPhrase("x".repeat(1025));
75        let encoded = r.encode(&mut buf);
76        assert!(matches!(
77            encoded.unwrap_err(),
78            EncodeError::FieldBoundsExceeded(_)
79        ));
80    }
81
82    #[test]
83    fn decode_too_large() {
84        let mut data: Vec<u8> = vec![0x00; 1025]; // Create a vector with 1025 bytes
85                                                  // Set first 2 bytes as length of 1025 as a VarInt
86        data[0] = 0x44;
87        data[1] = 0x01;
88        let mut buf: Bytes = data.into();
89        let decoded = ReasonPhrase::decode(&mut buf);
90        assert!(matches!(
91            decoded.unwrap_err(),
92            DecodeError::FieldBoundsExceeded(_)
93        ));
94    }
95}