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*/