@@ -52,9 +52,53 @@ pub enum MaybeUnset<V> {
5252}
5353
5454/// Represents timeuuid (uuid V1) value
55- #[ derive( Debug , Clone , Copy ) ]
55+ ///
56+ /// This type has custom comparison logic which follows Scylla/Cassandra semantics.
57+ /// For details, see [`Ord` implementation](#impl-Ord-for-CqlTimeuuid).
58+ #[ derive( Debug , Clone , Copy , Eq ) ]
5659pub struct CqlTimeuuid ( Uuid ) ;
5760
61+ /// [`Uuid`] delegate methods
62+ impl CqlTimeuuid {
63+ pub fn as_bytes ( & self ) -> & [ u8 ; 16 ] {
64+ self . 0 . as_bytes ( )
65+ }
66+ }
67+
68+ impl CqlTimeuuid {
69+ /// Read 8 most significant bytes of timeuuid from serialized bytes
70+ fn msb ( & self ) -> u64 {
71+ // Scylla and Cassandra use a standard UUID memory layout for MSB:
72+ // 4 bytes 2 bytes 2 bytes
73+ // time_low - time_mid - time_hi_and_version
74+ let bytes = self . 0 . as_bytes ( ) ;
75+ ( ( bytes[ 6 ] & 0x0F ) as u64 ) << 56
76+ | ( bytes[ 7 ] as u64 ) << 48
77+ | ( bytes[ 4 ] as u64 ) << 40
78+ | ( bytes[ 5 ] as u64 ) << 32
79+ | ( bytes[ 0 ] as u64 ) << 24
80+ | ( bytes[ 1 ] as u64 ) << 16
81+ | ( bytes[ 2 ] as u64 ) << 8
82+ | ( bytes[ 3 ] as u64 )
83+ }
84+
85+ fn lsb ( & self ) -> u64 {
86+ let bytes = self . 0 . as_bytes ( ) ;
87+ ( bytes[ 8 ] as u64 ) << 56
88+ | ( bytes[ 9 ] as u64 ) << 48
89+ | ( bytes[ 10 ] as u64 ) << 40
90+ | ( bytes[ 11 ] as u64 ) << 32
91+ | ( bytes[ 12 ] as u64 ) << 24
92+ | ( bytes[ 13 ] as u64 ) << 16
93+ | ( bytes[ 14 ] as u64 ) << 8
94+ | ( bytes[ 15 ] as u64 )
95+ }
96+
97+ fn lsb_signed ( & self ) -> u64 {
98+ self . lsb ( ) ^ 0x8080808080808080
99+ }
100+ }
101+
58102impl std:: str:: FromStr for CqlTimeuuid {
59103 type Err = uuid:: Error ;
60104
@@ -81,6 +125,35 @@ impl From<Uuid> for CqlTimeuuid {
81125 }
82126}
83127
128+ /// Compare two values of timeuuid type.
129+ ///
130+ /// Cassandra legacy requires:
131+ /// - converting 8 most significant bytes to date, which is then compared.
132+ /// - masking off UUID version from the 8 ms-bytes during compare, to
133+ /// treat possible non-version-1 UUID the same way as UUID.
134+ /// - using signed compare for least significant bits.
135+ impl Ord for CqlTimeuuid {
136+ fn cmp ( & self , other : & Self ) -> std:: cmp:: Ordering {
137+ let mut res = self . msb ( ) . cmp ( & other. msb ( ) ) ;
138+ if let std:: cmp:: Ordering :: Equal = res {
139+ res = self . lsb_signed ( ) . cmp ( & other. lsb_signed ( ) ) ;
140+ }
141+ res
142+ }
143+ }
144+
145+ impl PartialOrd for CqlTimeuuid {
146+ fn partial_cmp ( & self , other : & Self ) -> Option < std:: cmp:: Ordering > {
147+ Some ( self . cmp ( other) )
148+ }
149+ }
150+
151+ impl PartialEq for CqlTimeuuid {
152+ fn eq ( & self , other : & Self ) -> bool {
153+ self . cmp ( other) == std:: cmp:: Ordering :: Equal
154+ }
155+ }
156+
84157/// Native CQL date representation that allows for a bigger range of dates (-262145-1-1 to 262143-12-31).
85158///
86159/// Represented as number of days since -5877641-06-23 i.e. 2^31 days before unix epoch.
0 commit comments