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