protobuf/reflect/
types.rs

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