summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorSoniEx2 <endermoneymod@gmail.com>2021-01-16 10:12:13 -0300
committerSoniEx2 <endermoneymod@gmail.com>2021-01-16 10:12:53 -0300
commitadf6b9f7be9a59be129869f4c63d33b10c80e23f (patch)
tree3b4eb41861b9d52310045b23dcd85ef52adb3fa7 /src
parentc0b4a8a326a320ac33c5d9d6bac2f7ea7eb703ce (diff)
Workaround lack of GATs
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs46
-rw-r--r--src/vm.rs9
2 files changed, 44 insertions, 11 deletions
diff --git a/src/lib.rs b/src/lib.rs
index f41b4c6..08609ab 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -5,21 +5,49 @@ mod vm;
 
 pub use pattern::Pattern;
 
+// TODO replace with GATs
+/// The key returned from pairs and get.
+pub enum Key<'b, T, U> {
+    /// Reference.
+    Ref(&'b T),
+    /// Borrowed string.
+    Str(&'b str),
+    /// Owned types.
+    Own(U),
+}
+
+impl<'b, T, U: Copy> Copy for Key<'b, T, U> {
+}
+
+impl<'b, T, U: Clone> Clone for Key<'b, T, U> {
+    fn clone(&self) -> Self {
+        match self {
+            Key::Ref(r) => Key::Ref(r),
+            Key::Str(r) => Key::Str(r),
+            Key::Own(v) => Key::Own(v.clone()),
+        }
+    }
+}
+
+pub type KVPair<'b, T> = (Key<'b, <T as PatternTypes>::Value, <T as PatternTypes>::OwnKey>, &'b <T as PatternTypes>::Value);
+
 // TODO investigate if this should be PatternTypes: Default
 /// Defines the types and operations used for matching.
 pub trait PatternTypes {
+    // TODO investigate Value: ?Sized
     /// The value type.
     type Value;
 
-    /// The owned key type. May be uninhabited.
     // TODO replace with GATs.
-    type Key;
+    // TODO potentially relax with Clone?
+    /// The owned key type. May be uninhabited.
+    type OwnKey: Copy + 'static;
 
     /// Returns an iterator over key-value pairs contained within an item, or
     /// None if this operation is unsupported for the given value.
     fn pairs<'b>(
         item: &'b Self::Value
-    ) -> Option<Box<dyn Iterator<Item=(&'b Self::Value, &'b Self::Value)> + 'b>> {
+    ) -> Option<Box<dyn Iterator<Item=KVPair<'b, Self>> + 'b>> {
         // TODO remove these default impls that only exist for testing purposes
         let x = None;
         Some(Box::new(x.into_iter()))
@@ -29,16 +57,20 @@ pub trait PatternTypes {
     /// this operation is unsupported for the given value.
     fn get<'a, 'b>(
         item: &'b Self::Value,
-        key: &'a str
-    ) -> Option<Option<(&'b Self::Value, &'b Self::Value)>> {
+        key: Key<'a, Self::Value, Self::OwnKey>
+    ) -> Option<Option<KVPair<'b, Self>>> {
         // TODO remove these default impls that only exist for testing purposes
         Some(None)
     }
 
-    /// Returns whether two values are the same/equivalent. This must provide
+    // TODO replace with GATs + newtypes
+    /// Returns whether two keys/values are the same/equivalent. This must provide
     /// the same guarantees as PartialEq. In fact, this is a replacement for
     /// PartialEq for cases where it's not possible to just use PartialEq.
-    fn matches(left: &Self::Value, right: &Self::Value) -> bool;
+    fn matches(
+        left: Key<'_, Self::Value, Self::OwnKey>,
+        right: Key<'_, Self::Value, Self::OwnKey>
+    ) -> bool;
 }
 
 // TODO
diff --git a/src/vm.rs b/src/vm.rs
index 595fac1..5b27a36 100644
--- a/src/vm.rs
+++ b/src/vm.rs
@@ -1,3 +1,4 @@
+use crate::KVPair;
 use crate::PatternTypes;
 use crate::Predicate;
 use crate::errors::MatchError;
@@ -7,7 +8,7 @@ use std::marker::PhantomData;
 
 pub(crate) const MAX_CALLS: usize = 250;
 
-type Matches<'a, 'b, T> = BTreeMap<&'a str, (&'b <T as PatternTypes>::Value, &'b <T as PatternTypes>::Value)>;
+type Matches<'a, 'b, T> = BTreeMap<&'a str, KVPair<'b, T>>;
 
 // TODO: use a builder for this?
 /// The constant pool for a pattern.
@@ -95,7 +96,7 @@ impl<'a, 'b, T: PatternTypes> Frame<'a, 'b, T> {
 enum HolderState<'a, 'b, T: PatternTypes> {
     EmptyKey,
     EmptySubtree,
-    Key((&'b T::Value, &'b T::Value)),
+    Key(KVPair<'b, T>),
     Subtree(Matches<'a, 'b, T>, &'b T::Value),
 }
 
@@ -136,7 +137,7 @@ struct Holder<'a, 'b, T: PatternTypes> {
      name: Option<&'a str>,
      value: HolderState<'a, 'b, T>,
      parent: Option<&'b T::Value>,
-     iterator: Box<dyn Iterator<Item=(&'b T::Value, &'b T::Value)> + 'b>,
+     iterator: Box<dyn Iterator<Item=KVPair<'b, T>> + 'b>,
      filters: Vec<Box<dyn for<'c> Fn(&'c mut HolderState<'a, 'b, T>) + 'a>>,
 }
 
@@ -262,7 +263,7 @@ impl<'a, 'b, T: PatternTypes> Matcher<'a, 'b, T> {
 }
 
 impl<'a, 'b, T: PatternTypes> Iterator for Matcher<'a, 'b, T> {
-    type Item = Result<BTreeMap<&'a str, (&'b T::Value, &'b T::Value)>, MatchError>;
+    type Item = Result<BTreeMap<&'a str, KVPair<'b, T>>, MatchError>;
 
     fn next(&mut self) -> Option<Self::Item> {
         while !self.frame.path.is_empty() {