1use alloc::string::String;
11use alloc::vec::Vec;
12
13use crate::ProtoFieldType;
14use crate::reader::{Reader, WireType};
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub enum Label {
19 Optional,
21 Required,
23 Repeated,
25}
26
27impl Label {
28 fn from_wire(v: i32) -> Self {
29 match v {
30 2 => Self::Required,
31 3 => Self::Repeated,
32 _ => Self::Optional,
33 }
34 }
35}
36
37#[derive(Debug, Clone, PartialEq, Eq)]
39pub struct Field {
40 pub name: String,
42 pub number: i32,
44 pub label: Label,
46 pub ty: Option<ProtoFieldType>,
48 pub type_name: String,
51 pub oneof_index: Option<i32>,
54}
55
56#[derive(Debug, Clone, PartialEq, Eq, Default)]
58pub struct Message {
59 pub name: String,
61 pub fields: Vec<Field>,
63 pub nested: Vec<Message>,
65 pub enums: Vec<Enum>,
67 pub map_entry: bool,
70 pub oneofs: Vec<String>,
73}
74
75#[derive(Debug, Clone, PartialEq, Eq, Default)]
77pub struct Enum {
78 pub name: String,
80 pub values: Vec<(String, i32)>,
82}
83
84#[derive(Debug, Clone, PartialEq, Eq, Default)]
86pub struct File {
87 pub package: String,
89 pub messages: Vec<Message>,
91 pub enums: Vec<Enum>,
93}
94
95#[derive(Debug, Clone, PartialEq, Eq, Default)]
97pub struct FileDescriptorSet {
98 pub files: Vec<File>,
100}
101
102fn read_str(r: &mut Reader<'_>) -> Option<String> {
103 core::str::from_utf8(r.read_len_delimited()?)
104 .ok()
105 .map(String::from)
106}
107
108fn parse_message(bytes: &[u8]) -> Option<Message> {
110 let mut m = Message::default();
111 let mut r = Reader::new(bytes);
112 while !r.at_end() {
113 let (field, wt) = r.read_tag()?;
114 match (field, wt) {
115 (1, WireType::Len) => m.name = read_str(&mut r)?, (2, WireType::Len) => m.fields.push(parse_field(r.read_len_delimited()?)?), (3, WireType::Len) => m.nested.push(parse_message(r.read_len_delimited()?)?), (4, WireType::Len) => m.enums.push(parse_enum(r.read_len_delimited()?)?), (7, WireType::Len) => m.map_entry = parse_message_options(r.read_len_delimited()?)?, (8, WireType::Len) => m.oneofs.push(parse_oneof(r.read_len_delimited()?)?), (_, wt) => r.skip(wt)?,
122 }
123 }
124 Some(m)
125}
126
127fn parse_field(bytes: &[u8]) -> Option<Field> {
128 let mut name = String::new();
129 let mut number = 0i32;
130 let mut label = Label::Optional;
131 let mut ty = None;
132 let mut type_name = String::new();
133 let mut oneof_index = None;
134 let mut r = Reader::new(bytes);
135 while !r.at_end() {
136 let (field, wt) = r.read_tag()?;
137 match (field, wt) {
138 (1, WireType::Len) => name = read_str(&mut r)?, (3, WireType::Varint) => number = i32::try_from(r.read_varint()?).ok()?, (4, WireType::Varint) => {
141 label = Label::from_wire(i32::try_from(r.read_varint()?).ok()?)
142 } (5, WireType::Varint) => {
144 ty = ProtoFieldType::from_wire(i32::try_from(r.read_varint()?).ok()?)
145 } (6, WireType::Len) => type_name = read_str(&mut r)?, (9, WireType::Varint) => oneof_index = Some(i32::try_from(r.read_varint()?).ok()?), (_, wt) => r.skip(wt)?,
149 }
150 }
151 Some(Field {
152 name,
153 number,
154 label,
155 ty,
156 type_name,
157 oneof_index,
158 })
159}
160
161fn parse_oneof(bytes: &[u8]) -> Option<String> {
163 let mut name = String::new();
164 let mut r = Reader::new(bytes);
165 while !r.at_end() {
166 let (field, wt) = r.read_tag()?;
167 match (field, wt) {
168 (1, WireType::Len) => name = read_str(&mut r)?, (_, wt) => r.skip(wt)?,
170 }
171 }
172 Some(name)
173}
174
175fn parse_message_options(bytes: &[u8]) -> Option<bool> {
178 let mut map_entry = false;
179 let mut r = Reader::new(bytes);
180 while !r.at_end() {
181 let (field, wt) = r.read_tag()?;
182 match (field, wt) {
183 (7, WireType::Varint) => map_entry = r.read_varint()? != 0, (_, wt) => r.skip(wt)?,
185 }
186 }
187 Some(map_entry)
188}
189
190fn parse_enum(bytes: &[u8]) -> Option<Enum> {
191 let mut e = Enum::default();
192 let mut r = Reader::new(bytes);
193 while !r.at_end() {
194 let (field, wt) = r.read_tag()?;
195 match (field, wt) {
196 (1, WireType::Len) => e.name = read_str(&mut r)?, (2, WireType::Len) => {
198 let mut vr = Reader::new(r.read_len_delimited()?);
200 let mut vname = String::new();
201 let mut vnum = 0i32;
202 while !vr.at_end() {
203 let (vf, vwt) = vr.read_tag()?;
204 match (vf, vwt) {
205 (1, WireType::Len) => vname = read_str(&mut vr)?,
206 (2, WireType::Varint) => vnum = i32::try_from(vr.read_varint()?).ok()?,
207 (_, vwt) => vr.skip(vwt)?,
208 }
209 }
210 e.values.push((vname, vnum));
211 }
212 (_, wt) => r.skip(wt)?,
213 }
214 }
215 Some(e)
216}
217
218fn parse_file(bytes: &[u8]) -> Option<File> {
219 let mut f = File::default();
220 let mut r = Reader::new(bytes);
221 while !r.at_end() {
222 let (field, wt) = r.read_tag()?;
223 match (field, wt) {
224 (2, WireType::Len) => f.package = read_str(&mut r)?, (4, WireType::Len) => f.messages.push(parse_message(r.read_len_delimited()?)?), (5, WireType::Len) => f.enums.push(parse_enum(r.read_len_delimited()?)?), (_, wt) => r.skip(wt)?,
228 }
229 }
230 Some(f)
231}
232
233impl FileDescriptorSet {
234 #[must_use]
237 pub fn decode(bytes: &[u8]) -> Option<Self> {
238 let mut set = Self::default();
239 let mut r = Reader::new(bytes);
240 while !r.at_end() {
241 let (field, wt) = r.read_tag()?;
242 match (field, wt) {
243 (1, WireType::Len) => set.files.push(parse_file(r.read_len_delimited()?)?), (_, wt) => r.skip(wt)?,
245 }
246 }
247 Some(set)
248 }
249}
250
251#[cfg(test)]
252mod tests {
253 #![allow(clippy::unwrap_used)]
254 use super::*;
255 use alloc::vec;
256
257 #[test]
258 fn parses_a_field_descriptor() {
259 let bytes = [0x0a, 0x01, b'x', 0x18, 0x01, 0x28, 0x05];
261 let f = parse_field(&bytes).unwrap();
262 assert_eq!(f.name, "x");
263 assert_eq!(f.number, 1);
264 assert_eq!(f.ty, Some(ProtoFieldType::Int32));
265 assert_eq!(f.label, Label::Optional);
266 }
267
268 #[test]
269 fn parses_map_entry_option() {
270 let bytes = [0x0a, 0x01, b'E', 0x3a, 0x02, 0x38, 0x01];
273 let m = parse_message(&bytes).unwrap();
274 assert_eq!(m.name, "E");
275 assert!(m.map_entry);
276 }
277
278 #[test]
279 fn parses_oneof_index_and_decl() {
280 let fx = [0x0a, 0x01, b'x', 0x18, 0x01, 0x28, 0x05, 0x48, 0x00];
282 let od = [0x0a, 0x04, b'b', b'o', b'd', b'y'];
284 let mut msg = vec![0x0a, 0x01, b'M'];
286 msg.push(0x12);
287 msg.push(fx.len() as u8);
288 msg.extend_from_slice(&fx);
289 msg.push(0x42);
290 msg.push(od.len() as u8);
291 msg.extend_from_slice(&od);
292
293 let m = parse_message(&msg).unwrap();
294 assert_eq!(m.fields[0].oneof_index, Some(0));
295 assert_eq!(m.oneofs, vec!["body".to_string()]);
296 }
297
298 #[test]
299 fn parses_a_message_with_two_fields() {
300 let fa = [0x0a, 0x01, b'a', 0x18, 0x01, 0x28, 0x09];
302 let fb = [0x0a, 0x01, b'b', 0x18, 0x02, 0x20, 0x03, 0x28, 0x08];
304 let mut msg = vec![0x0a, 0x01, b'M'];
306 msg.push(0x12);
307 msg.push(fa.len() as u8);
308 msg.extend_from_slice(&fa);
309 msg.push(0x12);
310 msg.push(fb.len() as u8);
311 msg.extend_from_slice(&fb);
312
313 let m = parse_message(&msg).unwrap();
314 assert_eq!(m.name, "M");
315 assert_eq!(m.fields.len(), 2);
316 assert_eq!(m.fields[0].name, "a");
317 assert_eq!(m.fields[0].ty, Some(ProtoFieldType::String));
318 assert_eq!(m.fields[1].name, "b");
319 assert_eq!(m.fields[1].number, 2);
320 assert_eq!(m.fields[1].label, Label::Repeated);
321 assert_eq!(m.fields[1].ty, Some(ProtoFieldType::Bool));
322 }
323}