1 //! Implementations of `ProtobufType` for all types.
2 
3 use std::marker;
4 use std::mem;
5 
6 #[cfg(feature = "bytes")]
7 use bytes::Bytes;
8 #[cfg(feature = "bytes")]
9 use chars::Chars;
10 
11 use core::Message;
12 use enums::ProtobufEnum;
13 use error::ProtobufResult;
14 use parse_from_bytes;
15 use reflect::ProtobufValue;
16 use rt;
17 use stream::CodedInputStream;
18 use stream::CodedOutputStream;
19 use unknown::UnknownValues;
20 use wire_format::WireType;
21 use zigzag::decode_zig_zag_32;
22 use zigzag::decode_zig_zag_64;
23 
24 /// Protobuf elementary type as generic trait
25 pub trait ProtobufType {
26     /// Rust type of value
27     type Value: ProtobufValue + Clone + 'static;
28 
29     /// Wire type when writing to stream
wire_type() -> WireType30     fn wire_type() -> WireType;
31 
32     /// Read value from `CodedInputStream`
read(is: &mut CodedInputStream) -> ProtobufResult<Self::Value>33     fn read(is: &mut CodedInputStream) -> ProtobufResult<Self::Value>;
34 
35     /// Compute wire size
compute_size(value: &Self::Value) -> u3236     fn compute_size(value: &Self::Value) -> u32;
37 
38     /// Get value from `UnknownValues`
get_from_unknown(unknown_values: &UnknownValues) -> Option<Self::Value>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)
compute_size_with_length_delimiter(value: &Self::Value) -> u3243     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]
get_cached_size(value: &Self::Value) -> u3254     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]
get_cached_size_with_length_delimiter(value: &Self::Value) -> u3260     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
write_with_cached_size( field_number: u32, value: &Self::Value, os: &mut CodedOutputStream, ) -> ProtobufResult<()>70     fn write_with_cached_size(
71         field_number: u32,
72         value: &Self::Value,
73         os: &mut CodedOutputStream,
74     ) -> ProtobufResult<()>;
75 }
76 
77 /// `float`
78 pub struct ProtobufTypeFloat;
79 /// `double`
80 pub struct ProtobufTypeDouble;
81 /// `uint32`
82 pub struct ProtobufTypeInt32;
83 /// `int64`
84 pub struct ProtobufTypeInt64;
85 /// `uint32`
86 pub struct ProtobufTypeUint32;
87 /// `uint64`
88 pub struct ProtobufTypeUint64;
89 /// `sint32`
90 pub struct ProtobufTypeSint32;
91 /// `sint64`
92 pub struct ProtobufTypeSint64;
93 /// `fixed32`
94 pub struct ProtobufTypeFixed32;
95 /// `fixed64`
96 pub struct ProtobufTypeFixed64;
97 /// `sfixed32`
98 pub struct ProtobufTypeSfixed32;
99 /// `sfixed64`
100 pub struct ProtobufTypeSfixed64;
101 /// `bool`
102 pub struct ProtobufTypeBool;
103 /// `string`
104 pub struct ProtobufTypeString;
105 /// `bytes`
106 pub struct ProtobufTypeBytes;
107 /// Something which should be deleted
108 pub struct ProtobufTypeChars;
109 
110 /// `bytes` as [`Bytes`](bytes::Bytes)
111 #[cfg(feature = "bytes")]
112 pub struct ProtobufTypeCarllercheBytes;
113 /// `string` as [`Chars`](crate::Chars)
114 #[cfg(feature = "bytes")]
115 pub struct ProtobufTypeCarllercheChars;
116 
117 /// `enum`
118 pub struct ProtobufTypeEnum<E: ProtobufEnum>(marker::PhantomData<E>);
119 /// `message`
120 pub struct ProtobufTypeMessage<M: Message>(marker::PhantomData<M>);
121 
122 impl ProtobufType for ProtobufTypeFloat {
123     type Value = f32;
124 
wire_type() -> WireType125     fn wire_type() -> WireType {
126         WireType::WireTypeFixed32
127     }
128 
read(is: &mut CodedInputStream) -> ProtobufResult<f32>129     fn read(is: &mut CodedInputStream) -> ProtobufResult<f32> {
130         is.read_float()
131     }
132 
compute_size(_value: &f32) -> u32133     fn compute_size(_value: &f32) -> u32 {
134         4
135     }
136 
get_from_unknown(unknown_values: &UnknownValues) -> Option<f32>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 
write_with_cached_size( field_number: u32, value: &f32, os: &mut CodedOutputStream, ) -> ProtobufResult<()>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 
155 impl ProtobufType for ProtobufTypeDouble {
156     type Value = f64;
157 
wire_type() -> WireType158     fn wire_type() -> WireType {
159         WireType::WireTypeFixed64
160     }
161 
read(is: &mut CodedInputStream) -> ProtobufResult<f64>162     fn read(is: &mut CodedInputStream) -> ProtobufResult<f64> {
163         is.read_double()
164     }
165 
get_from_unknown(unknown_values: &UnknownValues) -> Option<f64>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 
compute_size(_value: &f64) -> u32175     fn compute_size(_value: &f64) -> u32 {
176         8
177     }
178 
write_with_cached_size( field_number: u32, value: &f64, os: &mut CodedOutputStream, ) -> ProtobufResult<()>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 
188 impl ProtobufType for ProtobufTypeInt32 {
189     type Value = i32;
190 
wire_type() -> WireType191     fn wire_type() -> WireType {
192         WireType::WireTypeVarint
193     }
194 
read(is: &mut CodedInputStream) -> ProtobufResult<i32>195     fn read(is: &mut CodedInputStream) -> ProtobufResult<i32> {
196         is.read_int32()
197     }
198 
compute_size(value: &i32) -> u32199     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 
write_with_cached_size( field_number: u32, value: &i32, os: &mut CodedOutputStream, ) -> ProtobufResult<()>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 
get_from_unknown(unknown_values: &UnknownValues) -> Option<i32>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 
220 impl ProtobufType for ProtobufTypeInt64 {
221     type Value = i64;
222 
wire_type() -> WireType223     fn wire_type() -> WireType {
224         WireType::WireTypeVarint
225     }
226 
read(is: &mut CodedInputStream) -> ProtobufResult<i64>227     fn read(is: &mut CodedInputStream) -> ProtobufResult<i64> {
228         is.read_int64()
229     }
230 
get_from_unknown(unknown_values: &UnknownValues) -> Option<i64>231     fn get_from_unknown(unknown_values: &UnknownValues) -> Option<i64> {
232         unknown_values.varint.iter().rev().next().map(|&v| v as i64)
233     }
234 
compute_size(value: &i64) -> u32235     fn compute_size(value: &i64) -> u32 {
236         rt::compute_raw_varint64_size(*value as u64)
237     }
238 
write_with_cached_size( field_number: u32, value: &i64, os: &mut CodedOutputStream, ) -> ProtobufResult<()>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 
248 impl ProtobufType for ProtobufTypeUint32 {
249     type Value = u32;
250 
wire_type() -> WireType251     fn wire_type() -> WireType {
252         WireType::WireTypeVarint
253     }
254 
read(is: &mut CodedInputStream) -> ProtobufResult<u32>255     fn read(is: &mut CodedInputStream) -> ProtobufResult<u32> {
256         is.read_uint32()
257     }
258 
get_from_unknown(unknown_values: &UnknownValues) -> Option<u32>259     fn get_from_unknown(unknown_values: &UnknownValues) -> Option<u32> {
260         unknown_values.varint.iter().rev().next().map(|&v| v as u32)
261     }
262 
compute_size(value: &u32) -> u32263     fn compute_size(value: &u32) -> u32 {
264         rt::compute_raw_varint32_size(*value)
265     }
266 
write_with_cached_size( field_number: u32, value: &u32, os: &mut CodedOutputStream, ) -> ProtobufResult<()>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 
276 impl ProtobufType for ProtobufTypeUint64 {
277     type Value = u64;
278 
wire_type() -> WireType279     fn wire_type() -> WireType {
280         WireType::WireTypeVarint
281     }
282 
read(is: &mut CodedInputStream) -> ProtobufResult<u64>283     fn read(is: &mut CodedInputStream) -> ProtobufResult<u64> {
284         is.read_uint64()
285     }
286 
get_from_unknown(unknown_values: &UnknownValues) -> Option<u64>287     fn get_from_unknown(unknown_values: &UnknownValues) -> Option<u64> {
288         unknown_values.varint.iter().cloned().rev().next()
289     }
290 
compute_size(value: &u64) -> u32291     fn compute_size(value: &u64) -> u32 {
292         rt::compute_raw_varint64_size(*value)
293     }
294 
write_with_cached_size( field_number: u32, value: &u64, os: &mut CodedOutputStream, ) -> ProtobufResult<()>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 
304 impl ProtobufType for ProtobufTypeSint32 {
305     type Value = i32;
306 
wire_type() -> WireType307     fn wire_type() -> WireType {
308         WireType::WireTypeVarint
309     }
310 
read(is: &mut CodedInputStream) -> ProtobufResult<i32>311     fn read(is: &mut CodedInputStream) -> ProtobufResult<i32> {
312         is.read_sint32()
313     }
314 
get_from_unknown(unknown_values: &UnknownValues) -> Option<i32>315     fn get_from_unknown(unknown_values: &UnknownValues) -> Option<i32> {
316         ProtobufTypeUint32::get_from_unknown(unknown_values).map(decode_zig_zag_32)
317     }
318 
compute_size(value: &i32) -> u32319     fn compute_size(value: &i32) -> u32 {
320         rt::value_varint_zigzag_size_no_tag(*value)
321     }
322 
write_with_cached_size( field_number: u32, value: &i32, os: &mut CodedOutputStream, ) -> ProtobufResult<()>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 
332 impl ProtobufType for ProtobufTypeSint64 {
333     type Value = i64;
334 
wire_type() -> WireType335     fn wire_type() -> WireType {
336         WireType::WireTypeVarint
337     }
338 
read(is: &mut CodedInputStream) -> ProtobufResult<i64>339     fn read(is: &mut CodedInputStream) -> ProtobufResult<i64> {
340         is.read_sint64()
341     }
342 
get_from_unknown(unknown_values: &UnknownValues) -> Option<i64>343     fn get_from_unknown(unknown_values: &UnknownValues) -> Option<i64> {
344         ProtobufTypeUint64::get_from_unknown(unknown_values).map(decode_zig_zag_64)
345     }
346 
compute_size(value: &i64) -> u32347     fn compute_size(value: &i64) -> u32 {
348         rt::value_varint_zigzag_size_no_tag(*value)
349     }
350 
write_with_cached_size( field_number: u32, value: &i64, os: &mut CodedOutputStream, ) -> ProtobufResult<()>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 
360 impl ProtobufType for ProtobufTypeFixed32 {
361     type Value = u32;
362 
wire_type() -> WireType363     fn wire_type() -> WireType {
364         WireType::WireTypeFixed32
365     }
366 
read(is: &mut CodedInputStream) -> ProtobufResult<u32>367     fn read(is: &mut CodedInputStream) -> ProtobufResult<u32> {
368         is.read_fixed32()
369     }
370 
get_from_unknown(unknown_values: &UnknownValues) -> Option<u32>371     fn get_from_unknown(unknown_values: &UnknownValues) -> Option<u32> {
372         unknown_values.fixed32.iter().cloned().rev().next()
373     }
374 
compute_size(_value: &u32) -> u32375     fn compute_size(_value: &u32) -> u32 {
376         4
377     }
378 
write_with_cached_size( field_number: u32, value: &u32, os: &mut CodedOutputStream, ) -> ProtobufResult<()>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 
388 impl ProtobufType for ProtobufTypeFixed64 {
389     type Value = u64;
390 
wire_type() -> WireType391     fn wire_type() -> WireType {
392         WireType::WireTypeFixed64
393     }
394 
read(is: &mut CodedInputStream) -> ProtobufResult<u64>395     fn read(is: &mut CodedInputStream) -> ProtobufResult<u64> {
396         is.read_fixed64()
397     }
398 
get_from_unknown(unknown_values: &UnknownValues) -> Option<u64>399     fn get_from_unknown(unknown_values: &UnknownValues) -> Option<u64> {
400         unknown_values.fixed64.iter().cloned().rev().next()
401     }
402 
compute_size(_value: &u64) -> u32403     fn compute_size(_value: &u64) -> u32 {
404         8
405     }
406 
write_with_cached_size( field_number: u32, value: &u64, os: &mut CodedOutputStream, ) -> ProtobufResult<()>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 
416 impl ProtobufType for ProtobufTypeSfixed32 {
417     type Value = i32;
418 
wire_type() -> WireType419     fn wire_type() -> WireType {
420         WireType::WireTypeFixed32
421     }
422 
read(is: &mut CodedInputStream) -> ProtobufResult<i32>423     fn read(is: &mut CodedInputStream) -> ProtobufResult<i32> {
424         is.read_sfixed32()
425     }
426 
get_from_unknown(unknown_values: &UnknownValues) -> Option<i32>427     fn get_from_unknown(unknown_values: &UnknownValues) -> Option<i32> {
428         ProtobufTypeFixed32::get_from_unknown(unknown_values).map(|u| u as i32)
429     }
430 
compute_size(_value: &i32) -> u32431     fn compute_size(_value: &i32) -> u32 {
432         4
433     }
434 
write_with_cached_size( field_number: u32, value: &i32, os: &mut CodedOutputStream, ) -> ProtobufResult<()>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 
444 impl ProtobufType for ProtobufTypeSfixed64 {
445     type Value = i64;
446 
wire_type() -> WireType447     fn wire_type() -> WireType {
448         WireType::WireTypeFixed64
449     }
450 
read(is: &mut CodedInputStream) -> ProtobufResult<i64>451     fn read(is: &mut CodedInputStream) -> ProtobufResult<i64> {
452         is.read_sfixed64()
453     }
454 
get_from_unknown(unknown_values: &UnknownValues) -> Option<i64>455     fn get_from_unknown(unknown_values: &UnknownValues) -> Option<i64> {
456         ProtobufTypeFixed64::get_from_unknown(unknown_values).map(|u| u as i64)
457     }
458 
compute_size(_value: &i64) -> u32459     fn compute_size(_value: &i64) -> u32 {
460         8
461     }
462 
write_with_cached_size( field_number: u32, value: &i64, os: &mut CodedOutputStream, ) -> ProtobufResult<()>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 
472 impl ProtobufType for ProtobufTypeBool {
473     type Value = bool;
474 
wire_type() -> WireType475     fn wire_type() -> WireType {
476         WireType::WireTypeVarint
477     }
478 
read(is: &mut CodedInputStream) -> ProtobufResult<bool>479     fn read(is: &mut CodedInputStream) -> ProtobufResult<bool> {
480         is.read_bool()
481     }
482 
get_from_unknown(unknown: &UnknownValues) -> Option<bool>483     fn get_from_unknown(unknown: &UnknownValues) -> Option<bool> {
484         unknown.varint.iter().rev().next().map(|&v| v != 0)
485     }
486 
compute_size(_value: &bool) -> u32487     fn compute_size(_value: &bool) -> u32 {
488         1
489     }
490 
write_with_cached_size( field_number: u32, value: &bool, os: &mut CodedOutputStream, ) -> ProtobufResult<()>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 
500 impl ProtobufType for ProtobufTypeString {
501     type Value = String;
502 
wire_type() -> WireType503     fn wire_type() -> WireType {
504         WireType::WireTypeLengthDelimited
505     }
506 
read(is: &mut CodedInputStream) -> ProtobufResult<String>507     fn read(is: &mut CodedInputStream) -> ProtobufResult<String> {
508         is.read_string()
509     }
510 
get_from_unknown(unknown_values: &UnknownValues) -> Option<String>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 
compute_size(value: &String) -> u32517     fn compute_size(value: &String) -> u32 {
518         value.len() as u32
519     }
520 
write_with_cached_size( field_number: u32, value: &String, os: &mut CodedOutputStream, ) -> ProtobufResult<()>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 
530 impl ProtobufType for ProtobufTypeBytes {
531     type Value = Vec<u8>;
532 
wire_type() -> WireType533     fn wire_type() -> WireType {
534         WireType::WireTypeLengthDelimited
535     }
536 
read(is: &mut CodedInputStream) -> ProtobufResult<Vec<u8>>537     fn read(is: &mut CodedInputStream) -> ProtobufResult<Vec<u8>> {
538         is.read_bytes()
539     }
540 
get_from_unknown(unknown_values: &UnknownValues) -> Option<Vec<u8>>541     fn get_from_unknown(unknown_values: &UnknownValues) -> Option<Vec<u8>> {
542         unknown_values.length_delimited.iter().cloned().rev().next()
543     }
544 
compute_size(value: &Vec<u8>) -> u32545     fn compute_size(value: &Vec<u8>) -> u32 {
546         value.len() as u32
547     }
548 
write_with_cached_size( field_number: u32, value: &Vec<u8>, os: &mut CodedOutputStream, ) -> ProtobufResult<()>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")]
559 impl ProtobufType for ProtobufTypeCarllercheBytes {
560     type Value = Bytes;
561 
wire_type() -> WireType562     fn wire_type() -> WireType {
563         ProtobufTypeBytes::wire_type()
564     }
565 
read(is: &mut CodedInputStream) -> ProtobufResult<Self::Value>566     fn read(is: &mut CodedInputStream) -> ProtobufResult<Self::Value> {
567         is.read_carllerche_bytes()
568     }
569 
get_from_unknown(unknown_values: &UnknownValues) -> Option<Bytes>570     fn get_from_unknown(unknown_values: &UnknownValues) -> Option<Bytes> {
571         ProtobufTypeBytes::get_from_unknown(unknown_values).map(Bytes::from)
572     }
573 
compute_size(value: &Bytes) -> u32574     fn compute_size(value: &Bytes) -> u32 {
575         value.len() as u32
576     }
577 
write_with_cached_size( field_number: u32, value: &Bytes, os: &mut CodedOutputStream, ) -> ProtobufResult<()>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")]
588 impl ProtobufType for ProtobufTypeCarllercheChars {
589     type Value = Chars;
590 
wire_type() -> WireType591     fn wire_type() -> WireType {
592         ProtobufTypeBytes::wire_type()
593     }
594 
read(is: &mut CodedInputStream) -> ProtobufResult<Self::Value>595     fn read(is: &mut CodedInputStream) -> ProtobufResult<Self::Value> {
596         is.read_carllerche_chars()
597     }
598 
get_from_unknown(unknown_values: &UnknownValues) -> Option<Chars>599     fn get_from_unknown(unknown_values: &UnknownValues) -> Option<Chars> {
600         ProtobufTypeString::get_from_unknown(unknown_values).map(Chars::from)
601     }
602 
compute_size(value: &Chars) -> u32603     fn compute_size(value: &Chars) -> u32 {
604         value.len() as u32
605     }
606 
write_with_cached_size( field_number: u32, value: &Chars, os: &mut CodedOutputStream, ) -> ProtobufResult<()>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 
616 impl<E: ProtobufEnum + ProtobufValue> ProtobufType for ProtobufTypeEnum<E> {
617     type Value = E;
618 
wire_type() -> WireType619     fn wire_type() -> WireType {
620         WireType::WireTypeVarint
621     }
622 
read(is: &mut CodedInputStream) -> ProtobufResult<E>623     fn read(is: &mut CodedInputStream) -> ProtobufResult<E> {
624         is.read_enum()
625     }
626 
get_from_unknown(unknown_values: &UnknownValues) -> Option<E>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 
compute_size(value: &E) -> u32633     fn compute_size(value: &E) -> u32 {
634         rt::compute_raw_varint32_size(value.value() as u32) // TODO: wrap
635     }
636 
write_with_cached_size( field_number: u32, value: &E, os: &mut CodedOutputStream, ) -> ProtobufResult<()>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 
646 impl<M: Message + Clone + ProtobufValue> ProtobufType for ProtobufTypeMessage<M> {
647     type Value = M;
648 
wire_type() -> WireType649     fn wire_type() -> WireType {
650         WireType::WireTypeLengthDelimited
651     }
652 
read(is: &mut CodedInputStream) -> ProtobufResult<M>653     fn read(is: &mut CodedInputStream) -> ProtobufResult<M> {
654         is.read_message()
655     }
656 
get_from_unknown(unknown_values: &UnknownValues) -> Option<M>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 
compute_size(value: &M) -> u32667     fn compute_size(value: &M) -> u32 {
668         value.compute_size()
669     }
670 
get_cached_size(value: &M) -> u32671     fn get_cached_size(value: &M) -> u32 {
672         value.get_cached_size()
673     }
674 
write_with_cached_size( field_number: u32, value: &Self::Value, os: &mut CodedOutputStream, ) -> ProtobufResult<()>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 }
686