megacommerce_shared/utils/
grpc.rs

1use 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  // Convenience method to create from any type that implements Into<Vec<u8>>
59  pub fn from_unknown_slice(slice: &[u8]) -> Self {
60    AnyValue::Unknown(slice.to_vec())
61  }
62
63  // Try to convert to specific types (useful for extracting values)
64  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  // Check the type of the value
121  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  // Type checking methods
231  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
348// Separate trait for conversions
349pub 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}