vrl/stdlib/casing/
camelcase.rs1use crate::compiler::prelude::*;
2
3use crate::stdlib::casing::{ORIGINAL_CASE, into_case};
4use convert_case::Case;
5
6#[derive(Clone, Copy, Debug)]
7pub struct Camelcase;
8
9impl Function for Camelcase {
10 fn identifier(&self) -> &'static str {
11 "camelcase"
12 }
13
14 fn usage(&self) -> &'static str {
15 "Takes the `value` string, and turns it into camelCase. Optionally, you can pass in the existing case of the function, or else an attempt is made to determine the case automatically."
16 }
17
18 fn category(&self) -> &'static str {
19 Category::String.as_ref()
20 }
21
22 fn return_kind(&self) -> u16 {
23 kind::BYTES
24 }
25
26 fn parameters(&self) -> &'static [Parameter] {
27 const PARAMETERS: &[Parameter] = &[
28 Parameter::required("value", kind::BYTES, "The string to convert to camelCase."),
29 ORIGINAL_CASE,
30 ];
31
32 PARAMETERS
33 }
34
35 fn compile(
36 &self,
37 state: &state::TypeState,
38 _ctx: &mut FunctionCompileContext,
39 arguments: ArgumentList,
40 ) -> Compiled {
41 let value = arguments.required("value");
42 let original_case = arguments
43 .optional_enum("original_case", &super::variants(), state)?
44 .map(|b| {
45 into_case(
46 b.try_bytes_utf8_lossy()
47 .expect("cant convert to string")
48 .as_ref(),
49 )
50 })
51 .transpose()?;
52
53 Ok(CamelcaseFn {
54 value,
55 original_case,
56 }
57 .as_expr())
58 }
59
60 fn examples(&self) -> &'static [Example] {
61 &[
62 example! {
63 title: "camelCase a string without specifying original case",
64 source: r#"camelcase("input-string")"#,
65 result: Ok("inputString"),
66 },
67 example! {
68 title: "camelcase a snake_case string",
69 source: r#"camelcase("foo_bar_baz", "snake_case")"#,
70 result: Ok("fooBarBaz"),
71 },
72 example! {
73 title: "camelcase specifying the wrong original case (noop)",
74 source: r#"camelcase("foo_bar_baz", "kebab-case")"#,
75 result: Ok("foo_bar_baz"),
76 },
77 ]
78 }
79}
80
81#[derive(Debug, Clone)]
82struct CamelcaseFn {
83 value: Box<dyn Expression>,
84 original_case: Option<Case>,
85}
86
87impl FunctionExpression for CamelcaseFn {
88 fn resolve(&self, ctx: &mut Context) -> Resolved {
89 let value = self.value.resolve(ctx)?;
90 super::convert_case(&value, Case::Camel, self.original_case)
91 }
92
93 fn type_def(&self, _: &state::TypeState) -> TypeDef {
94 TypeDef::bytes().infallible()
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101 use crate::value;
102
103 test_function![
104 camelcase => Camelcase;
105
106 simple {
107 args: func_args![value: value!("into_camel"), original_case: "snake_case"],
108 want: Ok(value!("intoCamel")),
109 tdef: TypeDef::bytes(),
110 }
111
112 no_case {
113 args: func_args![value: value!("into_camel")],
114 want: Ok(value!("intoCamel")),
115 tdef: TypeDef::bytes(),
116 }
117 ];
118}