1 //! Serialization constants. 2 3 // TODO: temporary 4 pub use self::WireType::*; 5 6 /// Tag occupies 3 bits 7 pub const TAG_TYPE_BITS: u32 = 3; 8 /// Tag mask 9 pub const TAG_TYPE_MASK: u32 = (1u32 << TAG_TYPE_BITS) - 1; 10 /// Max possible field number 11 pub const FIELD_NUMBER_MAX: u32 = 0x1fffffff; 12 13 /// One of six defined protobuf wire types 14 #[derive(PartialEq, Eq, Clone, Debug)] 15 pub enum WireType { 16 /// Varint (e. g. `int32` or `sint64`) 17 WireTypeVarint = 0, 18 /// Fixed size 64 bit (e. g. `fixed64` or `double`) 19 WireTypeFixed64 = 1, 20 /// Length-delimited (e. g. `message` or `string`) 21 WireTypeLengthDelimited = 2, 22 /// Groups are not supported by rust-protobuf 23 WireTypeStartGroup = 3, 24 /// Groups are not supported by rust-protobuf 25 WireTypeEndGroup = 4, 26 /// Fixed size 64 bit (e. g. `fixed32` or `float`) 27 WireTypeFixed32 = 5, 28 } 29 30 impl Copy for WireType {} 31 32 impl WireType { 33 /// Parse wire type new(n: u32) -> Option<WireType>34 pub fn new(n: u32) -> Option<WireType> { 35 match n { 36 0 => Some(WireTypeVarint), 37 1 => Some(WireTypeFixed64), 38 2 => Some(WireTypeLengthDelimited), 39 3 => Some(WireTypeStartGroup), 40 4 => Some(WireTypeEndGroup), 41 5 => Some(WireTypeFixed32), 42 _ => None, 43 } 44 } 45 } 46 47 /// Parsed protobuf tag, which is a pair of field number and wire type 48 #[derive(Clone)] 49 pub struct Tag { 50 field_number: u32, 51 wire_type: WireType, 52 } 53 54 impl Copy for Tag {} 55 56 impl Tag { 57 /// Pack a tag to integer value(self) -> u3258 pub fn value(self) -> u32 { 59 (self.field_number << TAG_TYPE_BITS) | (self.wire_type as u32) 60 } 61 62 /// Parse integer into `Tag` object 63 // TODO: should return Result instead of Option new(value: u32) -> Option<Tag>64 pub fn new(value: u32) -> Option<Tag> { 65 let wire_type = WireType::new(value & TAG_TYPE_MASK); 66 if wire_type.is_none() { 67 return None; 68 } 69 let field_number = value >> TAG_TYPE_BITS; 70 if field_number == 0 { 71 return None; 72 } 73 Some(Tag { 74 field_number: field_number, 75 wire_type: wire_type.unwrap(), 76 }) 77 } 78 79 /// Create a tag from a field number and wire type. 80 /// 81 /// # Panics 82 /// 83 /// If field number is outside of allowed range. make(field_number: u32, wire_type: WireType) -> Tag84 pub fn make(field_number: u32, wire_type: WireType) -> Tag { 85 assert!(field_number > 0 && field_number <= FIELD_NUMBER_MAX); 86 Tag { 87 field_number: field_number, 88 wire_type: wire_type, 89 } 90 } 91 92 /// Tag as pair of (field number, wire type) unpack(self) -> (u32, WireType)93 pub fn unpack(self) -> (u32, WireType) { 94 (self.field_number(), self.wire_type()) 95 } 96 wire_type(self) -> WireType97 fn wire_type(self) -> WireType { 98 self.wire_type 99 } 100 101 /// Protobuf field number field_number(self) -> u32102 pub fn field_number(self) -> u32 { 103 self.field_number 104 } 105 } 106