diff options
author | Daniel Silverstone <dsilvers@digital-scurf.org> | 2021-08-14 08:59:40 +0100 |
---|---|---|
committer | Daniel Silverstone <dsilvers@digital-scurf.org> | 2021-09-07 17:32:19 +0100 |
commit | 204d2e3986ab74853797d7d28f723db1a088ee9f (patch) | |
tree | 598ad6f6d90477a3746d61bfce1436e5410474bb /src/bindings.rs | |
parent | 8f58565372ce664bf9f9e619ba909fcf13f3a84d (diff) | |
download | subplot-204d2e3986ab74853797d7d28f723db1a088ee9f.tar.gz |
bindings: Initial move toward multi-lingual bindings
Signed-off-by: Daniel Silverstone <dsilvers@digital-scurf.org>
Diffstat (limited to 'src/bindings.rs')
-rw-r--r-- | src/bindings.rs | 175 |
1 files changed, 42 insertions, 133 deletions
diff --git a/src/bindings.rs b/src/bindings.rs index 0291e68..2e87fe0 100644 --- a/src/bindings.rs +++ b/src/bindings.rs @@ -12,6 +12,7 @@ use std::collections::HashMap; use std::fmt::Debug; use std::path::Path; use std::str::FromStr; +use std::sync::Arc; use lazy_static::lazy_static; use regex::{escape, Regex, RegexBuilder}; @@ -104,7 +105,7 @@ pub struct BindingImpl { impl BindingImpl { /// Create a new binding implementation /// - /// ``` + /// ```ignore /// # use subplot::bindings::BindingImpl; /// /// let bimpl = BindingImpl::new("foo::bar::func", Some("foo::bar::func_cleanup")); @@ -118,7 +119,7 @@ impl BindingImpl { /// Retrieve the function name in this binding /// - /// ``` + /// ```ignore /// # use subplot::bindings::BindingImpl; /// let bimpl = BindingImpl::new("foo::bar::func", None); /// @@ -130,7 +131,7 @@ impl BindingImpl { /// Retrieve the cleanup function name in this binding /// - /// ``` + /// ```ignore /// # use subplot::bindings::BindingImpl; /// let bimpl = BindingImpl::new("foo::bar::func", None); /// @@ -155,7 +156,7 @@ pub struct Binding { kind: StepKind, pattern: String, regex: Regex, - impls: BindingImpl, + impls: HashMap<String, Arc<BindingImpl>>, types: HashMap<String, CaptureType>, } @@ -164,8 +165,6 @@ impl Binding { pub fn new( kind: StepKind, pattern: &str, - function: &str, - cleanup: Option<&str>, case_sensitive: bool, mut types: HashMap<String, CaptureType>, ) -> Result<Binding> { @@ -183,11 +182,19 @@ impl Binding { kind, pattern: pattern.to_owned(), regex, - impls: BindingImpl::new(function, cleanup), + impls: HashMap::new(), types, }) } + /// Insert an impl into this binding + pub fn add_impl(&mut self, template: &str, function: &str, cleanup: Option<&str>) { + self.impls.insert( + template.to_string(), + Arc::new(BindingImpl::new(function, cleanup)), + ); + } + /// Return the kind of step the binding is for. pub fn kind(&self) -> StepKind { self.kind @@ -198,14 +205,19 @@ impl Binding { &self.pattern } + /// Retrieve a particular implementation by name + pub fn step_impl(&self, template: &str) -> Option<Arc<BindingImpl>> { + self.impls.get(template).cloned() + } + /// Return name of function that implements step. pub fn function(&self) -> &str { - self.impls.function() + self.impls.values().next().unwrap().function() } /// Return name of function that implements cleanup. pub fn cleanup(&self) -> Option<&str> { - self.impls.cleanup() + self.impls.values().next().unwrap().cleanup() } /// Return the compiled regular expression for the pattern of the @@ -302,81 +314,41 @@ mod test_binding { #[test] fn creates_new_without_cleanup() { - let b = Binding::new( - StepKind::Given, - "I am Tomjon", - "set_name", - None, - false, - HashMap::new(), - ) - .unwrap(); + let mut b = Binding::new(StepKind::Given, "I am Tomjon", false, HashMap::new()).unwrap(); assert_eq!(b.kind(), StepKind::Given); assert!(b.regex().is_match("I am Tomjon")); assert!(!b.regex().is_match("I am Tomjon of Lancre")); assert!(!b.regex().is_match("Hello, I am Tomjon")); + b.add_impl("", "set_name", None); assert_eq!(b.function(), "set_name"); assert_eq!(b.cleanup(), None); } #[test] fn creates_new_with_cleanup() { - let b = Binding::new( - StepKind::Given, - "I am Tomjon", - "set_name", - Some("unset_name"), - false, - HashMap::new(), - ) - .unwrap(); + let mut b = Binding::new(StepKind::Given, "I am Tomjon", false, HashMap::new()).unwrap(); assert_eq!(b.kind(), StepKind::Given); assert!(b.regex().is_match("I am Tomjon")); assert!(!b.regex().is_match("I am Tomjon of Lancre")); assert!(!b.regex().is_match("Hello, I am Tomjon")); + b.add_impl("", "set_name", Some("unset_name")); assert_eq!(b.function(), "set_name"); assert_eq!(b.cleanup(), Some("unset_name")); } #[test] fn equal() { - let a = Binding::new( - StepKind::Given, - "I am Tomjon", - "set_name", - Some("unset"), - false, - HashMap::new(), - ) - .unwrap(); - let b = Binding::new( - StepKind::Given, - "I am Tomjon", - "set_name", - Some("unset"), - false, - HashMap::new(), - ) - .unwrap(); + let a = Binding::new(StepKind::Given, "I am Tomjon", false, HashMap::new()).unwrap(); + let b = Binding::new(StepKind::Given, "I am Tomjon", false, HashMap::new()).unwrap(); assert_eq!(a, b); } #[test] fn not_equal() { - let a = Binding::new( - StepKind::Given, - "I am Tomjon", - "set_name", - None, - false, - HashMap::new(), - ) - .unwrap(); + let a = Binding::new(StepKind::Given, "I am Tomjon", false, HashMap::new()).unwrap(); let b = Binding::new( StepKind::Given, "I am Tomjon of Lancre", - "set_name", - None, false, HashMap::new(), ) @@ -387,29 +359,21 @@ mod test_binding { #[test] fn does_not_match_with_wrong_kind() { let step = ScenarioStep::new(StepKind::Given, "given", "yo"); - let b = Binding::new(StepKind::When, "yo", "do_yo", None, false, HashMap::new()).unwrap(); + let b = Binding::new(StepKind::When, "yo", false, HashMap::new()).unwrap(); assert!(b.match_with_step(&step).is_none()); } #[test] fn does_not_match_with_wrong_text() { let step = ScenarioStep::new(StepKind::Given, "given", "foo"); - let b = Binding::new(StepKind::Given, "bar", "yo", None, false, HashMap::new()).unwrap(); + let b = Binding::new(StepKind::Given, "bar", false, HashMap::new()).unwrap(); assert!(b.match_with_step(&step).is_none()); } #[test] fn match_with_fixed_pattern() { let step = ScenarioStep::new(StepKind::Given, "given", "foo"); - let b = Binding::new( - StepKind::Given, - "foo", - "do_foo", - None, - false, - HashMap::new(), - ) - .unwrap(); + let b = Binding::new(StepKind::Given, "foo", false, HashMap::new()).unwrap(); let m = b.match_with_step(&step).unwrap(); assert_eq!(m.kind(), StepKind::Given); let mut parts = m.parts(); @@ -424,8 +388,6 @@ mod test_binding { let b = Binding::new( StepKind::Given, r"I am (?P<who>\S+), I am", - "set_name", - None, false, HashMap::new(), ) @@ -442,25 +404,9 @@ mod test_binding { #[test] fn case_sensitive_mismatch() { let step = ScenarioStep::new(StepKind::Given, "given", "I am Tomjon"); - let b = Binding::new( - StepKind::Given, - r"i am tomjon", - "set_name", - None, - false, - HashMap::new(), - ) - .unwrap(); + let b = Binding::new(StepKind::Given, r"i am tomjon", false, HashMap::new()).unwrap(); assert!(b.match_with_step(&step).is_some()); - let b = Binding::new( - StepKind::Given, - r"i am tomjon", - "set_name", - None, - true, - HashMap::new(), - ) - .unwrap(); + let b = Binding::new(StepKind::Given, r"i am tomjon", true, HashMap::new()).unwrap(); assert!(b.match_with_step(&step).is_none()); } } @@ -623,17 +569,14 @@ fn from_hashmap(parsed: &ParsedBinding) -> Result<Binding> { ?kind, ?pattern, ?types, - "Successfully prepared binding" + "Successfully acquired binding" ); - Binding::new( - kind, - &pattern, - &parsed.function, - parsed.cleanup.as_deref(), - parsed.case_sensitive, - types, - ) + let mut ret = Binding::new(kind, &pattern, parsed.case_sensitive, types)?; + event!(Level::TRACE, "Binding parsed OK"); + ret.add_impl("", &parsed.function, parsed.cleanup.as_deref()); + + Ok(ret) } #[cfg(test)] @@ -658,8 +601,6 @@ mod test_bindings { let binding = Binding::new( StepKind::Given, r"I am (?P<name>\S+)", - "set_name", - None, false, HashMap::new(), ) @@ -730,15 +671,7 @@ mod test_bindings { #[test] fn does_not_find_match_for_unmatching_kind() { let step = ScenarioStep::new(StepKind::Given, "given", "I am Tomjon"); - let binding = Binding::new( - StepKind::When, - r"I am Tomjon", - "set_foo", - None, - false, - HashMap::new(), - ) - .unwrap(); + let binding = Binding::new(StepKind::When, r"I am Tomjon", false, HashMap::new()).unwrap(); let mut bindings = Bindings::new(); bindings.add(binding); assert!(matches!( @@ -753,8 +686,6 @@ mod test_bindings { let binding = Binding::new( StepKind::Given, r"I am Tomjon of Lancre", - "set_foo", - None, false, HashMap::new(), ) @@ -771,24 +702,12 @@ mod test_bindings { fn two_matching_bindings() { let step = ScenarioStep::new(StepKind::Given, "given", "I am Tomjon"); let mut bindings = Bindings::default(); - bindings.add( - Binding::new( - StepKind::Given, - r"I am Tomjon", - "set_foo", - None, - false, - HashMap::new(), - ) - .unwrap(), - ); + bindings.add(Binding::new(StepKind::Given, r"I am Tomjon", false, HashMap::new()).unwrap()); bindings.add( Binding::new( StepKind::Given, &super::regex_from_simple_pattern(r"I am {name}", false, &mut HashMap::new()) .unwrap(), - "set_foo", - None, false, HashMap::new(), ) @@ -803,15 +722,7 @@ mod test_bindings { #[test] fn finds_match_for_fixed_string_pattern() { let step = ScenarioStep::new(StepKind::Given, "given", "I am Tomjon"); - let binding = Binding::new( - StepKind::Given, - r"I am Tomjon", - "set_name", - None, - false, - HashMap::new(), - ) - .unwrap(); + let binding = Binding::new(StepKind::Given, r"I am Tomjon", false, HashMap::new()).unwrap(); let mut bindings = Bindings::new(); bindings.add(binding); let m = bindings.find(&step).unwrap(); @@ -831,8 +742,6 @@ mod test_bindings { let binding = Binding::new( StepKind::Given, r"I am (?P<name>\S+)", - "set_name", - None, false, HashMap::new(), ) |