1 //! Constants used in serializations.
2 
3 use crate::descriptor::field_descriptor_proto;
4 use crate::error::WireError;
5 
6 /// Tag occupies three bits.
7 pub(crate) const TAG_TYPE_BITS: u32 = 3;
8 /// Apply this mask to varint value to obtain a tag.
9 pub(crate) const TAG_TYPE_MASK: u32 = (1u32 << TAG_TYPE_BITS as usize) - 1;
10 /// Max possible field number
11 pub(crate) const FIELD_NUMBER_MAX: u32 = 0x1fffffff;
12 
13 pub(crate) const MAX_MESSAGE_SIZE: u64 = i32::MAX as u64;
14 
15 #[inline]
check_message_size(size: u64) -> crate::Result<u32>16 pub(crate) fn check_message_size(size: u64) -> crate::Result<u32> {
17     if size <= MAX_MESSAGE_SIZE {
18         Ok(size as u32)
19     } else {
20         #[cold]
21         fn message_too_large(size: u64) -> crate::Error {
22             WireError::MessageTooLarge(size).into()
23         }
24 
25         Err(message_too_large(size))
26     }
27 }
28 
29 /// All supported "wire types" are listed in this enum.
30 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
31 pub enum WireType {
32     /// Variable-length integer
33     Varint = 0,
34     /// 32-bit field (e. g. `fixed64` or `double`)
35     Fixed64 = 1,
36     /// Length-delimited field
37     LengthDelimited = 2,
38     /// Groups are not supported in rust-protobuf
39     StartGroup = 3,
40     /// Groups are not supported in rust-protobuf
41     EndGroup = 4,
42     /// 32-bit field (e. g. `fixed32` or `float`)
43     Fixed32 = 5,
44 }
45 
46 impl WireType {
47     /// Construct `WireType` from number, or return `None` if type is unknown.
new(n: u32) -> Option<WireType>48     pub fn new(n: u32) -> Option<WireType> {
49         match n {
50             0 => Some(WireType::Varint),
51             1 => Some(WireType::Fixed64),
52             2 => Some(WireType::LengthDelimited),
53             3 => Some(WireType::StartGroup),
54             4 => Some(WireType::EndGroup),
55             5 => Some(WireType::Fixed32),
56             _ => None,
57         }
58     }
59 
60     #[doc(hidden)]
for_type(field_type: field_descriptor_proto::Type) -> WireType61     pub fn for_type(field_type: field_descriptor_proto::Type) -> WireType {
62         use field_descriptor_proto::Type;
63         match field_type {
64             Type::TYPE_INT32 => WireType::Varint,
65             Type::TYPE_INT64 => WireType::Varint,
66             Type::TYPE_UINT32 => WireType::Varint,
67             Type::TYPE_UINT64 => WireType::Varint,
68             Type::TYPE_SINT32 => WireType::Varint,
69             Type::TYPE_SINT64 => WireType::Varint,
70             Type::TYPE_BOOL => WireType::Varint,
71             Type::TYPE_ENUM => WireType::Varint,
72             Type::TYPE_FIXED32 => WireType::Fixed32,
73             Type::TYPE_FIXED64 => WireType::Fixed64,
74             Type::TYPE_SFIXED32 => WireType::Fixed32,
75             Type::TYPE_SFIXED64 => WireType::Fixed64,
76             Type::TYPE_FLOAT => WireType::Fixed32,
77             Type::TYPE_DOUBLE => WireType::Fixed64,
78             Type::TYPE_STRING => WireType::LengthDelimited,
79             Type::TYPE_BYTES => WireType::LengthDelimited,
80             Type::TYPE_MESSAGE => WireType::LengthDelimited,
81             Type::TYPE_GROUP => WireType::LengthDelimited, // not true
82         }
83     }
84 }
85 
86 /// Parsed field tag (a pair of field number and wire type)
87 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
88 pub(crate) struct Tag {
89     field_number: u32,
90     wire_type: WireType,
91 }
92 
93 impl Tag {
94     /// Fold tag to a number to be serialized.
value(self) -> u3295     pub(crate) fn value(self) -> u32 {
96         (self.field_number << TAG_TYPE_BITS) | (self.wire_type as u32)
97     }
98 
99     /// Extract wire type and field number from integer tag
new(value: u32) -> crate::Result<Tag>100     pub(crate) fn new(value: u32) -> crate::Result<Tag> {
101         let wire_type = WireType::new(value & TAG_TYPE_MASK);
102         if wire_type.is_none() {
103             return Err(WireError::IncorrectTag(value).into());
104         }
105         let field_number = value >> TAG_TYPE_BITS;
106         if field_number == 0 {
107             return Err(WireError::IncorrectTag(value).into());
108         }
109         Ok(Tag {
110             field_number,
111             wire_type: wire_type.unwrap(),
112         })
113     }
114 
115     /// Construct a tag from a field number and wire type.
116     ///
117     /// # Panics
118     ///
119     /// If field number is outside of valid range.
make(field_number: u32, wire_type: WireType) -> Tag120     pub(crate) fn make(field_number: u32, wire_type: WireType) -> Tag {
121         assert!(field_number > 0 && field_number <= FIELD_NUMBER_MAX);
122         Tag {
123             field_number,
124             wire_type,
125         }
126     }
127 
128     /// Get field number and wire type
unpack(self) -> (u32, WireType)129     pub(crate) fn unpack(self) -> (u32, WireType) {
130         (self.field_number(), self.wire_type())
131     }
132 
133     /// Get wire type
wire_type(self) -> WireType134     fn wire_type(self) -> WireType {
135         self.wire_type
136     }
137 
138     /// Get field number
field_number(self) -> u32139     pub(crate) fn field_number(self) -> u32 {
140         self.field_number
141     }
142 }
143