about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2024-08-18T19·37+0300
committerclbot <clbot@tvl.fyi>2024-08-19T13·19+0000
commit56d4f01e9f5c227ccd923308dd58acbd560e993f (patch)
tree97269fa54d0f6f48233b263bbe7e6a3a8b3da8b1
parent86f467cee6d9551f5e4c9f2e16d6fa0c9bc232ce (diff)
feat(tazjin/german-string): add [Partial]Ord implementation r/8532
Change-Id: I8002ec63be45a15160387c21ed1fa8721a7c3eb4
Reviewed-on: https://cl.tvl.fyi/c/depot/+/12242
Tested-by: BuildkiteCI
Reviewed-by: tazjin <tazjin@tvl.su>
Autosubmit: tazjin <tazjin@tvl.su>
-rw-r--r--users/tazjin/german-string/src/lib.rs62
1 files changed, 62 insertions, 0 deletions
diff --git a/users/tazjin/german-string/src/lib.rs b/users/tazjin/german-string/src/lib.rs
index 7eb9eda4e88a..e696af7cbe62 100644
--- a/users/tazjin/german-string/src/lib.rs
+++ b/users/tazjin/german-string/src/lib.rs
@@ -1,4 +1,5 @@
 use std::alloc::Layout;
+use std::cmp::Ordering;
 use std::fmt::{Debug, Formatter};
 
 #[derive(Clone, Copy)]
@@ -119,6 +120,54 @@ impl PartialEq for GermanString {
 
 impl Eq for GermanString {}
 
+impl Ord for GermanString {
+    fn cmp(&self, other: &GermanString) -> Ordering {
+        match (self.len().cmp(&12), other.len().cmp(&12)) {
+            // two small strings
+            (Ordering::Less | Ordering::Equal, Ordering::Less | Ordering::Equal) => unsafe {
+                self.0.small.data[..self.len()].cmp(&other.0.small.data[..other.len()])
+            },
+            // two large strings
+            (Ordering::Greater, Ordering::Greater) => unsafe {
+                match self.0.large.prefix.cmp(&other.0.large.prefix) {
+                    Ordering::Equal => self.as_bytes().cmp(other.as_bytes()),
+                    ordering => ordering,
+                }
+            },
+
+            // LHS large, RHS small
+            (Ordering::Greater, _) => {
+                let prefix_ordering =
+                    unsafe { self.0.large.prefix.as_slice().cmp(&other.0.small.data[..4]) };
+
+                if prefix_ordering != Ordering::Equal {
+                    return prefix_ordering;
+                }
+
+                self.as_bytes().cmp(other.as_bytes())
+            }
+
+            // LHS small, RHS large
+            (_, Ordering::Greater) => {
+                let prefix_ordering =
+                    unsafe { self.0.small.data[..4].cmp(other.0.large.prefix.as_slice()) };
+
+                if prefix_ordering != Ordering::Equal {
+                    return prefix_ordering;
+                }
+
+                self.as_bytes().cmp(other.as_bytes())
+            }
+        }
+    }
+}
+
+impl PartialOrd for GermanString {
+    fn partial_cmp(&self, other: &GermanString) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
 impl Debug for GermanString {
     fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
         String::from_utf8_lossy(self.as_bytes()).fmt(f)
@@ -213,6 +262,19 @@ mod tests {
 
         // Test [`Eq`] implementation.
         #[test]
+        fn test_eq(lhs: Vec<u8>, rhs: Vec<u8>) {
+            let lhs_gs = GermanString::new_transient(lhs.as_slice());
+            let rhs_gs = GermanString::new_transient(rhs.as_slice());
+
+            assert_eq!(
+                (lhs == rhs),
+                (lhs_gs == rhs_gs),
+                "Eq should match between std::String and GermanString ({:?} == {:?})",
+                lhs, rhs,
+            );
+        }
+
+        #[test]
         fn test_reflexivity(x: GermanString) {
             prop_assert!(x == x);
         }