Skip to main content

serde_protobuf/
value.rs

1//! Types for representing runtime Protobuf values.
2use std::collections;
3
4use protobuf;
5use protobuf::wire_format;
6
7use crate::descriptor;
8use crate::error;
9
10/// Any protobuf value.
11#[derive(Clone, Debug)]
12pub enum Value {
13    /// A boolean value.
14    Bool(bool),
15    /// A 32-bit signed integer.
16    I32(i32),
17    /// A 64-bit signed integer.
18    I64(i64),
19    /// A 32-bit unsigned integer.
20    U32(u32),
21    /// A 64-bit unsigned integer.
22    U64(u64),
23    /// A 32-bit floating point value.
24    F32(f32),
25    /// A 64-bit floating point value.
26    F64(f64),
27    /// A byte vector.
28    Bytes(Vec<u8>),
29    /// A string.
30    String(String),
31    /// An enum value.
32    Enum(i32),
33    /// A message.
34    Message(Message),
35}
36
37/// A message value.
38#[derive(Clone, Debug)]
39pub struct Message {
40    /// Known fields on the message.
41    pub fields: collections::BTreeMap<i32, Field>,
42    /// Unknown fields on the message.
43    pub unknown: protobuf::UnknownFields,
44}
45
46/// A message field value.
47#[derive(Clone, Debug)]
48pub enum Field {
49    /// A field with a single value.
50    Singular(Option<Value>),
51    /// A field with several (repeated) values.
52    Repeated(Vec<Value>),
53}
54
55impl Message {
56    /// Creates a message given a Protobuf descriptor.
57    #[inline]
58    pub fn new(message: &descriptor::MessageDescriptor) -> Message {
59        let mut m = Message {
60            fields: collections::BTreeMap::new(),
61            unknown: protobuf::UnknownFields::new(),
62        };
63
64        for field in message.fields() {
65            m.fields.insert(
66                field.number(),
67                if field.is_repeated() {
68                    Field::Repeated(Vec::new())
69                } else {
70                    Field::Singular(field.default_value().cloned())
71                },
72            );
73        }
74
75        m
76    }
77
78    /// Merge data from the given input stream into this message.
79    #[inline]
80    pub fn merge_from(
81        &mut self,
82        descriptors: &descriptor::Descriptors,
83        message: &descriptor::MessageDescriptor,
84        input: &mut protobuf::CodedInputStream,
85    ) -> error::Result<()> {
86        while !input.eof()? {
87            let (number, wire_type) = input.read_tag_unpack()?;
88
89            if let Some(field) = message.field_by_number(number as i32) {
90                let value = self.ensure_field(field);
91                value.merge_from(descriptors, field, input, wire_type)?;
92            } else {
93                use protobuf::rt::read_unknown_or_skip_group as u;
94                u(number, wire_type, input, &mut self.unknown)?;
95            }
96        }
97        Ok(())
98    }
99
100    #[inline]
101    fn ensure_field(&mut self, field: &descriptor::FieldDescriptor) -> &mut Field {
102        self.fields
103            .entry(field.number())
104            .or_insert_with(|| Field::new(field))
105    }
106}
107
108impl Field {
109    /// Creates a field given a Protobuf descriptor.
110    #[inline]
111    pub fn new(field: &descriptor::FieldDescriptor) -> Field {
112        if field.is_repeated() {
113            Field::Repeated(Vec::new())
114        } else {
115            Field::Singular(None)
116        }
117    }
118
119    /// Merge data from the given input stream into this field.
120    #[inline]
121    pub fn merge_from(
122        &mut self,
123        descriptors: &descriptor::Descriptors,
124        field: &descriptor::FieldDescriptor,
125        input: &mut protobuf::CodedInputStream,
126        wire_type: protobuf::wire_format::WireType,
127    ) -> error::Result<()> {
128        // Make the type dispatch below more compact
129        use crate::descriptor::FieldType::*;
130        use protobuf::wire_format::WireType::*;
131        use protobuf::CodedInputStream as I;
132
133        // Singular scalar
134        macro_rules! ss {
135            ($expected_wire_type:expr, $visit_func:expr, $reader:expr) => {
136                self.merge_scalar(input, wire_type, $expected_wire_type, $visit_func, $reader)
137            };
138        }
139
140        // Packable scalar
141        macro_rules! ps {
142            ($expected_wire_type:expr, $visit_func:expr, $reader:expr) => {
143                self.merge_packable_scalar(
144                    input,
145                    wire_type,
146                    $expected_wire_type,
147                    $visit_func,
148                    $reader,
149                )
150            };
151            ($expected_wire_type:expr, $size:expr, $visit_func:expr, $reader:expr) => {
152                // TODO: use size to pre-allocate buffer space
153                self.merge_packable_scalar(
154                    input,
155                    wire_type,
156                    $expected_wire_type,
157                    $visit_func,
158                    $reader,
159                )
160            };
161        }
162
163        match field.field_type(descriptors) {
164            Bool => ps!(WireTypeVarint, Value::Bool, I::read_bool),
165            Int32 => ps!(WireTypeVarint, Value::I32, I::read_int32),
166            Int64 => ps!(WireTypeVarint, Value::I64, I::read_int64),
167            SInt32 => ps!(WireTypeVarint, Value::I32, I::read_sint32),
168            SInt64 => ps!(WireTypeVarint, Value::I64, I::read_sint64),
169            UInt32 => ps!(WireTypeVarint, Value::U32, I::read_uint32),
170            UInt64 => ps!(WireTypeVarint, Value::U64, I::read_uint64),
171            Fixed32 => ps!(WireTypeFixed32, 4, Value::U32, I::read_fixed32),
172            Fixed64 => ps!(WireTypeFixed64, 8, Value::U64, I::read_fixed64),
173            SFixed32 => ps!(WireTypeFixed32, 4, Value::I32, I::read_sfixed32),
174            SFixed64 => ps!(WireTypeFixed64, 8, Value::I64, I::read_sfixed64),
175            Float => ps!(WireTypeFixed32, 4, Value::F32, I::read_float),
176            Double => ps!(WireTypeFixed64, 8, Value::F64, I::read_double),
177            Bytes => ss!(WireTypeLengthDelimited, Value::Bytes, I::read_bytes),
178            String => ss!(WireTypeLengthDelimited, Value::String, I::read_string),
179            Enum(_) => self.merge_enum(input, wire_type),
180            Message(ref m) => self.merge_message(input, descriptors, m, wire_type),
181            Group => unimplemented!(),
182            UnresolvedEnum(e) => Err(error::Error::UnknownEnum { name: e.to_owned() }),
183            UnresolvedMessage(m) => Err(error::Error::UnknownMessage { name: m.to_owned() }),
184        }
185    }
186
187    #[inline]
188    fn merge_scalar<'a, A, V, R>(
189        &mut self,
190        input: &mut protobuf::CodedInputStream<'a>,
191        actual_wire_type: wire_format::WireType,
192        expected_wire_type: wire_format::WireType,
193        value_ctor: V,
194        reader: R,
195    ) -> error::Result<()>
196    where
197        V: Fn(A) -> Value,
198        R: Fn(&mut protobuf::CodedInputStream<'a>) -> protobuf::ProtobufResult<A>,
199    {
200        if expected_wire_type == actual_wire_type {
201            self.put(value_ctor(reader(input)?));
202            Ok(())
203        } else {
204            Err(error::Error::BadWireType {
205                wire_type: actual_wire_type,
206            })
207        }
208    }
209
210    #[inline]
211    fn merge_packable_scalar<'a, A, V, R>(
212        &mut self,
213        input: &mut protobuf::CodedInputStream<'a>,
214        actual_wire_type: wire_format::WireType,
215        expected_wire_type: wire_format::WireType,
216        value_ctor: V,
217        reader: R,
218    ) -> error::Result<()>
219    where
220        V: Fn(A) -> Value,
221        R: Fn(&mut protobuf::CodedInputStream<'a>) -> protobuf::ProtobufResult<A>,
222    {
223        if wire_format::WireType::WireTypeLengthDelimited == actual_wire_type {
224            let len = input.read_raw_varint64()?;
225
226            let old_limit = input.push_limit(len)?;
227            while !input.eof()? {
228                self.put(value_ctor(reader(input)?));
229            }
230            input.pop_limit(old_limit);
231
232            Ok(())
233        } else {
234            self.merge_scalar(
235                input,
236                actual_wire_type,
237                expected_wire_type,
238                value_ctor,
239                reader,
240            )
241        }
242    }
243
244    #[inline]
245    fn merge_enum(
246        &mut self,
247        input: &mut protobuf::CodedInputStream,
248        actual_wire_type: wire_format::WireType,
249    ) -> error::Result<()> {
250        if wire_format::WireType::WireTypeVarint == actual_wire_type {
251            let v = input.read_raw_varint32()? as i32;
252            self.put(Value::Enum(v));
253            Ok(())
254        } else {
255            Err(error::Error::BadWireType {
256                wire_type: actual_wire_type,
257            })
258        }
259    }
260
261    #[inline]
262    fn merge_message(
263        &mut self,
264        input: &mut protobuf::CodedInputStream,
265        descriptors: &descriptor::Descriptors,
266        message: &descriptor::MessageDescriptor,
267        actual_wire_type: wire_format::WireType,
268    ) -> error::Result<()> {
269        if wire_format::WireType::WireTypeLengthDelimited == actual_wire_type {
270            let len = input.read_raw_varint64()?;
271            let mut msg = match *self {
272                Field::Singular(ref mut o) => {
273                    if let Some(Value::Message(m)) = o.take() {
274                        m
275                    } else {
276                        Message::new(message)
277                    }
278                }
279                _ => Message::new(message),
280            };
281
282            let old_limit = input.push_limit(len)?;
283            msg.merge_from(descriptors, message, input)?;
284            input.pop_limit(old_limit);
285
286            self.put(Value::Message(msg));
287            Ok(())
288        } else {
289            Err(error::Error::BadWireType {
290                wire_type: actual_wire_type,
291            })
292        }
293    }
294
295    #[inline]
296    fn put(&mut self, value: Value) {
297        match *self {
298            Field::Singular(ref mut s) => *s = Some(value),
299            Field::Repeated(ref mut r) => r.push(value),
300        }
301    }
302}