Skip to main content

nrc_protobuf/reflect/
value.rs

1use std::any::Any;
2
3#[cfg(feature = "bytes")]
4use bytes::Bytes;
5#[cfg(feature = "bytes")]
6use chars::Chars;
7
8use super::*;
9
10/// Type implemented by all protobuf elementary types
11/// (ints, floats, bool, string, bytes, enums, messages).
12pub trait ProtobufValue: Any + 'static {
13    /// As ref
14    fn as_ref(&self) -> ProtobufValueRef;
15
16    /// Convert to `Any`
17    fn as_any(&self) -> &Any {
18        unimplemented!()
19    }
20
21    /// Is value non-zero?
22    fn is_non_zero(&self) -> bool {
23        self.as_ref().is_non_zero()
24    }
25
26    /// Return `ProtobufValueRef` if self is `Copy`.
27    ///
28    /// # Panics
29    ///
30    /// if `Self` is not `Copy`.
31    fn as_ref_copy(&self) -> ProtobufValueRef<'static>
32//where Self : Copy // TODO
33    {
34        match self.as_ref() {
35            ProtobufValueRef::Bool(v) => ProtobufValueRef::Bool(v),
36            ProtobufValueRef::U32(v) => ProtobufValueRef::U32(v),
37            ProtobufValueRef::U64(v) => ProtobufValueRef::U64(v),
38            ProtobufValueRef::I32(v) => ProtobufValueRef::I32(v),
39            ProtobufValueRef::I64(v) => ProtobufValueRef::I64(v),
40            ProtobufValueRef::F32(v) => ProtobufValueRef::F32(v),
41            ProtobufValueRef::F64(v) => ProtobufValueRef::F64(v),
42            ProtobufValueRef::Enum(v) => ProtobufValueRef::Enum(v),
43            ProtobufValueRef::String(..)
44            | ProtobufValueRef::Bytes(..)
45            | ProtobufValueRef::Message(..) => unreachable!(),
46        }
47    }
48}
49
50impl ProtobufValue for u32 {
51    fn as_ref(&self) -> ProtobufValueRef {
52        ProtobufValueRef::U32(*self)
53    }
54}
55
56impl ProtobufValue for u64 {
57    fn as_ref(&self) -> ProtobufValueRef {
58        ProtobufValueRef::U64(*self)
59    }
60}
61
62impl ProtobufValue for i32 {
63    fn as_ref(&self) -> ProtobufValueRef {
64        ProtobufValueRef::I32(*self)
65    }
66}
67
68impl ProtobufValue for i64 {
69    fn as_ref(&self) -> ProtobufValueRef {
70        ProtobufValueRef::I64(*self)
71    }
72}
73
74impl ProtobufValue for f32 {
75    fn as_ref(&self) -> ProtobufValueRef {
76        ProtobufValueRef::F32(*self)
77    }
78}
79
80impl ProtobufValue for f64 {
81    fn as_ref(&self) -> ProtobufValueRef {
82        ProtobufValueRef::F64(*self)
83    }
84}
85
86impl ProtobufValue for bool {
87    fn as_ref(&self) -> ProtobufValueRef {
88        ProtobufValueRef::Bool(*self)
89    }
90}
91
92impl ProtobufValue for String {
93    fn as_ref(&self) -> ProtobufValueRef {
94        ProtobufValueRef::String(*&self)
95    }
96}
97
98impl ProtobufValue for str {
99    fn as_ref(&self) -> ProtobufValueRef {
100        ProtobufValueRef::String(self)
101    }
102}
103
104impl ProtobufValue for Vec<u8> {
105    fn as_ref(&self) -> ProtobufValueRef {
106        ProtobufValueRef::Bytes(*&self)
107    }
108}
109
110#[cfg(feature = "bytes")]
111impl ProtobufValue for Bytes {
112    fn as_ref(&self) -> ProtobufValueRef {
113        ProtobufValueRef::Bytes(&*self)
114    }
115}
116
117#[cfg(feature = "bytes")]
118impl ProtobufValue for Chars {
119    fn as_ref(&self) -> ProtobufValueRef {
120        ProtobufValueRef::String(&*self)
121    }
122}
123
124// conflicting implementations, so generated code is used instead
125/*
126impl<E : ProtobufEnum> ProtobufValue for E {
127    fn as_ref(&self) -> ProtobufValueRef {
128        ProtobufValueRef::Enum(self.descriptor())
129    }
130}
131
132impl<M : Message> ProtobufValue for M {
133    fn as_ref(&self) -> ProtobufValueRef {
134        ProtobufValueRef::Message(self)
135    }
136}
137*/
138
139/// Dynamic reference to a value
140pub enum ProtobufValueRef<'a> {
141    /// `u32`
142    U32(u32),
143    /// `u64`
144    U64(u64),
145    /// `i32`
146    I32(i32),
147    /// `i64`
148    I64(i64),
149    /// `f32`
150    F32(f32),
151    /// `f64`
152    F64(f64),
153    /// `bool`
154    Bool(bool),
155    /// `string`
156    String(&'a str),
157    /// `bytes`
158    Bytes(&'a [u8]),
159    /// `enum`
160    Enum(&'static EnumValueDescriptor),
161    /// `message`
162    Message(&'a Message),
163}
164
165impl<'a> ProtobufValueRef<'a> {
166    /// Is value non-zero?
167    pub fn is_non_zero(&self) -> bool {
168        match *self {
169            ProtobufValueRef::U32(v) => v != 0,
170            ProtobufValueRef::U64(v) => v != 0,
171            ProtobufValueRef::I32(v) => v != 0,
172            ProtobufValueRef::I64(v) => v != 0,
173            ProtobufValueRef::F32(v) => v != 0.,
174            ProtobufValueRef::F64(v) => v != 0.,
175            ProtobufValueRef::Bool(v) => v,
176            ProtobufValueRef::String(v) => !v.is_empty(),
177            ProtobufValueRef::Bytes(v) => !v.is_empty(),
178            ProtobufValueRef::Enum(v) => v.value() != 0,
179            ProtobufValueRef::Message(_) => true,
180        }
181    }
182}