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