1use std::collections::HashMap;
2
3use cel::{objects::Key as CelKey, Value as CelValue};
4use thiserror::Error;
5
6use crate::{Any, DurationError, Empty, FieldMask, TimestampError};
7
8#[derive(Debug, Error)]
9pub enum CelConversionError {
10 #[error("{0}")]
11 DurationError(#[from] DurationError),
12
13 #[error("{0}")]
14 TimestampError(#[from] TimestampError),
15}
16
17impl From<Any> for CelValue {
18 fn from(value: Any) -> Self {
19 let mut cel_map: HashMap<CelKey, CelValue> = HashMap::new();
20 cel_map.insert(
21 "type_url".to_string().into(),
22 CelValue::String(value.type_url.clone().into()),
23 );
24 cel_map.insert(
25 "value".to_string().into(),
26 CelValue::Bytes(value.value.clone().into()),
27 );
28
29 CelValue::Map(cel_map.into())
30 }
31}
32
33#[cfg(feature = "chrono")]
34mod chrono {
35 use cel::Value as CelValue;
36 use chrono::{DateTime, FixedOffset};
37
38 use crate::{cel::CelConversionError, Duration, Timestamp};
39
40 impl TryFrom<Duration> for CelValue {
41 type Error = CelConversionError;
42
43 fn try_from(value: Duration) -> Result<Self, Self::Error> {
44 let chrono_dur: chrono::Duration = value.try_into().map_err(CelConversionError::from)?;
45
46 Ok(CelValue::Duration(chrono_dur))
47 }
48 }
49
50 impl TryFrom<Timestamp> for CelValue {
51 type Error = CelConversionError;
52
53 fn try_from(value: Timestamp) -> Result<Self, Self::Error> {
54 let chrono_timestamp: DateTime<FixedOffset> =
55 value.try_into().map_err(CelConversionError::from)?;
56 Ok(CelValue::Timestamp(chrono_timestamp))
57 }
58 }
59}
60
61impl From<FieldMask> for CelValue {
62 fn from(value: FieldMask) -> Self {
63 let paths = &value.paths;
64
65 let mut cel_vals: Vec<CelValue> = Vec::new();
66 for path in paths {
67 cel_vals.push(CelValue::String(path.clone().into()));
68 }
69
70 let mut cel_map: HashMap<CelKey, CelValue> = HashMap::new();
71 cel_map.insert("paths".into(), CelValue::List(cel_vals.into()));
72
73 CelValue::Map(cel_map.into())
74 }
75}
76
77impl From<&FieldMask> for CelValue {
78 fn from(value: &FieldMask) -> Self {
79 let paths = &value.paths;
80
81 let mut cel_vals: Vec<CelValue> = Vec::new();
82 for path in paths {
83 cel_vals.push(CelValue::String(path.clone().into()));
84 }
85
86 let mut cel_map: HashMap<CelKey, CelValue> = HashMap::new();
87 cel_map.insert("paths".into(), CelValue::List(cel_vals.into()));
88
89 CelValue::Map(cel_map.into())
90 }
91}
92
93impl From<Empty> for CelValue {
94 fn from(_: Empty) -> Self {
95 CelValue::Map(HashMap::<CelKey, CelValue>::new().into())
96 }
97}