@@ -230,7 +230,10 @@ impl std::hash::Hash for CqlTimeuuid {
230230///
231231/// Currently, Scylla and Cassandra support non-normalized `varint` values.
232232/// Bytes provided by the user via constructor are passed to DB as is.
233- #[ derive( Clone , Debug ) ]
233+ ///
234+ /// The implementation of [`PartialEq`], however, normalizes the underlying bytes
235+ /// before comparison. For details, check [examples](#impl-PartialEq-for-CqlVarint).
236+ #[ derive( Clone , Eq , Debug ) ]
234237pub struct CqlVarint ( Vec < u8 > ) ;
235238
236239/// Constructors from bytes
@@ -267,6 +270,42 @@ impl CqlVarint {
267270 }
268271}
269272
273+ impl CqlVarint {
274+ fn as_normalized_slice ( & self ) -> & [ u8 ] {
275+ let digits = self . 0 . as_slice ( ) ;
276+ if digits. is_empty ( ) {
277+ // num-bigint crate normalizes empty vector to 0.
278+ // We will follow the same approach.
279+ return & [ 0 ] ;
280+ }
281+
282+ let non_zero_position = match digits. iter ( ) . position ( |b| * b != 0 ) {
283+ Some ( pos) => pos,
284+ None => {
285+ // Vector is filled with zeros. Represent it as 0.
286+ return & [ 0 ] ;
287+ }
288+ } ;
289+
290+ if non_zero_position > 0 {
291+ // There were some leading zeros.
292+ // Now, there are two cases:
293+ let zeros_to_remove = if digits[ non_zero_position] > 0x7f {
294+ // Most significant bit is 1, so we need to include one of the leading
295+ // zeros as originally it represented a positive number.
296+ non_zero_position - 1
297+ } else {
298+ // Most significant bit is 0 - positive number with no leading zeros.
299+ non_zero_position
300+ } ;
301+ return & digits[ zeros_to_remove..] ;
302+ }
303+
304+ // There were no leading zeros at all - leave as is.
305+ digits
306+ }
307+ }
308+
270309impl From < BigInt > for CqlVarint {
271310 fn from ( value : BigInt ) -> Self {
272311 Self ( value. to_signed_bytes_be ( ) )
@@ -279,6 +318,25 @@ impl From<CqlVarint> for BigInt {
279318 }
280319}
281320
321+ /// Compares two [`CqlVarint`] values after normalization.
322+ ///
323+ /// # Example
324+ ///
325+ /// ```rust
326+ /// # use scylla_cql::frame::value::CqlVarint;
327+ /// let non_normalized_bytes = vec![0x00, 0x01];
328+ /// let normalized_bytes = vec![0x01];
329+ /// assert_eq!(
330+ /// CqlVarint::from_signed_bytes_be(non_normalized_bytes),
331+ /// CqlVarint::from_signed_bytes_be(normalized_bytes)
332+ /// );
333+ /// ```
334+ impl PartialEq for CqlVarint {
335+ fn eq ( & self , other : & Self ) -> bool {
336+ self . as_normalized_slice ( ) == other. as_normalized_slice ( )
337+ }
338+ }
339+
282340/// Native CQL date representation that allows for a bigger range of dates (-262145-1-1 to 262143-12-31).
283341///
284342/// Represented as number of days since -5877641-06-23 i.e. 2^31 days before unix epoch.
0 commit comments