sbrd_gen/generator/build_string/
duplicate_permutation.rs

1use crate::builder::{GeneratorBuilder, ValueBound};
2use crate::error::{BuildError, GenerateError};
3use crate::generator::{GeneratorBase, Randomizer, ValueChildGeneratorBase, ValueOrChild};
4use crate::value::{DataValue, DataValueMap, SbrdInt};
5use crate::GeneratorType;
6
7/// The generator with permuting [`DataValue::String`] joined by separator
8///
9/// [`DataValue::String`]: ../../value/enum.DataValue.html#variant.String
10pub struct DuplicatePermutationGenerator<R: Randomizer + ?Sized> {
11    nullable: bool,
12    count_range: ValueBound<SbrdInt>,
13    separator: String,
14    selectable_values: Vec<ValueOrChild<R>>,
15}
16
17impl<R: Randomizer + ?Sized> ValueChildGeneratorBase<R> for DuplicatePermutationGenerator<R> {
18    fn get_selectable(&self) -> &[ValueOrChild<R>] {
19        &self.selectable_values
20    }
21}
22
23impl<R: Randomizer + ?Sized> GeneratorBase<R> for DuplicatePermutationGenerator<R> {
24    fn create(builder: GeneratorBuilder) -> Result<Self, BuildError>
25    where
26        Self: Sized,
27    {
28        let GeneratorBuilder {
29            generator_type,
30            nullable,
31            separator,
32            range,
33            children,
34            chars,
35            values,
36            filepath,
37            ..
38        } = builder;
39
40        if generator_type != GeneratorType::DuplicatePermutation {
41            return Err(BuildError::InvalidType(generator_type));
42        }
43
44        let count_range = match range {
45            None => Self::default_range(),
46            Some(r) => r
47                .try_convert_with(|s| {
48                    s.to_parse_string().parse::<SbrdInt>().map_err(|e| {
49                        BuildError::FailParseValue(
50                            s.to_parse_string(),
51                            "Int".to_string(),
52                            e.to_string(),
53                        )
54                    })
55                })?
56                .without_no_bound_from_other((0..).into()),
57        };
58        if let Some(s) = count_range.get_start() {
59            if s < &0 {
60                return Err(BuildError::InvalidValue(count_range.to_string()));
61            }
62        }
63        if count_range.is_empty() {
64            return Err(BuildError::RangeEmpty(count_range.convert_into()));
65        }
66
67        let _separator = separator.unwrap_or_else(|| "".to_string());
68
69        let selectable_values = Self::build_selectable(children, chars, values, filepath)?;
70
71        Ok(Self {
72            nullable,
73            count_range,
74            separator: _separator,
75            selectable_values,
76        })
77    }
78
79    fn is_nullable(&self) -> bool {
80        self.nullable
81    }
82
83    fn generate_without_null(
84        &self,
85        rng: &mut R,
86        context: &DataValueMap<&str>,
87    ) -> Result<DataValue, GenerateError> {
88        let mut result: String = String::new();
89        let mut is_first = true;
90        let count = rng.gen_range(self.count_range);
91        for _ in 0..count {
92            let value_string = self
93                .generate_from_values_or_children(rng, context)?
94                .to_permutation_string();
95
96            if is_first {
97                is_first = false;
98                result += &value_string;
99            } else {
100                result.push_str(&self.separator);
101                result += &value_string;
102            }
103        }
104
105        Ok(result.into())
106    }
107}
108
109impl<R: Randomizer + ?Sized> DuplicatePermutationGenerator<R> {
110    /// default count range
111    fn default_range() -> ValueBound<SbrdInt> {
112        ValueBound::new(Some(1), Some((true, 15)))
113    }
114}