moq_lite/ietf/
group.rs

1use crate::coding::{Decode, DecodeError, Encode};
2
3const SUBGROUP_ID: u8 = 0x0;
4
5pub struct Group {
6	pub request_id: u64,
7	pub group_id: u64,
8
9	// Each object has extensions.
10	pub has_extensions: bool,
11
12	// There's an explicit subgroup on the wire.
13	pub has_subgroup: bool,
14
15	// Use the first object ID as the subgroup ID
16	// Since we don't support subgroups or object ID > 0, this is trivial to support.
17	// Not compatibile with has_subgroup
18	pub has_subgroup_object: bool,
19
20	// There's an implicit end marker when the stream is closed.
21	pub has_end: bool,
22}
23
24impl Encode for Group {
25	fn encode<W: bytes::BufMut>(&self, w: &mut W) {
26		assert!(
27			!self.has_subgroup || !self.has_subgroup_object,
28			"has_subgroup and has_subgroup_object cannot be true at the same time"
29		);
30
31		let mut id: u8 = 0x10; // Base value
32		if self.has_extensions {
33			id |= 0x01;
34		}
35		if self.has_subgroup {
36			id |= 0x02;
37		}
38		if self.has_subgroup_object {
39			id |= 0x04;
40		}
41		if self.has_end {
42			id |= 0x08;
43		}
44		id.encode(w);
45
46		self.request_id.encode(w);
47		self.group_id.encode(w);
48
49		if self.has_subgroup {
50			SUBGROUP_ID.encode(w);
51		}
52
53		// Publisher priority
54		0u8.encode(w);
55	}
56}
57
58impl Decode for Group {
59	fn decode<R: bytes::Buf>(r: &mut R) -> Result<Self, DecodeError> {
60		let id = u64::decode(r)?;
61		if !(0x10..=0x1D).contains(&id) {
62			return Err(DecodeError::InvalidValue);
63		}
64
65		let has_extensions = (id & 0x01) != 0;
66		let has_subgroup = (id & 0x02) != 0;
67		let has_subgroup_object = (id & 0x04) != 0;
68		let has_end = (id & 0x08) != 0;
69
70		if has_subgroup && has_subgroup_object {
71			return Err(DecodeError::InvalidValue);
72		}
73
74		let request_id = u64::decode(r)?;
75		let group_id = u64::decode(r)?;
76
77		if has_subgroup {
78			let subgroup_id = u8::decode(r)?;
79			if subgroup_id != SUBGROUP_ID {
80				return Err(DecodeError::Unsupported);
81			}
82		}
83
84		let _publisher_priority = u8::decode(r)?;
85
86		Ok(Self {
87			request_id,
88			group_id,
89			has_extensions,
90			has_subgroup,
91			has_subgroup_object,
92			has_end,
93		})
94	}
95}
96
97/* We use an optimized streaming version to avoid buffering the entire frame.
98pub struct Object {
99	// If None, this is the end of the group.
100	pub payload: Option<Vec<u8>>,
101}
102
103impl Encode for Object {
104	fn encode<W: bytes::BufMut>(&self, w: &mut W) {
105		0u8.encode(w); // id_delta == 0
106
107		let size = self.payload.as_ref().map(|p| p.len()).unwrap_or(0);
108		size.encode(w);
109
110		match &self.payload {
111			Some(payload) if !payload.is_empty() => w.put_slice(payload),
112			Some(_) => 0u8.encode(w),
113			None => GROUP_END.encode(w),
114		}
115	}
116}
117
118impl Decode for Object {
119	fn decode<R: bytes::Buf>(r: &mut R) -> Result<Self, DecodeError> {
120		let id_delta = u64::decode(r)?;
121		if id_delta != 0 {
122			return Err(DecodeError::Unsupported);
123		}
124
125		let size = u64::decode(r)?;
126
127		if r.remaining() < size as usize {
128			return Err(DecodeError::Short);
129		}
130
131		if size > 0 {
132			let payload = r.copy_to_bytes(size as usize).to_vec();
133			Ok(Self { payload: Some(payload) })
134		} else {
135			match u8::decode(r)? {
136				0 => Ok(Self {
137					payload: Some(Vec::new()),
138				}),
139				GROUP_END => Ok(Self { payload: None }),
140				_ => Err(DecodeError::InvalidValue),
141			}
142		}
143	}
144}
145
146// The same as Object, but when extensions have been negotiated.
147// They're always ignored of course.
148pub struct ObjectExtensions {
149	// If None, this is the end of the group.
150	pub payload: Option<Vec<u8>>,
151}
152
153impl Encode for ObjectExtensions {
154	fn encode<W: bytes::BufMut>(&self, w: &mut W) {
155		0u8.encode(w); // id_delta == 0
156
157		// zero length extensions
158		0u8.encode(w);
159
160		let size = self.payload.as_ref().map(|p| p.len()).unwrap_or(0);
161		size.encode(w);
162
163		match &self.payload {
164			Some(payload) if !payload.is_empty() => w.put_slice(payload),
165			Some(_) => 0u8.encode(w),
166			None => GROUP_END.encode(w),
167		}
168	}
169}
170
171impl Decode for ObjectExtensions {
172	fn decode<R: bytes::Buf>(r: &mut R) -> Result<Self, DecodeError> {
173		let id_delta = u64::decode(r)?;
174		if id_delta != 0 {
175			return Err(DecodeError::Unsupported);
176		}
177
178		let size = u64::decode(r)?;
179		if r.remaining() < size as usize {
180			return Err(DecodeError::Short);
181		}
182
183		// Skip the extensions
184		r.advance(size as usize);
185
186		let size = u64::decode(r)?;
187		if r.remaining() < size as usize {
188			return Err(DecodeError::Short);
189		}
190
191		if size > 0 {
192			let payload = r.copy_to_bytes(size as usize).to_vec();
193			Ok(Self { payload: Some(payload) })
194		} else {
195			match u8::decode(r)? {
196				0 => Ok(Self {
197					payload: Some(Vec::new()),
198				}),
199				GROUP_END => Ok(Self { payload: None }),
200				_ => Err(DecodeError::InvalidValue),
201			}
202		}
203	}
204}
205
206*/