sbrd_gen/generator/random_values/
get_value_at_generator.rs

1use crate::builder::GeneratorBuilder;
2use crate::error::{BuildError, GenerateError};
3use crate::eval::{EvalError, Evaluator};
4use crate::generator::{GeneratorBase, Randomizer, ValueGeneratorBase};
5use crate::value::{DataValue, DataValueMap, SbrdInt, SbrdReal, SbrdString};
6use crate::GeneratorType;
7use evalexpr::EvalexprError;
8use std::str::FromStr;
9
10/// The generator that gets a T value from the values with the value evaluated by `script` as the index of 0-index.
11pub struct GetValueAtGenerator<T> {
12    nullable: bool,
13    script: String,
14    selectable_values: Vec<T>,
15}
16
17impl<R: Randomizer + ?Sized, T: ForGetValueAtGeneratorType> ValueGeneratorBase<R, T>
18    for GetValueAtGenerator<T>
19{
20    fn parse(input: &str) -> Result<T, BuildError> {
21        T::parse(input)
22    }
23}
24
25impl<R: Randomizer + ?Sized, T: ForGetValueAtGeneratorType> GeneratorBase<R>
26    for GetValueAtGenerator<T>
27{
28    fn create(builder: GeneratorBuilder) -> Result<Self, BuildError>
29    where
30        Self: Sized,
31    {
32        let GeneratorBuilder {
33            generator_type,
34            nullable,
35            script,
36            chars,
37            values,
38            filepath,
39            ..
40        } = builder;
41
42        if generator_type != T::get_generator_type() {
43            return Err(BuildError::InvalidType(generator_type));
44        }
45
46        let selectable_values =
47            <Self as ValueGeneratorBase<R, T>>::build_selectable(chars, values, filepath)?;
48
49        match script {
50            None => Err(BuildError::NotExistValueOf("script".to_string())),
51            Some(script) => Ok(Self {
52                nullable,
53                script,
54                selectable_values,
55            }),
56        }
57    }
58
59    fn is_nullable(&self) -> bool {
60        self.nullable
61    }
62
63    fn generate_without_null(
64        &self,
65        _rng: &mut R,
66        context: &DataValueMap<&str>,
67    ) -> Result<DataValue, GenerateError> {
68        let evaluator = Evaluator::new(context);
69        let index: usize = evaluator
70            .eval_int(&self.script)
71            .and_then(|v| {
72                if v < 0 {
73                    Err(EvalError::FailEval(EvalexprError::CustomMessage(format!(
74                        "Expected a not negative integer, actual {} is negative.",
75                        v
76                    ))))
77                } else {
78                    Ok(v as usize)
79                }
80            })
81            .map_err(|e| {
82                GenerateError::FailEval(
83                    e,
84                    self.script.clone(),
85                    context
86                        .iter()
87                        .map(|(k, v)| (k.to_string(), v.clone()))
88                        .collect::<DataValueMap<String>>(),
89                )
90            })?;
91
92        match self.selectable_values.get(index) {
93            None => Err(GenerateError::FailGenerate(format!(
94                "Not found value at index {}",
95                index
96            ))),
97            Some(v) => Ok(v.to_data_value()),
98        }
99    }
100}
101
102/// Helper traits for generators that the generate value
103pub trait ForGetValueAtGeneratorType {
104    /// The type of the generator
105    fn get_generator_type() -> GeneratorType;
106
107    /// Function of parser the input value
108    fn parse(s: &str) -> Result<Self, BuildError>
109    where
110        Self: Sized;
111
112    /// Function of converter for a generated value
113    fn to_data_value(&self) -> DataValue;
114}
115
116impl ForGetValueAtGeneratorType for SbrdInt {
117    fn get_generator_type() -> GeneratorType {
118        GeneratorType::GetIntValueAt
119    }
120
121    fn parse(s: &str) -> Result<SbrdInt, BuildError> {
122        SbrdInt::from_str(s).map_err(|e| {
123            BuildError::FailParseValue(s.to_string(), "Int".to_string(), e.to_string())
124        })
125    }
126
127    fn to_data_value(&self) -> DataValue {
128        DataValue::Int(*self)
129    }
130}
131
132impl ForGetValueAtGeneratorType for SbrdReal {
133    fn get_generator_type() -> GeneratorType {
134        GeneratorType::GetRealValueAt
135    }
136
137    fn parse(s: &str) -> Result<SbrdReal, BuildError> {
138        SbrdReal::from_str(s).map_err(|e| {
139            BuildError::FailParseValue(s.to_string(), "Real".to_string(), e.to_string())
140        })
141    }
142
143    fn to_data_value(&self) -> DataValue {
144        DataValue::Real(*self)
145    }
146}
147
148impl ForGetValueAtGeneratorType for SbrdString {
149    fn get_generator_type() -> GeneratorType {
150        GeneratorType::GetStringValueAt
151    }
152
153    fn parse(s: &str) -> Result<String, BuildError> {
154        Ok(s.to_string())
155    }
156
157    fn to_data_value(&self) -> DataValue {
158        DataValue::String(self.to_string())
159    }
160}