moq_transport/coding/
bounded_string.rs1use 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
43bounded_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, 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]; 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}