1use crate::error::RegistryError;
6use crate::expression::{CompiledExpression, ParameterTypeRegistry};
7use crate::handler::Handler;
8use crate::step_kind::StepKind;
9use crate::value::Value;
10use std::collections::HashMap;
11use std::rc::Rc;
12
13pub use crate::expression::ParseFn;
14
15pub type FormatFn = Rc<dyn Fn(&Value) -> Option<String>>;
19
20#[derive(Clone, Debug, PartialEq, Eq)]
23pub struct CustomParameterType {
24 pub name: String,
25 pub regexp: String,
26}
27
28impl CustomParameterType {
29 pub fn new(name: impl Into<String>, regexp: impl Into<String>) -> CustomParameterType {
30 CustomParameterType {
31 name: name.into(),
32 regexp: regexp.into(),
33 }
34 }
35}
36
37#[derive(Clone)]
40pub struct StepRegistration {
41 pub expression: String,
42 pub expression_source_file: String,
43 pub expression_source_line: usize,
44 pub handler: Handler,
45 pub compiled: CompiledExpression,
46 pub kind: Option<StepKind>,
47}
48
49#[derive(Clone)]
51pub struct Registry {
52 pub steps: Vec<Rc<StepRegistration>>,
53 pub parameter_types: ParameterTypeRegistry,
54 pub custom_parameter_types: Vec<CustomParameterType>,
55 pub formats: HashMap<String, FormatFn>,
56}
57
58pub fn create_registry() -> Registry {
60 Registry {
61 steps: Vec::new(),
62 parameter_types: ParameterTypeRegistry::new(),
63 custom_parameter_types: Vec::new(),
64 formats: HashMap::new(),
65 }
66}
67
68pub fn add_step(
72 registry: &Registry,
73 expression: &str,
74 expression_source_file: &str,
75 expression_source_line: usize,
76 handler: Handler,
77 kind: Option<StepKind>,
78) -> Result<Registry, RegistryError> {
79 for existing in ®istry.steps {
80 if existing.expression == expression {
81 return Err(RegistryError::DuplicateStep(format!(
82 "duplicate step definition for \"{}\" at {}:{} and {}:{}",
83 expression,
84 existing.expression_source_file,
85 existing.expression_source_line,
86 expression_source_file,
87 expression_source_line
88 )));
89 }
90 }
91 let compiled = CompiledExpression::compile(expression, ®istry.parameter_types)
92 .map_err(|e| RegistryError::Expression(e.message))?;
93 let mut steps = registry.steps.clone();
94 steps.push(Rc::new(StepRegistration {
95 expression: expression.to_string(),
96 expression_source_file: expression_source_file.to_string(),
97 expression_source_line,
98 handler,
99 compiled,
100 kind,
101 }));
102 Ok(Registry {
103 steps,
104 parameter_types: registry.parameter_types.clone(),
105 custom_parameter_types: registry.custom_parameter_types.clone(),
106 formats: registry.formats.clone(),
107 })
108}
109
110pub fn define_parameter_type(
112 registry: &Registry,
113 name: &str,
114 regexp: &str,
115 parse: ParseFn,
116) -> Registry {
117 let mut parameter_types = registry.parameter_types.clone();
118 parameter_types.define(name, regexp, parse);
119 let mut custom_parameter_types = registry.custom_parameter_types.clone();
120 custom_parameter_types.push(CustomParameterType::new(name, regexp));
121 Registry {
122 steps: registry.steps.clone(),
123 parameter_types,
124 custom_parameter_types,
125 formats: registry.formats.clone(),
126 }
127}
128
129pub fn define_parameter_type_with_format(
131 registry: &Registry,
132 name: &str,
133 regexp: &str,
134 parse: ParseFn,
135 format: FormatFn,
136) -> Registry {
137 let mut next = define_parameter_type(registry, name, regexp, parse);
138 next.formats.insert(name.to_string(), format);
139 next
140}