• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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