sbrd_gen/generator/random_values/
get_value_at_generator.rs1use 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
10pub 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
102pub trait ForGetValueAtGeneratorType {
104 fn get_generator_type() -> GeneratorType;
106
107 fn parse(s: &str) -> Result<Self, BuildError>
109 where
110 Self: Sized;
111
112 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}