use crate::compiler::prelude::*;
use crate::stdlib::casing::{ORIGINAL_CASE, into_case};
use convert_case::Case;
#[derive(Clone, Copy, Debug)]
pub struct Camelcase;
impl Function for Camelcase {
fn identifier(&self) -> &'static str {
"camelcase"
}
fn usage(&self) -> &'static str {
"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."
}
fn category(&self) -> &'static str {
Category::String.as_ref()
}
fn return_kind(&self) -> u16 {
kind::BYTES
}
fn parameters(&self) -> &'static [Parameter] {
const PARAMETERS: &[Parameter] = &[
Parameter::required("value", kind::BYTES, "The string to convert to camelCase."),
ORIGINAL_CASE,
];
PARAMETERS
}
fn compile(
&self,
state: &state::TypeState,
_ctx: &mut FunctionCompileContext,
arguments: ArgumentList,
) -> Compiled {
let value = arguments.required("value");
let original_case = arguments
.optional_enum("original_case", &super::variants(), state)?
.map(|b| {
into_case(
b.try_bytes_utf8_lossy()
.expect("cant convert to string")
.as_ref(),
)
})
.transpose()?;
Ok(CamelcaseFn {
value,
original_case,
}
.as_expr())
}
fn examples(&self) -> &'static [Example] {
&[
example! {
title: "camelCase a string without specifying original case",
source: r#"camelcase("input-string")"#,
result: Ok("inputString"),
},
example! {
title: "camelcase a snake_case string",
source: r#"camelcase("foo_bar_baz", "snake_case")"#,
result: Ok("fooBarBaz"),
},
example! {
title: "camelcase specifying the wrong original case (noop)",
source: r#"camelcase("foo_bar_baz", "kebab-case")"#,
result: Ok("foo_bar_baz"),
},
]
}
}
#[derive(Debug, Clone)]
struct CamelcaseFn {
value: Box<dyn Expression>,
original_case: Option<Case>,
}
impl FunctionExpression for CamelcaseFn {
fn resolve(&self, ctx: &mut Context) -> Resolved {
let value = self.value.resolve(ctx)?;
super::convert_case(&value, Case::Camel, self.original_case)
}
fn type_def(&self, _: &state::TypeState) -> TypeDef {
TypeDef::bytes().infallible()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::value;
test_function![
camelcase => Camelcase;
simple {
args: func_args![value: value!("into_camel"), original_case: "snake_case"],
want: Ok(value!("intoCamel")),
tdef: TypeDef::bytes(),
}
no_case {
args: func_args![value: value!("into_camel")],
want: Ok(value!("intoCamel")),
tdef: TypeDef::bytes(),
}
];
}