Skip to main content

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