1const WIRE_VARINT: u32 = 0;
38const WIRE_64BIT: u32 = 1;
39const WIRE_LEN: u32 = 2;
40const WIRE_32BIT: u32 = 5;
41
42fn encode_varint(buf: &mut Vec<u8>, mut v: u64) {
45 loop {
46 if v < 0x80 {
47 buf.push(v as u8);
48 return;
49 }
50 buf.push((v as u8 & 0x7F) | 0x80);
51 v >>= 7;
52 }
53}
54
55fn decode_varint(buf: &[u8], pos: &mut usize) -> Option<u64> {
56 let mut result: u64 = 0;
57 let mut shift = 0u32;
58 loop {
59 if *pos >= buf.len() {
60 return None;
61 }
62 let byte = buf[*pos];
63 *pos += 1;
64 result |= ((byte & 0x7F) as u64) << shift;
65 if byte < 0x80 {
66 return Some(result);
67 }
68 shift += 7;
69 if shift >= 64 {
70 return None;
71 }
72 }
73}
74
75fn zigzag_encode(v: i64) -> u64 {
76 ((v << 1) ^ (v >> 63)) as u64
77}
78
79fn zigzag_decode(v: u64) -> i64 {
80 ((v >> 1) as i64) ^ (-((v & 1) as i64))
81}
82
83pub struct ProtoEncoder {
87 buf: Vec<u8>,
88}
89
90impl ProtoEncoder {
91 pub fn new() -> Self {
92 Self { buf: Vec::new() }
93 }
94
95 pub fn with_capacity(cap: usize) -> Self {
96 Self {
97 buf: Vec::with_capacity(cap),
98 }
99 }
100
101 fn tag(self, field: u32, wire: u32) -> Self {
102 let mut s = self;
103 encode_varint(&mut s.buf, ((field as u64) << 3) | (wire as u64));
104 s
105 }
106
107 pub fn uint64(self, field: u32, value: u64) -> Self {
110 let mut s = self.tag(field, WIRE_VARINT);
111 encode_varint(&mut s.buf, value);
112 s
113 }
114
115 pub fn uint32(self, field: u32, value: u32) -> Self {
116 self.uint64(field, value as u64)
117 }
118
119 pub fn int64(self, field: u32, value: i64) -> Self {
120 self.uint64(field, value as u64)
121 }
122
123 pub fn int32(self, field: u32, value: i32) -> Self {
124 self.uint64(field, value as u64)
125 }
126
127 pub fn sint64(self, field: u32, value: i64) -> Self {
128 self.uint64(field, zigzag_encode(value))
129 }
130
131 pub fn sint32(self, field: u32, value: i32) -> Self {
132 self.sint64(field, value as i64)
133 }
134
135 pub fn bool(self, field: u32, value: bool) -> Self {
136 self.uint64(field, value as u64)
137 }
138
139 pub fn bytes(self, field: u32, value: &[u8]) -> Self {
142 let mut s = self.tag(field, WIRE_LEN);
143 encode_varint(&mut s.buf, value.len() as u64);
144 s.buf.extend_from_slice(value);
145 s
146 }
147
148 pub fn string(self, field: u32, value: &str) -> Self {
149 self.bytes(field, value.as_bytes())
150 }
151
152 pub fn message(self, field: u32, msg: &ProtoEncoder) -> Self {
154 self.bytes(field, &msg.buf)
155 }
156
157 pub fn fixed64(self, field: u32, value: u64) -> Self {
160 let mut s = self.tag(field, WIRE_64BIT);
161 s.buf.extend_from_slice(&value.to_le_bytes());
162 s
163 }
164
165 pub fn sfixed64(self, field: u32, value: i64) -> Self {
166 self.fixed64(field, value as u64)
167 }
168
169 pub fn double(self, field: u32, value: f64) -> Self {
170 self.fixed64(field, value.to_bits())
171 }
172
173 pub fn fixed32(self, field: u32, value: u32) -> Self {
174 let mut s = self.tag(field, WIRE_32BIT);
175 s.buf.extend_from_slice(&value.to_le_bytes());
176 s
177 }
178
179 pub fn sfixed32(self, field: u32, value: i32) -> Self {
180 self.fixed32(field, value as u32)
181 }
182
183 pub fn float(self, field: u32, value: f32) -> Self {
184 self.fixed32(field, value.to_bits())
185 }
186
187 pub fn as_bytes(&self) -> &[u8] {
190 &self.buf
191 }
192
193 pub fn finish(self) -> Vec<u8> {
194 self.buf
195 }
196
197 pub fn len(&self) -> usize {
198 self.buf.len()
199 }
200
201 pub fn is_empty(&self) -> bool {
202 self.buf.is_empty()
203 }
204}
205
206impl Default for ProtoEncoder {
207 fn default() -> Self {
208 Self::new()
209 }
210}
211
212pub struct ProtoDecoder<'a> {
216 buf: &'a [u8],
217 pos: usize,
218}
219
220pub struct ProtoField<'a> {
222 pub number: u32,
223 pub wire_type: u32,
224 data: FieldData<'a>,
225}
226
227enum FieldData<'a> {
228 Varint(u64),
229 Fixed64([u8; 8]),
230 Bytes(&'a [u8]),
231 Fixed32([u8; 4]),
232}
233
234impl<'a> ProtoField<'a> {
235 pub fn as_u64(&self) -> u64 {
236 match &self.data {
237 FieldData::Varint(v) => *v,
238 FieldData::Fixed64(b) => u64::from_le_bytes(*b),
239 FieldData::Fixed32(b) => u32::from_le_bytes(*b) as u64,
240 FieldData::Bytes(b) => {
241 let mut arr = [0u8; 8];
242 let n = b.len().min(8);
243 arr[..n].copy_from_slice(&b[..n]);
244 u64::from_le_bytes(arr)
245 }
246 }
247 }
248
249 pub fn as_i64(&self) -> i64 {
250 self.as_u64() as i64
251 }
252
253 pub fn as_u32(&self) -> u32 {
254 self.as_u64() as u32
255 }
256
257 pub fn as_i32(&self) -> i32 {
258 self.as_u64() as i32
259 }
260
261 pub fn as_sint64(&self) -> i64 {
262 zigzag_decode(self.as_u64())
263 }
264
265 pub fn as_sint32(&self) -> i32 {
266 self.as_sint64() as i32
267 }
268
269 pub fn as_bool(&self) -> bool {
270 self.as_u64() != 0
271 }
272
273 pub fn as_f64(&self) -> f64 {
274 match &self.data {
275 FieldData::Fixed64(b) => f64::from_bits(u64::from_le_bytes(*b)),
276 _ => self.as_u64() as f64,
277 }
278 }
279
280 pub fn as_f32(&self) -> f32 {
281 match &self.data {
282 FieldData::Fixed32(b) => f32::from_bits(u32::from_le_bytes(*b)),
283 _ => self.as_u64() as f32,
284 }
285 }
286
287 pub fn as_bytes(&self) -> &'a [u8] {
288 match &self.data {
289 FieldData::Bytes(b) => b,
290 _ => &[],
291 }
292 }
293
294 pub fn as_str(&self) -> &'a str {
295 core::str::from_utf8(self.as_bytes()).unwrap_or("")
296 }
297
298 pub fn as_message(&self) -> ProtoDecoder<'a> {
300 ProtoDecoder::new(self.as_bytes())
301 }
302}
303
304impl<'a> ProtoDecoder<'a> {
305 pub fn new(buf: &'a [u8]) -> Self {
306 Self { buf, pos: 0 }
307 }
308
309 pub fn next(&mut self) -> Option<ProtoField<'a>> {
310 if self.pos >= self.buf.len() {
311 return None;
312 }
313 let tag = decode_varint(self.buf, &mut self.pos)?;
314 let wire_type = (tag & 0x07) as u32;
315 let number = (tag >> 3) as u32;
316
317 let data = match wire_type {
318 WIRE_VARINT => {
319 let v = decode_varint(self.buf, &mut self.pos)?;
320 FieldData::Varint(v)
321 }
322 WIRE_64BIT => {
323 if self.pos + 8 > self.buf.len() {
324 return None;
325 }
326 let mut arr = [0u8; 8];
327 arr.copy_from_slice(&self.buf[self.pos..self.pos + 8]);
328 self.pos += 8;
329 FieldData::Fixed64(arr)
330 }
331 WIRE_LEN => {
332 let len = decode_varint(self.buf, &mut self.pos)? as usize;
333 if self.pos + len > self.buf.len() {
334 return None;
335 }
336 let slice = &self.buf[self.pos..self.pos + len];
337 self.pos += len;
338 FieldData::Bytes(slice)
339 }
340 WIRE_32BIT => {
341 if self.pos + 4 > self.buf.len() {
342 return None;
343 }
344 let mut arr = [0u8; 4];
345 arr.copy_from_slice(&self.buf[self.pos..self.pos + 4]);
346 self.pos += 4;
347 FieldData::Fixed32(arr)
348 }
349 _ => return None, };
351
352 Some(ProtoField {
353 number,
354 wire_type,
355 data,
356 })
357 }
358
359 pub fn collect_fields(&mut self) -> Vec<ProtoField<'a>> {
361 let mut fields = Vec::new();
362 while let Some(f) = self.next() {
363 fields.push(f);
364 }
365 fields
366 }
367}