tinc_build/codegen/cel/functions/
bytes.rs1use syn::parse_quote;
2use tinc_cel::CelValue;
3
4use super::Function;
5use crate::codegen::cel::compiler::{CompileError, CompiledExpr, CompilerCtx, ConstantCompiledExpr, RuntimeCompiledExpr};
6use crate::codegen::cel::types::CelType;
7
8#[derive(Debug, Clone, Default)]
9pub(crate) struct Bytes;
10
11impl Function for Bytes {
12 fn name(&self) -> &'static str {
13 "bytes"
14 }
15
16 fn syntax(&self) -> &'static str {
17 "<this>.bytes()"
18 }
19
20 fn compile(&self, ctx: CompilerCtx) -> Result<CompiledExpr, CompileError> {
21 let Some(this) = ctx.this else {
22 return Err(CompileError::syntax("missing this", self));
23 };
24
25 if !ctx.args.is_empty() {
26 return Err(CompileError::syntax("takes no arguments", self));
27 }
28
29 match this.into_cel()? {
30 CompiledExpr::Constant(ConstantCompiledExpr { value }) => {
31 Ok(CompiledExpr::constant(CelValue::cel_to_bytes(value)?))
32 }
33 CompiledExpr::Runtime(RuntimeCompiledExpr { expr, .. }) => Ok(CompiledExpr::runtime(
34 CelType::CelValue,
35 parse_quote!(::tinc::__private::cel::CelValue::cel_to_bytes(#expr)?),
36 )),
37 }
38 }
39}
40
41#[cfg(test)]
42#[cfg(feature = "prost")]
43#[cfg_attr(coverage_nightly, coverage(off))]
44mod tests {
45 use quote::quote;
46 use syn::parse_quote;
47 use tinc_cel::CelValue;
48
49 use crate::codegen::cel::compiler::{CompiledExpr, Compiler, CompilerCtx};
50 use crate::codegen::cel::functions::{Bytes, Function};
51 use crate::codegen::cel::types::CelType;
52 use crate::types::{ProtoType, ProtoTypeRegistry, ProtoValueType};
53
54 #[test]
55 fn test_bytes_syntax() {
56 let registry = ProtoTypeRegistry::new(crate::Mode::Prost, crate::extern_paths::ExternPaths::new(crate::Mode::Prost));
57 let compiler = Compiler::new(®istry);
58 insta::assert_debug_snapshot!(Bytes.compile(CompilerCtx::new(compiler.child(), None, &[])), @r#"
59 Err(
60 InvalidSyntax {
61 message: "missing this",
62 syntax: "<this>.bytes()",
63 },
64 )
65 "#);
66
67 insta::assert_debug_snapshot!(Bytes.compile(CompilerCtx::new(compiler.child(), Some(CompiledExpr::constant(CelValue::String("hi".into()))), &[])), @r"
68 Ok(
69 Constant(
70 ConstantCompiledExpr {
71 value: Bytes(
72 Borrowed(
73 [
74 104,
75 105,
76 ],
77 ),
78 ),
79 },
80 ),
81 )
82 ");
83
84 insta::assert_debug_snapshot!(Bytes.compile(CompilerCtx::new(compiler.child(), Some(CompiledExpr::constant(CelValue::List(Default::default()))), &[
85 cel_parser::parse("1 + 1").unwrap(), ])), @r#"
87 Err(
88 InvalidSyntax {
89 message: "takes no arguments",
90 syntax: "<this>.bytes()",
91 },
92 )
93 "#);
94 }
95
96 #[test]
97 #[cfg(not(valgrind))]
98 fn test_bytes_runtime() {
99 let registry = ProtoTypeRegistry::new(crate::Mode::Prost, crate::extern_paths::ExternPaths::new(crate::Mode::Prost));
100 let compiler = Compiler::new(®istry);
101
102 let string_value =
103 CompiledExpr::runtime(CelType::Proto(ProtoType::Value(ProtoValueType::String)), parse_quote!(input));
104
105 let output = Bytes
106 .compile(CompilerCtx::new(compiler.child(), Some(string_value), &[]))
107 .unwrap();
108
109 insta::assert_snapshot!(postcompile::compile_str!(
110 postcompile::config! {
111 test: true,
112 dependencies: vec![
113 postcompile::Dependency::version("tinc", "*"),
114 ],
115 },
116 quote! {
117 fn to_bytes(input: &str) -> Result<::tinc::__private::cel::CelValue<'_>, ::tinc::__private::cel::CelError<'_>> {
118 Ok(#output)
119 }
120
121 #[test]
122 fn test_to_bytes() {
123 assert_eq!(to_bytes("some string").unwrap(), ::tinc::__private::cel::CelValueConv::conv(b"some string"));
124 }
125 },
126 ));
127 }
128}