blob: 20244a176528030aca7f84be1195b3a9694fafb6 [file] [log] [blame]
Chih-Hung Hsiehcfc3a232020-06-10 20:13:05 -07001//! Implementations of `ProtobufType` for all types.
2
3use std::marker;
4use std::mem;
5
6#[cfg(feature = "bytes")]
Haibo Huangd32e6ee2020-08-12 13:52:04 -07007use bytes::Bytes;
Chih-Hung Hsiehcfc3a232020-06-10 20:13:05 -07008
David LeGare793d84b2022-03-02 16:21:10 +00009#[cfg(feature = "bytes")]
10use crate::chars::Chars;
Joel Galensonfa77f002021-04-02 11:32:01 -070011use crate::coded_input_stream::CodedInputStream;
12use crate::coded_output_stream::CodedOutputStream;
Haibo Huangd32e6ee2020-08-12 13:52:04 -070013use crate::enums::ProtobufEnum;
14use crate::error::ProtobufResult;
15use crate::message::Message;
Haibo Huangd32e6ee2020-08-12 13:52:04 -070016use crate::reflect::ProtobufValue;
17use crate::rt;
Haibo Huangd32e6ee2020-08-12 13:52:04 -070018use crate::unknown::UnknownValues;
19use crate::wire_format::WireType;
20use crate::zigzag::decode_zig_zag_32;
21use crate::zigzag::decode_zig_zag_64;
Chih-Hung Hsiehcfc3a232020-06-10 20:13:05 -070022
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()
Haibo Huang914311b2021-01-07 18:06:15 -0800663 .map(|bytes| M::parse_from_bytes(bytes).expect("cannot parse message"))
Chih-Hung Hsiehcfc3a232020-06-10 20:13:05 -0700664 }
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}