tera_rand/
string.rs

1use crate::common::parse_arg;
2use crate::error::unsupported_arg;
3use rand::distr::{Alphanumeric, SampleString, StandardUniform};
4use rand::rng;
5use std::collections::HashMap;
6use tera::{to_value, Result, Value};
7
8/// A Tera function to generate a random String.
9///
10/// By default, this function will generate an alphanumeric string of length 8. For a string with
11/// a different length, pass an integer length to the `length` parameter in the template.
12///
13/// # Example usage
14///
15/// ```edition2021
16/// use tera::{Context, Tera};
17/// use tera_rand::random_string;
18///
19/// let mut tera: Tera = Tera::default();
20/// tera.register_function("random_string", random_string);
21/// let context: Context = Context::new();
22///
23/// // use the default length of 8
24/// let rendered: String = tera
25///     .render_str("{{ random_string() }}", &context)
26///     .unwrap();
27/// // use a custom length of 16
28/// let rendered: String = tera
29///     .render_str("{{ random_string(length=16) }}", &context)
30///     .unwrap();
31/// // use alphanumeric space (which is also the default)
32/// let rendered: String = tera
33///     .render_str(r#"{{ random_string(space="alphanumeric") }}"#, &context)
34///     .unwrap();
35/// // use standard uniform space
36/// let rendered: String = tera
37///     .render_str(r#"{{ random_string(space="standard-uniform") }}"#, &context)
38///     .unwrap();
39/// ```
40pub fn random_string(args: &HashMap<String, Value>) -> Result<Value> {
41    let str_length: usize = parse_arg(args, "length")?.unwrap_or(8usize);
42
43    let space_as_string: String =
44        parse_arg(args, "space")?.unwrap_or_else(|| String::from("alphanumeric"));
45
46    let random_string: String = match space_as_string.as_str() {
47        "alphanumeric" => Ok(Alphanumeric.sample_string(&mut rng(), str_length)),
48        "standard-uniform" => Ok(StandardUniform.sample_string(&mut rng(), str_length)),
49        _ => Err(unsupported_arg("space", space_as_string)),
50    }?;
51    let json_value: Value = to_value(random_string)?;
52    Ok(json_value)
53}
54
55#[cfg(test)]
56mod tests {
57    use crate::common::tests::test_tera_rand_function;
58    use crate::string::*;
59    use tracing_test::traced_test;
60
61    #[test]
62    #[traced_test]
63    fn test_random_string() {
64        test_tera_rand_function(
65            random_string,
66            "random_string",
67            r#"{ "some_field": "{{ random_string() }}" }"#,
68            r#"\{ "some_field": "[\w\d]{8}" }"#,
69        );
70    }
71
72    #[test]
73    #[traced_test]
74    fn test_random_string_with_custom_length() {
75        test_tera_rand_function(
76            random_string,
77            "random_string",
78            r#"{ "some_field": "{{ random_string(length=12) }}" }"#,
79            r#"\{ "some_field": "[\w\d]{12}" }"#,
80        );
81    }
82
83    #[test]
84    #[traced_test]
85    fn test_random_string_with_alphanumeric_space() {
86        test_tera_rand_function(
87            random_string,
88            "random_string",
89            r#"{ "some_field": "{{ random_string(space="alphanumeric") }}" }"#,
90            r#"\{ "some_field": "[\w\d]{8}" }"#,
91        );
92    }
93
94    #[test]
95    #[traced_test]
96    fn test_random_string_with_standard_space() {
97        test_tera_rand_function(
98            random_string,
99            "random_string",
100            r#"{ "some_field": "{{ random_string(space="standard-uniform") }}" }"#,
101            r#"\{ "some_field": ".{8}" }"#,
102        );
103    }
104
105    #[test]
106    #[traced_test]
107    fn test_random_string_with_standard_space_and_custom_length() {
108        test_tera_rand_function(
109            random_string,
110            "random_string",
111            r#"{ "some_field": "{{ random_string(space="standard-uniform", length=12) }}" }"#,
112            r#"\{ "some_field": ".{12}" }"#,
113        );
114    }
115}