protobuf/
types.rs

1//! Implementations of `ProtobufType` for all types.
2
3use std::marker;
4use std::mem;
5
6#[cfg(feature = "bytes")]
7use bytes::Bytes;
8
9#[cfg(feature = "bytes")]
10use crate::chars::Chars;
11use crate::coded_input_stream::CodedInputStream;
12use crate::coded_output_stream::CodedOutputStream;
13use crate::enums::ProtobufEnum;
14use crate::error::ProtobufResult;
15use crate::message::Message;
16use crate::reflect::ProtobufValue;
17use crate::rt;
18use crate::unknown::UnknownValues;
19use crate::wire_format::WireType;
20use crate::zigzag::decode_zig_zag_32;
21use crate::zigzag::decode_zig_zag_64;
22
23/// Protobuf elementary type as generic trait
24pub trait ProtobufType {
25    /// Rust type of value
26    type Value: ProtobufValue + Clone + 'static;
27
28    /// Wire type when writing to stream
29    fn wire_type() -> WireType;
30
31    /// Read value from `CodedInputStream`
32    fn read(is: &mut CodedInputStream) -> ProtobufResult<Self::Value>;
33
34    /// Compute wire size
35    fn compute_size(value: &Self::Value) -> u32;
36
37    /// Get value from `UnknownValues`
38    fn get_from_unknown(unknown_values: &UnknownValues) -> Option<Self::Value>;
39
40    /// Compute size adding length prefix if wire type is length delimited
41    /// (i. e. string, bytes, message)
42    fn compute_size_with_length_delimiter(value: &Self::Value) -> u32 {
43        let size = Self::compute_size(value);
44        if Self::wire_type() == WireType::WireTypeLengthDelimited {
45            rt::compute_raw_varint32_size(size) + size
46        } else {
47            size
48        }
49    }
50
51    /// Get previously computed size
52    #[inline]
53    fn get_cached_size(value: &Self::Value) -> u32 {
54        Self::compute_size(value)
55    }
56
57    /// Get previously cached size with length prefix
58    #[inline]
59    fn get_cached_size_with_length_delimiter(value: &Self::Value) -> u32 {
60        let size = Self::get_cached_size(value);
61        if Self::wire_type() == WireType::WireTypeLengthDelimited {
62            rt::compute_raw_varint32_size(size) + size
63        } else {
64            size
65        }
66    }
67
68    /// Write a value with previously cached size
69    fn write_with_cached_size(
70        field_number: u32,
71        value: &Self::Value,
72        os: &mut CodedOutputStream,
73    ) -> ProtobufResult<()>;
74}
75
76/// `float`
77pub struct ProtobufTypeFloat;
78/// `double`
79pub struct ProtobufTypeDouble;
80/// `uint32`
81pub struct ProtobufTypeInt32;
82/// `int64`
83pub struct ProtobufTypeInt64;
84/// `uint32`
85pub struct ProtobufTypeUint32;
86/// `uint64`
87pub struct ProtobufTypeUint64;
88/// `sint32`
89pub struct ProtobufTypeSint32;
90/// `sint64`
91pub struct ProtobufTypeSint64;
92/// `fixed32`
93pub struct ProtobufTypeFixed32;
94/// `fixed64`
95pub struct ProtobufTypeFixed64;
96/// `sfixed32`
97pub struct ProtobufTypeSfixed32;
98/// `sfixed64`
99pub struct ProtobufTypeSfixed64;
100/// `bool`
101pub struct ProtobufTypeBool;
102/// `string`
103pub struct ProtobufTypeString;
104/// `bytes`
105pub struct ProtobufTypeBytes;
106/// Something which should be deleted
107pub struct ProtobufTypeChars;
108
109/// `bytes` as [`Bytes`](bytes::Bytes)
110#[cfg(feature = "bytes")]
111pub struct ProtobufTypeCarllercheBytes;
112/// `string` as [`Chars`](crate::Chars)
113#[cfg(feature = "bytes")]
114pub struct ProtobufTypeCarllercheChars;
115
116/// `enum`
117pub struct ProtobufTypeEnum<E: ProtobufEnum>(marker::PhantomData<E>);
118/// `message`
119pub struct ProtobufTypeMessage<M: Message>(marker::PhantomData<M>);
120
121impl ProtobufType for ProtobufTypeFloat {
122    type Value = f32;
123
124    fn wire_type() -> WireType {
125        WireType::WireTypeFixed32
126    }
127
128    fn read(is: &mut CodedInputStream) -> ProtobufResult<f32> {
129        is.read_float()
130    }
131
132    fn compute_size(_value: &f32) -> u32 {
133        4
134    }
135
136    fn get_from_unknown(unknown_values: &UnknownValues) -> Option<f32> {
137        unknown_values
138            .fixed32
139            .iter()
140            .rev()
141            .next()
142            .map(|&bits| unsafe { mem::transmute::<u32, f32>(bits) })
143    }
144
145    fn write_with_cached_size(
146        field_number: u32,
147        value: &f32,
148        os: &mut CodedOutputStream,
149    ) -> ProtobufResult<()> {
150        os.write_float(field_number, *value)
151    }
152}
153
154impl ProtobufType for ProtobufTypeDouble {
155    type Value = f64;
156
157    fn wire_type() -> WireType {
158        WireType::WireTypeFixed64
159    }
160
161    fn read(is: &mut CodedInputStream) -> ProtobufResult<f64> {
162        is.read_double()
163    }
164
165    fn get_from_unknown(unknown_values: &UnknownValues) -> Option<f64> {
166        unknown_values
167            .fixed64
168            .iter()
169            .rev()
170            .next()
171            .map(|&bits| unsafe { mem::transmute::<u64, f64>(bits) })
172    }
173
174    fn compute_size(_value: &f64) -> u32 {
175        8
176    }
177
178    fn write_with_cached_size(
179        field_number: u32,
180        value: &f64,
181        os: &mut CodedOutputStream,
182    ) -> ProtobufResult<()> {
183        os.write_double(field_number, *value)
184    }
185}
186
187impl ProtobufType for ProtobufTypeInt32 {
188    type Value = i32;
189
190    fn wire_type() -> WireType {
191        WireType::WireTypeVarint
192    }
193
194    fn read(is: &mut CodedInputStream) -> ProtobufResult<i32> {
195        is.read_int32()
196    }
197
198    fn compute_size(value: &i32) -> u32 {
199        // See also: https://github.com/protocolbuffers/protobuf/blob/bd00671b924310c0353a730bf8fa77c44e0a9c72/src/google/protobuf/io/coded_stream.h#L1300-L1306
200        if *value < 0 {
201            return 10;
202        }
203        rt::compute_raw_varint32_size(*value as u32)
204    }
205
206    fn write_with_cached_size(
207        field_number: u32,
208        value: &i32,
209        os: &mut CodedOutputStream,
210    ) -> ProtobufResult<()> {
211        os.write_int32(field_number, *value)
212    }
213
214    fn get_from_unknown(unknown_values: &UnknownValues) -> Option<i32> {
215        unknown_values.varint.iter().rev().next().map(|&v| v as i32)
216    }
217}
218
219impl ProtobufType for ProtobufTypeInt64 {
220    type Value = i64;
221
222    fn wire_type() -> WireType {
223        WireType::WireTypeVarint
224    }
225
226    fn read(is: &mut CodedInputStream) -> ProtobufResult<i64> {
227        is.read_int64()
228    }
229
230    fn get_from_unknown(unknown_values: &UnknownValues) -> Option<i64> {
231        unknown_values.varint.iter().rev().next().map(|&v| v as i64)
232    }
233
234    fn compute_size(value: &i64) -> u32 {
235        rt::compute_raw_varint64_size(*value as u64)
236    }
237
238    fn write_with_cached_size(
239        field_number: u32,
240        value: &i64,
241        os: &mut CodedOutputStream,
242    ) -> ProtobufResult<()> {
243        os.write_int64(field_number, *value)
244    }
245}
246
247impl ProtobufType for ProtobufTypeUint32 {
248    type Value = u32;
249
250    fn wire_type() -> WireType {
251        WireType::WireTypeVarint
252    }
253
254    fn read(is: &mut CodedInputStream) -> ProtobufResult<u32> {
255        is.read_uint32()
256    }
257
258    fn get_from_unknown(unknown_values: &UnknownValues) -> Option<u32> {
259        unknown_values.varint.iter().rev().next().map(|&v| v as u32)
260    }
261
262    fn compute_size(value: &u32) -> u32 {
263        rt::compute_raw_varint32_size(*value)
264    }
265
266    fn write_with_cached_size(
267        field_number: u32,
268        value: &u32,
269        os: &mut CodedOutputStream,
270    ) -> ProtobufResult<()> {
271        os.write_uint32(field_number, *value)
272    }
273}
274
275impl ProtobufType for ProtobufTypeUint64 {
276    type Value = u64;
277
278    fn wire_type() -> WireType {
279        WireType::WireTypeVarint
280    }
281
282    fn read(is: &mut CodedInputStream) -> ProtobufResult<u64> {
283        is.read_uint64()
284    }
285
286    fn get_from_unknown(unknown_values: &UnknownValues) -> Option<u64> {
287        unknown_values.varint.iter().cloned().rev().next()
288    }
289
290    fn compute_size(value: &u64) -> u32 {
291        rt::compute_raw_varint64_size(*value)
292    }
293
294    fn write_with_cached_size(
295        field_number: u32,
296        value: &u64,
297        os: &mut CodedOutputStream,
298    ) -> ProtobufResult<()> {
299        os.write_uint64(field_number, *value)
300    }
301}
302
303impl ProtobufType for ProtobufTypeSint32 {
304    type Value = i32;
305
306    fn wire_type() -> WireType {
307        WireType::WireTypeVarint
308    }
309
310    fn read(is: &mut CodedInputStream) -> ProtobufResult<i32> {
311        is.read_sint32()
312    }
313
314    fn get_from_unknown(unknown_values: &UnknownValues) -> Option<i32> {
315        ProtobufTypeUint32::get_from_unknown(unknown_values).map(decode_zig_zag_32)
316    }
317
318    fn compute_size(value: &i32) -> u32 {
319        rt::value_varint_zigzag_size_no_tag(*value)
320    }
321
322    fn write_with_cached_size(
323        field_number: u32,
324        value: &i32,
325        os: &mut CodedOutputStream,
326    ) -> ProtobufResult<()> {
327        os.write_sint32(field_number, *value)
328    }
329}
330
331impl ProtobufType for ProtobufTypeSint64 {
332    type Value = i64;
333
334    fn wire_type() -> WireType {
335        WireType::WireTypeVarint
336    }
337
338    fn read(is: &mut CodedInputStream) -> ProtobufResult<i64> {
339        is.read_sint64()
340    }
341
342    fn get_from_unknown(unknown_values: &UnknownValues) -> Option<i64> {
343        ProtobufTypeUint64::get_from_unknown(unknown_values).map(decode_zig_zag_64)
344    }
345
346    fn compute_size(value: &i64) -> u32 {
347        rt::value_varint_zigzag_size_no_tag(*value)
348    }
349
350    fn write_with_cached_size(
351        field_number: u32,
352        value: &i64,
353        os: &mut CodedOutputStream,
354    ) -> ProtobufResult<()> {
355        os.write_sint64(field_number, *value)
356    }
357}
358
359impl ProtobufType for ProtobufTypeFixed32 {
360    type Value = u32;
361
362    fn wire_type() -> WireType {
363        WireType::WireTypeFixed32
364    }
365
366    fn read(is: &mut CodedInputStream) -> ProtobufResult<u32> {
367        is.read_fixed32()
368    }
369
370    fn get_from_unknown(unknown_values: &UnknownValues) -> Option<u32> {
371        unknown_values.fixed32.iter().cloned().rev().next()
372    }
373
374    fn compute_size(_value: &u32) -> u32 {
375        4
376    }
377
378    fn write_with_cached_size(
379        field_number: u32,
380        value: &u32,
381        os: &mut CodedOutputStream,
382    ) -> ProtobufResult<()> {
383        os.write_fixed32(field_number, *value)
384    }
385}
386
387impl ProtobufType for ProtobufTypeFixed64 {
388    type Value = u64;
389
390    fn wire_type() -> WireType {
391        WireType::WireTypeFixed64
392    }
393
394    fn read(is: &mut CodedInputStream) -> ProtobufResult<u64> {
395        is.read_fixed64()
396    }
397
398    fn get_from_unknown(unknown_values: &UnknownValues) -> Option<u64> {
399        unknown_values.fixed64.iter().cloned().rev().next()
400    }
401
402    fn compute_size(_value: &u64) -> u32 {
403        8
404    }
405
406    fn write_with_cached_size(
407        field_number: u32,
408        value: &u64,
409        os: &mut CodedOutputStream,
410    ) -> ProtobufResult<()> {
411        os.write_fixed64(field_number, *value)
412    }
413}
414
415impl ProtobufType for ProtobufTypeSfixed32 {
416    type Value = i32;
417
418    fn wire_type() -> WireType {
419        WireType::WireTypeFixed32
420    }
421
422    fn read(is: &mut CodedInputStream) -> ProtobufResult<i32> {
423        is.read_sfixed32()
424    }
425
426    fn get_from_unknown(unknown_values: &UnknownValues) -> Option<i32> {
427        ProtobufTypeFixed32::get_from_unknown(unknown_values).map(|u| u as i32)
428    }
429
430    fn compute_size(_value: &i32) -> u32 {
431        4
432    }
433
434    fn write_with_cached_size(
435        field_number: u32,
436        value: &i32,
437        os: &mut CodedOutputStream,
438    ) -> ProtobufResult<()> {
439        os.write_sfixed32(field_number, *value)
440    }
441}
442
443impl ProtobufType for ProtobufTypeSfixed64 {
444    type Value = i64;
445
446    fn wire_type() -> WireType {
447        WireType::WireTypeFixed64
448    }
449
450    fn read(is: &mut CodedInputStream) -> ProtobufResult<i64> {
451        is.read_sfixed64()
452    }
453
454    fn get_from_unknown(unknown_values: &UnknownValues) -> Option<i64> {
455        ProtobufTypeFixed64::get_from_unknown(unknown_values).map(|u| u as i64)
456    }
457
458    fn compute_size(_value: &i64) -> u32 {
459        8
460    }
461
462    fn write_with_cached_size(
463        field_number: u32,
464        value: &i64,
465        os: &mut CodedOutputStream,
466    ) -> ProtobufResult<()> {
467        os.write_sfixed64(field_number, *value)
468    }
469}
470
471impl ProtobufType for ProtobufTypeBool {
472    type Value = bool;
473
474    fn wire_type() -> WireType {
475        WireType::WireTypeVarint
476    }
477
478    fn read(is: &mut CodedInputStream) -> ProtobufResult<bool> {
479        is.read_bool()
480    }
481
482    fn get_from_unknown(unknown: &UnknownValues) -> Option<bool> {
483        unknown.varint.iter().rev().next().map(|&v| v != 0)
484    }
485
486    fn compute_size(_value: &bool) -> u32 {
487        1
488    }
489
490    fn write_with_cached_size(
491        field_number: u32,
492        value: &bool,
493        os: &mut CodedOutputStream,
494    ) -> ProtobufResult<()> {
495        os.write_bool(field_number, *value)
496    }
497}
498
499impl ProtobufType for ProtobufTypeString {
500    type Value = String;
501
502    fn wire_type() -> WireType {
503        WireType::WireTypeLengthDelimited
504    }
505
506    fn read(is: &mut CodedInputStream) -> ProtobufResult<String> {
507        is.read_string()
508    }
509
510    fn get_from_unknown(unknown_values: &UnknownValues) -> Option<String> {
511        // TODO: should not panic
512        ProtobufTypeBytes::get_from_unknown(unknown_values)
513            .map(|b| String::from_utf8(b).expect("not a valid string"))
514    }
515
516    fn compute_size(value: &String) -> u32 {
517        value.len() as u32
518    }
519
520    fn write_with_cached_size(
521        field_number: u32,
522        value: &String,
523        os: &mut CodedOutputStream,
524    ) -> ProtobufResult<()> {
525        os.write_string(field_number, &value)
526    }
527}
528
529impl ProtobufType for ProtobufTypeBytes {
530    type Value = Vec<u8>;
531
532    fn wire_type() -> WireType {
533        WireType::WireTypeLengthDelimited
534    }
535
536    fn read(is: &mut CodedInputStream) -> ProtobufResult<Vec<u8>> {
537        is.read_bytes()
538    }
539
540    fn get_from_unknown(unknown_values: &UnknownValues) -> Option<Vec<u8>> {
541        unknown_values.length_delimited.iter().cloned().rev().next()
542    }
543
544    fn compute_size(value: &Vec<u8>) -> u32 {
545        value.len() as u32
546    }
547
548    fn write_with_cached_size(
549        field_number: u32,
550        value: &Vec<u8>,
551        os: &mut CodedOutputStream,
552    ) -> ProtobufResult<()> {
553        os.write_bytes(field_number, &value)
554    }
555}
556
557#[cfg(feature = "bytes")]
558impl ProtobufType for ProtobufTypeCarllercheBytes {
559    type Value = Bytes;
560
561    fn wire_type() -> WireType {
562        ProtobufTypeBytes::wire_type()
563    }
564
565    fn read(is: &mut CodedInputStream) -> ProtobufResult<Self::Value> {
566        is.read_carllerche_bytes()
567    }
568
569    fn get_from_unknown(unknown_values: &UnknownValues) -> Option<Bytes> {
570        ProtobufTypeBytes::get_from_unknown(unknown_values).map(Bytes::from)
571    }
572
573    fn compute_size(value: &Bytes) -> u32 {
574        value.len() as u32
575    }
576
577    fn write_with_cached_size(
578        field_number: u32,
579        value: &Bytes,
580        os: &mut CodedOutputStream,
581    ) -> ProtobufResult<()> {
582        os.write_bytes(field_number, &value)
583    }
584}
585
586#[cfg(feature = "bytes")]
587impl ProtobufType for ProtobufTypeCarllercheChars {
588    type Value = Chars;
589
590    fn wire_type() -> WireType {
591        ProtobufTypeBytes::wire_type()
592    }
593
594    fn read(is: &mut CodedInputStream) -> ProtobufResult<Self::Value> {
595        is.read_carllerche_chars()
596    }
597
598    fn get_from_unknown(unknown_values: &UnknownValues) -> Option<Chars> {
599        ProtobufTypeString::get_from_unknown(unknown_values).map(Chars::from)
600    }
601
602    fn compute_size(value: &Chars) -> u32 {
603        value.len() as u32
604    }
605
606    fn write_with_cached_size(
607        field_number: u32,
608        value: &Chars,
609        os: &mut CodedOutputStream,
610    ) -> ProtobufResult<()> {
611        os.write_string(field_number, &value)
612    }
613}
614
615impl<E: ProtobufEnum + ProtobufValue> ProtobufType for ProtobufTypeEnum<E> {
616    type Value = E;
617
618    fn wire_type() -> WireType {
619        WireType::WireTypeVarint
620    }
621
622    fn read(is: &mut CodedInputStream) -> ProtobufResult<E> {
623        is.read_enum()
624    }
625
626    fn get_from_unknown(unknown_values: &UnknownValues) -> Option<E> {
627        // TODO: do not panic
628        ProtobufTypeInt32::get_from_unknown(unknown_values)
629            .map(|i| E::from_i32(i).expect("not a valid enum value"))
630    }
631
632    fn compute_size(value: &E) -> u32 {
633        rt::compute_raw_varint32_size(value.value() as u32) // TODO: wrap
634    }
635
636    fn write_with_cached_size(
637        field_number: u32,
638        value: &E,
639        os: &mut CodedOutputStream,
640    ) -> ProtobufResult<()> {
641        os.write_enum_obj(field_number, *value)
642    }
643}
644
645impl<M: Message + Clone + ProtobufValue> ProtobufType for ProtobufTypeMessage<M> {
646    type Value = M;
647
648    fn wire_type() -> WireType {
649        WireType::WireTypeLengthDelimited
650    }
651
652    fn read(is: &mut CodedInputStream) -> ProtobufResult<M> {
653        is.read_message()
654    }
655
656    fn get_from_unknown(unknown_values: &UnknownValues) -> Option<M> {
657        // TODO: do not panic
658        unknown_values
659            .length_delimited
660            .iter()
661            .rev()
662            .next()
663            .map(|bytes| M::parse_from_bytes(bytes).expect("cannot parse message"))
664    }
665
666    fn compute_size(value: &M) -> u32 {
667        value.compute_size()
668    }
669
670    fn get_cached_size(value: &M) -> u32 {
671        value.get_cached_size()
672    }
673
674    fn write_with_cached_size(
675        field_number: u32,
676        value: &Self::Value,
677        os: &mut CodedOutputStream,
678    ) -> ProtobufResult<()> {
679        os.write_tag(field_number, WireType::WireTypeLengthDelimited)?;
680        os.write_raw_varint32(value.get_cached_size())?;
681        value.write_to_with_cached_sizes(os)?;
682        Ok(())
683    }
684}