megacommerce_shared/utils/
grpc.rs1use std::fmt;
2
3use megacommerce_proto::Any;
4
5#[derive(Debug, Clone)]
6pub enum AnyValue {
7 String(String),
8 Bool(bool),
9 Int32(i32),
10 Int64(i64),
11 Float(f32),
12 Double(f64),
13 Bytes(Vec<u8>),
14 Unknown(Vec<u8>),
15}
16
17impl AnyValue {
18 pub fn from_string(s: String) -> Self {
19 AnyValue::String(s)
20 }
21
22 pub fn from_str(s: &str) -> Self {
23 AnyValue::String(s.to_string())
24 }
25
26 pub fn from_bool(b: bool) -> Self {
27 AnyValue::Bool(b)
28 }
29
30 pub fn from_int32(i: i32) -> Self {
31 AnyValue::Int32(i)
32 }
33
34 pub fn from_int64(i: i64) -> Self {
35 AnyValue::Int64(i)
36 }
37
38 pub fn from_float(f: f32) -> Self {
39 AnyValue::Float(f)
40 }
41
42 pub fn from_double(d: f64) -> Self {
43 AnyValue::Double(d)
44 }
45
46 pub fn from_bytes(bytes: Vec<u8>) -> Self {
47 AnyValue::Bytes(bytes)
48 }
49
50 pub fn from_slice(slice: &[u8]) -> Self {
51 AnyValue::Bytes(slice.to_vec())
52 }
53
54 pub fn from_unknown(bytes: Vec<u8>) -> Self {
55 AnyValue::Unknown(bytes)
56 }
57
58 pub fn from_unknown_slice(slice: &[u8]) -> Self {
60 AnyValue::Unknown(slice.to_vec())
61 }
62
63 pub fn as_string(&self) -> Option<&String> {
65 match self {
66 AnyValue::String(s) => Some(s),
67 _ => None,
68 }
69 }
70
71 pub fn as_bool(&self) -> Option<bool> {
72 match self {
73 AnyValue::Bool(b) => Some(*b),
74 _ => None,
75 }
76 }
77
78 pub fn as_int32(&self) -> Option<i32> {
79 match self {
80 AnyValue::Int32(i) => Some(*i),
81 _ => None,
82 }
83 }
84
85 pub fn as_int64(&self) -> Option<i64> {
86 match self {
87 AnyValue::Int64(i) => Some(*i),
88 _ => None,
89 }
90 }
91
92 pub fn as_float(&self) -> Option<f32> {
93 match self {
94 AnyValue::Float(f) => Some(*f),
95 _ => None,
96 }
97 }
98
99 pub fn as_double(&self) -> Option<f64> {
100 match self {
101 AnyValue::Double(d) => Some(*d),
102 _ => None,
103 }
104 }
105
106 pub fn as_bytes(&self) -> Option<&Vec<u8>> {
107 match self {
108 AnyValue::Bytes(bytes) => Some(bytes),
109 _ => None,
110 }
111 }
112
113 pub fn as_unknown(&self) -> Option<&Vec<u8>> {
114 match self {
115 AnyValue::Unknown(bytes) => Some(bytes),
116 _ => None,
117 }
118 }
119
120 pub fn is_string(&self) -> bool {
122 matches!(self, AnyValue::String(_))
123 }
124
125 pub fn is_bool(&self) -> bool {
126 matches!(self, AnyValue::Bool(_))
127 }
128
129 pub fn is_int32(&self) -> bool {
130 matches!(self, AnyValue::Int32(_))
131 }
132
133 pub fn is_int64(&self) -> bool {
134 matches!(self, AnyValue::Int64(_))
135 }
136
137 pub fn is_float(&self) -> bool {
138 matches!(self, AnyValue::Float(_))
139 }
140
141 pub fn is_double(&self) -> bool {
142 matches!(self, AnyValue::Double(_))
143 }
144
145 pub fn is_bytes(&self) -> bool {
146 matches!(self, AnyValue::Bytes(_))
147 }
148
149 pub fn is_unknown(&self) -> bool {
150 matches!(self, AnyValue::Unknown(_))
151 }
152}
153
154pub fn grpc_deserialize_any(any: &Any) -> AnyValue {
155 match any.type_url.as_str() {
156 "type.googleapis.com/google.protobuf.StringValue" => String::from_utf8(any.value.clone())
157 .map(AnyValue::String)
158 .unwrap_or_else(|_| AnyValue::Unknown(any.value.clone())),
159 "type.googleapis.com/google.protobuf.BoolValue" => {
160 AnyValue::Bool(any.value.first().map(|&b| b != 0).unwrap_or(false))
161 }
162 "type.googleapis.com/google.protobuf.Int32Value" => any
163 .value
164 .as_slice()
165 .try_into()
166 .map(|bytes| AnyValue::Int32(i32::from_le_bytes(bytes)))
167 .unwrap_or(AnyValue::Unknown(any.value.clone())),
168 "type.googleapis.com/google.protobuf.Int64Value" => any
169 .value
170 .as_slice()
171 .try_into()
172 .map(|bytes| AnyValue::Int64(i64::from_le_bytes(bytes)))
173 .unwrap_or(AnyValue::Unknown(any.value.clone())),
174 "type.googleapis.com/google.protobuf.FloatValue" => any
175 .value
176 .as_slice()
177 .try_into()
178 .map(|bytes| AnyValue::Float(f32::from_le_bytes(bytes)))
179 .unwrap_or(AnyValue::Unknown(any.value.clone())),
180 "type.googleapis.com/google.protobuf.DoubleValue" => any
181 .value
182 .as_slice()
183 .try_into()
184 .map(|bytes| AnyValue::Double(f64::from_le_bytes(bytes)))
185 .unwrap_or(AnyValue::Unknown(any.value.clone())),
186 "type.googleapis.com/google.protobuf.BytesValue" => AnyValue::Bytes(any.value.clone()),
187 _ => AnyValue::Unknown(any.value.clone()),
188 }
189}
190
191impl fmt::Display for AnyValue {
192 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
193 match self {
194 AnyValue::String(s) => write!(f, "string:\"{}\"", s),
195 AnyValue::Bool(b) => write!(f, "bool:{}", b),
196 AnyValue::Int32(i) => write!(f, "i32:{}", i),
197 AnyValue::Int64(i) => write!(f, "i64:{}", i),
198 AnyValue::Float(n) => write!(f, "float:{}", n),
199 AnyValue::Double(n) => write!(f, "double:{}", n),
200 AnyValue::Bytes(bytes) => {
201 if bytes.len() <= 8 {
202 write!(f, "bytes:{}", hex::encode(bytes))
203 } else {
204 write!(f, "bytes:{}...", hex::encode(&bytes[..8]))
205 }
206 }
207 AnyValue::Unknown(bytes) => {
208 if bytes.len() <= 8 {
209 write!(f, "unknown:{}", hex::encode(bytes))
210 } else {
211 write!(f, "unknown:{}...", hex::encode(&bytes[..8]))
212 }
213 }
214 }
215 }
216}
217
218pub trait AnyExt {
219 fn from_string(s: String) -> Any;
220 fn from_str(s: &str) -> Any;
221 fn from_bool(b: bool) -> Any;
222 fn from_int32(i: i32) -> Any;
223 fn from_int64(i: i64) -> Any;
224 fn from_float(f: f32) -> Any;
225 fn from_double(d: f64) -> Any;
226 fn from_bytes(bytes: Vec<u8>) -> Any;
227 fn from_slice(slice: &[u8]) -> Any;
228 fn from_value<T: Into<AnyValue>>(value: T) -> Any;
229
230 fn is_string(&self) -> bool;
232 fn is_bool(&self) -> bool;
233 fn is_int32(&self) -> bool;
234 fn is_int64(&self) -> bool;
235 fn is_float(&self) -> bool;
236 fn is_double(&self) -> bool;
237 fn is_bytes(&self) -> bool;
238 fn is_unknown(&self) -> bool;
239}
240
241impl AnyExt for Any {
242 fn from_string(s: String) -> Any {
243 Any {
244 type_url: "type.googleapis.com/google.protobuf.StringValue".to_string(),
245 value: s.into_bytes(),
246 }
247 }
248
249 fn from_str(s: &str) -> Any {
250 Self::from_string(s.to_string())
251 }
252
253 fn from_bool(b: bool) -> Any {
254 Any {
255 type_url: "type.googleapis.com/google.protobuf.BoolValue".to_string(),
256 value: vec![b as u8],
257 }
258 }
259
260 fn from_int32(i: i32) -> Any {
261 Any {
262 type_url: "type.googleapis.com/google.protobuf.Int32Value".to_string(),
263 value: i.to_le_bytes().to_vec(),
264 }
265 }
266
267 fn from_int64(i: i64) -> Any {
268 Any {
269 type_url: "type.googleapis.com/google.protobuf.Int64Value".to_string(),
270 value: i.to_le_bytes().to_vec(),
271 }
272 }
273
274 fn from_float(f: f32) -> Any {
275 Any {
276 type_url: "type.googleapis.com/google.protobuf.FloatValue".to_string(),
277 value: f.to_le_bytes().to_vec(),
278 }
279 }
280
281 fn from_double(d: f64) -> Any {
282 Any {
283 type_url: "type.googleapis.com/google.protobuf.DoubleValue".to_string(),
284 value: d.to_le_bytes().to_vec(),
285 }
286 }
287
288 fn from_bytes(bytes: Vec<u8>) -> Any {
289 Any { type_url: "type.googleapis.com/google.protobuf.BytesValue".to_string(), value: bytes }
290 }
291
292 fn from_slice(slice: &[u8]) -> Any {
293 Self::from_bytes(slice.to_vec())
294 }
295
296 fn from_value<T: Into<AnyValue>>(value: T) -> Any {
297 match value.into() {
298 AnyValue::String(s) => Self::from_string(s),
299 AnyValue::Bool(b) => Self::from_bool(b),
300 AnyValue::Int32(i) => Self::from_int32(i),
301 AnyValue::Int64(i) => Self::from_int64(i),
302 AnyValue::Float(f) => Self::from_float(f),
303 AnyValue::Double(d) => Self::from_double(d),
304 AnyValue::Bytes(bytes) => Self::from_bytes(bytes),
305 AnyValue::Unknown(bytes) => Any { type_url: "unknown".to_string(), value: bytes },
306 }
307 }
308
309 fn is_string(&self) -> bool {
310 self.type_url == "type.googleapis.com/google.protobuf.StringValue"
311 }
312
313 fn is_bool(&self) -> bool {
314 self.type_url == "type.googleapis.com/google.protobuf.BoolValue"
315 }
316
317 fn is_int32(&self) -> bool {
318 self.type_url == "type.googleapis.com/google.protobuf.Int32Value"
319 }
320
321 fn is_int64(&self) -> bool {
322 self.type_url == "type.googleapis.com/google.protobuf.Int64Value"
323 }
324
325 fn is_float(&self) -> bool {
326 self.type_url == "type.googleapis.com/google.protobuf.FloatValue"
327 }
328
329 fn is_double(&self) -> bool {
330 self.type_url == "type.googleapis.com/google.protobuf.DoubleValue"
331 }
332
333 fn is_bytes(&self) -> bool {
334 self.type_url == "type.googleapis.com/google.protobuf.BytesValue"
335 }
336
337 fn is_unknown(&self) -> bool {
338 !self.is_string()
339 && !self.is_bool()
340 && !self.is_int32()
341 && !self.is_int64()
342 && !self.is_float()
343 && !self.is_double()
344 && !self.is_bytes()
345 }
346}
347
348pub trait ToAny {
350 fn to_any(&self) -> Any;
351}
352
353impl ToAny for String {
354 fn to_any(&self) -> Any {
355 Any::from_string(self.clone())
356 }
357}
358
359impl ToAny for &str {
360 fn to_any(&self) -> Any {
361 Any::from_str(self)
362 }
363}
364
365impl ToAny for bool {
366 fn to_any(&self) -> Any {
367 Any::from_bool(*self)
368 }
369}
370
371impl ToAny for i32 {
372 fn to_any(&self) -> Any {
373 Any::from_int32(*self)
374 }
375}
376
377impl ToAny for i64 {
378 fn to_any(&self) -> Any {
379 Any::from_int64(*self)
380 }
381}
382
383impl ToAny for f32 {
384 fn to_any(&self) -> Any {
385 Any::from_float(*self)
386 }
387}
388
389impl ToAny for f64 {
390 fn to_any(&self) -> Any {
391 Any::from_double(*self)
392 }
393}
394
395impl ToAny for Vec<u8> {
396 fn to_any(&self) -> Any {
397 Any::from_bytes(self.clone())
398 }
399}
400
401impl ToAny for &[u8] {
402 fn to_any(&self) -> Any {
403 Any::from_slice(self)
404 }
405}
406
407impl ToAny for AnyValue {
408 fn to_any(&self) -> Any {
409 Any::from_value(self.clone())
410 }
411}