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