tinc_build/codegen/cel/compiler/
helpers.rs1use syn::parse_quote;
2use tinc_cel::CelValue;
3
4use super::{CompileError, CompiledExpr, Compiler, ConstantCompiledExpr, RuntimeCompiledExpr};
5use crate::codegen::cel::types::CelType;
6use crate::types::{ProtoModifiedValueType, ProtoType, ProtoValueType, ProtoWellKnownType};
7
8impl CompiledExpr {
9 pub(crate) fn into_bool(self, compiler: &Compiler) -> CompiledExpr {
10 match &self {
11 CompiledExpr::Runtime(RuntimeCompiledExpr {
12 expr,
13 ty: CelType::Proto(ProtoType::Modified(ProtoModifiedValueType::OneOf(_))),
14 }) => CompiledExpr::Runtime(RuntimeCompiledExpr {
15 expr: parse_quote! { (#expr).is_some() },
16 ty: CelType::Proto(ProtoType::Value(ProtoValueType::Bool)),
17 }),
18 CompiledExpr::Runtime(RuntimeCompiledExpr {
19 expr,
20 ty: CelType::Proto(ProtoType::Modified(ProtoModifiedValueType::Optional(ty))),
21 }) => {
22 let value_to_bool = CompiledExpr::Runtime(RuntimeCompiledExpr {
23 expr: parse_quote! { ___to_bool_value },
24 ty: CelType::Proto(ProtoType::Value(ty.clone())),
25 })
26 .into_bool(compiler);
27
28 CompiledExpr::Runtime(RuntimeCompiledExpr {
29 expr: parse_quote! {
30 match #expr {
31 Some(___to_bool_value) => #value_to_bool,
32 None => false,
33 }
34 },
35 ty: CelType::Proto(ProtoType::Value(ProtoValueType::Bool)),
36 })
37 }
38 CompiledExpr::Runtime(RuntimeCompiledExpr {
39 ty: CelType::Proto(ProtoType::Value(ProtoValueType::Message { .. })),
40 ..
41 }) => CompiledExpr::Constant(ConstantCompiledExpr {
42 value: tinc_cel::CelValue::Bool(true),
43 }),
44 CompiledExpr::Runtime(RuntimeCompiledExpr { expr, .. }) => CompiledExpr::Runtime(RuntimeCompiledExpr {
45 expr: parse_quote! {
46 ::tinc::__private::cel::to_bool(#expr)
47 },
48 ty: CelType::Proto(ProtoType::Value(ProtoValueType::Bool)),
49 }),
50 CompiledExpr::Constant(ConstantCompiledExpr {
51 value: CelValue::Enum(cel_enum),
52 }) => CompiledExpr::Constant(ConstantCompiledExpr {
53 value: tinc_cel::CelValue::Bool(
54 compiler
55 .registry
56 .get_enum(&cel_enum.tag)
57 .is_some_and(|e| e.variants.values().any(|v| v.value == cel_enum.value)),
58 ),
59 }),
60 CompiledExpr::Constant(ConstantCompiledExpr { value }) => CompiledExpr::Constant(ConstantCompiledExpr {
61 value: tinc_cel::CelValue::Bool(value.to_bool()),
62 }),
63 }
64 }
65
66 pub(crate) fn into_cel(self) -> Result<CompiledExpr, CompileError> {
67 match self {
68 CompiledExpr::Runtime(RuntimeCompiledExpr {
69 expr,
70 ty: ty @ CelType::CelValue,
71 }) => Ok(CompiledExpr::Runtime(RuntimeCompiledExpr { expr, ty })),
72 CompiledExpr::Runtime(RuntimeCompiledExpr {
73 expr,
74 ty:
75 CelType::Proto(ProtoType::Value(
76 ProtoValueType::Bool
77 | ProtoValueType::Bytes
78 | ProtoValueType::Double
79 | ProtoValueType::Float
80 | ProtoValueType::Int32
81 | ProtoValueType::Int64
82 | ProtoValueType::String
83 | ProtoValueType::UInt32
84 | ProtoValueType::UInt64
85 | ProtoValueType::WellKnown(
86 ProtoWellKnownType::Duration
87 | ProtoWellKnownType::Empty
88 | ProtoWellKnownType::ListValue
89 | ProtoWellKnownType::Struct
90 | ProtoWellKnownType::Timestamp
91 | ProtoWellKnownType::Value,
92 ),
93 )),
94 }) => Ok(CompiledExpr::Runtime(RuntimeCompiledExpr {
95 expr: parse_quote! {
96 ::tinc::__private::cel::CelValueConv::conv(#expr)
97 },
98 ty: CelType::CelValue,
99 })),
100 CompiledExpr::Runtime(RuntimeCompiledExpr {
101 expr,
102 ty: CelType::Proto(ProtoType::Modified(ProtoModifiedValueType::Map(key_ty, value_ty))),
103 }) => {
104 let key_to_cel = CompiledExpr::Runtime(RuntimeCompiledExpr {
105 expr: parse_quote!(key),
106 ty: CelType::Proto(ProtoType::Value(key_ty)),
107 })
108 .into_cel()?;
109
110 let value_to_cel = CompiledExpr::Runtime(RuntimeCompiledExpr {
111 expr: parse_quote!(value),
112 ty: CelType::Proto(ProtoType::Value(value_ty)),
113 })
114 .into_cel()?;
115
116 Ok(CompiledExpr::Runtime(RuntimeCompiledExpr {
117 expr: parse_quote! {
118 ::tinc::__private::cel::CelValue::Map(
119 (#expr).into_iter().map(|(key, value)| {
120 (
121 #key_to_cel,
122 #value_to_cel,
123 )
124 }).collect()
125 )
126 },
127 ty: CelType::CelValue,
128 }))
129 }
130 CompiledExpr::Runtime(RuntimeCompiledExpr {
131 expr,
132 ty: CelType::Proto(ProtoType::Modified(ProtoModifiedValueType::Optional(some_ty))),
133 }) => {
134 let some_to_cel = CompiledExpr::Runtime(RuntimeCompiledExpr {
135 expr: parse_quote!(item),
136 ty: CelType::Proto(ProtoType::Value(some_ty)),
137 })
138 .into_cel()?;
139
140 Ok(CompiledExpr::Runtime(RuntimeCompiledExpr {
141 expr: parse_quote! {{
142 match (#expr) {
143 ::core::option::Option::Some(item) => #some_to_cel,
144 ::core::option::Option::None => ::tinc::__private::cel::CelValue::Null,
145 }
146 }},
147 ty: CelType::CelValue,
148 }))
149 }
150 CompiledExpr::Runtime(RuntimeCompiledExpr {
151 expr,
152 ty: CelType::Proto(ProtoType::Modified(ProtoModifiedValueType::Repeated(item_ty))),
153 }) => {
154 let item_to_cel = CompiledExpr::Runtime(RuntimeCompiledExpr {
155 expr: parse_quote!(item),
156 ty: CelType::Proto(ProtoType::Value(item_ty)),
157 })
158 .into_cel()?;
159
160 Ok(CompiledExpr::Runtime(RuntimeCompiledExpr {
161 expr: parse_quote! {
162 ::tinc::__private::cel::CelValue::List((#expr).into_iter().map(|item| #item_to_cel).collect())
163 },
164 ty: CelType::CelValue,
165 }))
166 }
167 CompiledExpr::Runtime(RuntimeCompiledExpr {
168 expr,
169 ty: CelType::Proto(ProtoType::Value(ProtoValueType::Enum(path))),
170 }) => {
171 let path = path.as_ref();
172 Ok(CompiledExpr::Runtime(RuntimeCompiledExpr {
173 expr: parse_quote! {
174 ::tinc::__private::cel::CelValue::cel_to_enum(
175 #expr,
176 #path,
177 )?
178 },
179 ty: CelType::CelValue,
180 }))
181 }
182 CompiledExpr::Runtime(RuntimeCompiledExpr {
184 ty: ty @ CelType::Proto(ProtoType::Modified(ProtoModifiedValueType::OneOf(_))),
185 ..
186 }) => Err(CompileError::TypeConversion {
187 ty: Box::new(ty),
188 message: "oneofs cannot be converted into cel types".into(),
189 }),
190 CompiledExpr::Runtime(RuntimeCompiledExpr {
192 ty: ty @ CelType::Proto(ProtoType::Value(ProtoValueType::Message(_))),
193 ..
194 }) => Err(CompileError::TypeConversion {
195 ty: Box::new(ty),
196 message: "message types cannot be converted into cel types".into(),
197 }),
198 CompiledExpr::Runtime(RuntimeCompiledExpr {
200 ty: ty @ CelType::Proto(ProtoType::Value(ProtoValueType::WellKnown(ProtoWellKnownType::Any))),
201 ..
202 }) => Err(CompileError::TypeConversion {
203 ty: Box::new(ty),
204 message: "any cannot be converted into cel types".into(),
205 }),
206 CompiledExpr::Constant(c) => Ok(CompiledExpr::Constant(c)),
207 }
208 }
209}