sbrd_gen/generator/
generator_base.rs1use crate::builder::{ChildGeneratorBuilder, GeneratorBuilder, Weight};
2use crate::error::{BuildError, GenerateError};
3use crate::eval::Evaluator;
4use crate::file::open_sbrd_file;
5use crate::value::{DataValue, DataValueMap};
6use either::Either;
7use rand::seq::SliceRandom;
8use rand::Rng;
9use std::io::{BufRead, BufReader};
10use std::path::PathBuf;
11
12pub trait Randomizer: 'static + Rng {}
14impl<R: 'static + Rng> Randomizer for R {}
15
16pub trait GeneratorBase<R: Randomizer + ?Sized> {
18 fn create(builder: GeneratorBuilder) -> Result<Self, BuildError>
20 where
21 Self: Sized;
22
23 fn is_nullable(&self) -> bool;
25
26 fn is_required(&self) -> bool {
28 !self.is_nullable()
29 }
30
31 fn generate(
33 &self,
34 rng: &mut R,
35 context: &DataValueMap<&str>,
36 ) -> Result<DataValue, GenerateError> {
37 if self.is_required() {
38 self.generate_without_null(rng, context)
39 } else {
40 if rng.gen_bool(0.1) {
41 return Ok(DataValue::Null);
42 }
43
44 self.generate_without_null(rng, context)
45 }
46 }
47
48 fn generate_without_null(
50 &self,
51 rng: &mut R,
52 context: &DataValueMap<&str>,
53 ) -> Result<DataValue, GenerateError>;
54}
55
56pub type CasedChild<R> = (Option<String>, Box<dyn GeneratorBase<R>>);
58pub trait CasedChildGeneratorBase<R: Randomizer + ?Sized> {
66 fn build_selectable(
68 children: Option<Vec<ChildGeneratorBuilder>>,
69 ) -> Result<Vec<CasedChild<R>>, BuildError> {
70 match children {
71 None => Err(BuildError::NotExistValueOf("children".to_string())),
72 Some(children) => {
73 let mut _children: Vec<(Option<String>, Box<dyn GeneratorBase<R>>)> = Vec::new();
74 let mut has_default_case = false;
75 for child_builder in children.into_iter() {
76 let ChildGeneratorBuilder {
77 condition, builder, ..
78 } = child_builder;
79 has_default_case = has_default_case || condition.is_none();
80 _children.push((condition, builder.build()?));
81 }
82
83 if _children.is_empty() {
84 return Err(BuildError::EmptySelectableChildren);
85 }
86
87 if !has_default_case {
88 return Err(BuildError::NotExistDefaultCase);
89 }
90
91 Ok(_children)
92 }
93 }
94 }
95
96 fn get_children(&self) -> &[CasedChild<R>];
98
99 fn generate_from_children(
101 &self,
102 rng: &mut R,
103 context: &DataValueMap<&str>,
104 ) -> Result<DataValue, GenerateError> {
105 for (condition, generator) in self.get_children().iter() {
106 return match condition {
107 None => generator.generate(rng, context),
108 Some(_condition) => {
109 let evaluator = Evaluator::new(context);
110 let is_satisfy = evaluator.eval_bool(_condition).map_err(|e| {
111 GenerateError::FailEval(
112 e,
113 _condition.clone(),
114 context
115 .iter()
116 .map(|(k, v)| (k.to_string(), v.clone()))
117 .collect::<DataValueMap<String>>(),
118 )
119 })?;
120 if !is_satisfy {
121 continue;
122 }
123
124 generator.generate(rng, context)
125 }
126 };
127 }
128
129 Err(GenerateError::FailGenerate(
130 "No match case condition".to_string(),
131 ))
132 }
133}
134
135pub type WeightedChild<R> = (Weight, Box<dyn GeneratorBase<R>>);
137pub trait WeightedChildGeneratorBase<R: Randomizer + ?Sized> {
139 fn build_selectable(
141 children: Option<Vec<ChildGeneratorBuilder>>,
142 ) -> Result<Vec<WeightedChild<R>>, BuildError> {
143 match children {
144 None => Err(BuildError::NotExistValueOf("children".to_string())),
145 Some(children) => {
146 let mut select_values = Vec::new();
147 for child_builder in children.into_iter() {
148 let ChildGeneratorBuilder {
149 weight, builder, ..
150 } = child_builder;
151 select_values.push((weight.unwrap_or(1), builder.build()?));
152 }
153
154 if select_values.is_empty() {
155 return Err(BuildError::EmptySelectableChildren);
156 }
157
158 if select_values.iter().fold(0, |acc, item| acc + item.0) == 0 {
159 return Err(BuildError::AllWeightsZero);
160 }
161
162 Ok(select_values)
163 }
164 }
165 }
166
167 fn get_selectable(&self) -> &[WeightedChild<R>];
169
170 fn generate_from_children(
172 &self,
173 rng: &mut R,
174 context: &DataValueMap<&str>,
175 ) -> Result<DataValue, GenerateError> {
176 let item = self
177 .get_selectable()
178 .choose_weighted(rng, |item| item.0)
179 .map_err(|err| GenerateError::FailGenerate(err.to_string()))?;
180
181 item.1.generate(rng, context)
182 }
183}
184
185pub trait ValueGeneratorBase<R: Randomizer + ?Sized, T> {
187 fn parse(input: &str) -> Result<T, BuildError>;
189
190 fn build_selectable(
192 chars: Option<String>,
193 values: Option<Vec<DataValue>>,
194 filepath: Option<PathBuf>,
195 ) -> Result<Vec<T>, BuildError> {
196 let mut selectable_values: Vec<T> = Vec::new();
197 if let Some(chars) = chars {
198 for c in chars.chars() {
199 selectable_values.push(Self::parse(&c.to_string())?);
200 }
201 }
202
203 if let Some(values) = values {
204 for value in values.into_iter() {
205 selectable_values.push(Self::parse(&value.to_parse_string())?);
206 }
207 }
208
209 if let Some(filepath) = filepath {
210 let file = open_sbrd_file(filepath.as_path())
211 .map_err(|e| BuildError::FileError(e, filepath.clone()))?;
212 let reader = BufReader::new(file);
213 for line in reader.lines() {
214 let line = line.map_err(|e| BuildError::FileError(e, filepath.clone()))?;
215 selectable_values.push(Self::parse(&line)?);
216 }
217 }
218
219 if selectable_values.is_empty() {
220 return Err(BuildError::EmptySelectableChildren);
221 }
222
223 Ok(selectable_values)
224 }
225}
226
227pub type ValueOrChild<R> = Either<String, Box<dyn GeneratorBase<R>>>;
232pub trait ValueChildGeneratorBase<R: Randomizer + ?Sized> {
234 fn build_selectable(
236 children: Option<Vec<ChildGeneratorBuilder>>,
237 chars: Option<String>,
238 values: Option<Vec<DataValue>>,
239 filepath: Option<PathBuf>,
240 ) -> Result<Vec<ValueOrChild<R>>, BuildError> {
241 let mut select_values = Vec::new();
242 if let Some(children) = children {
243 for child_builder in children.into_iter() {
244 let ChildGeneratorBuilder { builder, .. } = child_builder;
245 select_values.push(Either::Right(builder.build()?));
246 }
247 }
248
249 if let Some(chars) = chars {
250 select_values.extend(chars.chars().map(|c| Either::Left(c.to_string())));
251 }
252
253 if let Some(values) = values {
254 select_values.extend(values.into_iter().map(|v| Either::Left(v.to_string())));
255 }
256
257 if let Some(filepath) = filepath {
258 let file = open_sbrd_file(filepath.as_path())
259 .map_err(|e| BuildError::FileError(e, filepath.clone()))?;
260 let reader = BufReader::new(file);
261 for line in reader.lines() {
262 let line = line.map_err(|e| BuildError::FileError(e, filepath.clone()))?;
263 select_values.push(Either::Left(line));
264 }
265 }
266
267 if select_values.is_empty() {
268 return Err(BuildError::EmptySelectable);
269 }
270
271 Ok(select_values)
272 }
273
274 fn get_selectable(&self) -> &[ValueOrChild<R>];
276
277 fn generate_from_values_or_children(
279 &self,
280 rng: &mut R,
281 context: &DataValueMap<&str>,
282 ) -> Result<DataValue, GenerateError> {
283 self.get_selectable()
284 .choose_weighted(rng, |_| 1)
285 .map_err(|err| GenerateError::FailGenerate(err.to_string()))
286 .and_then(|either| match either {
287 Either::Left(item) => Ok(item.clone().into()),
288 Either::Right(item) => item.generate(rng, context),
289 })
290 }
291}