use std::{cmp::Reverse, fmt::Debug}; use bytes::Bytes; pub struct Key>(T, u64); pub type KeySlice<'a> = Key<&'a [u8]>; pub type KeyVec = Key>; pub type KeyBytes = Key; /// For testing purpose, should not use anywhere in your implementation. pub const TS_ENABLED: bool = true; /// Temporary, should remove after implementing full week 3 day 1 + 2. pub const TS_DEFAULT: u64 = 0; pub const TS_MAX: u64 = u64::MAX; pub const TS_MIN: u64 = u64::MIN; pub const TS_RANGE_BEGIN: u64 = u64::MAX; pub const TS_RANGE_END: u64 = u64::MIN; impl> Key { pub fn into_inner(self) -> T { self.0 } pub fn key_len(&self) -> usize { self.0.as_ref().len() } pub fn raw_len(&self) -> usize { self.0.as_ref().len() + std::mem::size_of::() } pub fn is_empty(&self) -> bool { self.0.as_ref().is_empty() } pub fn for_testing_ts(self) -> u64 { self.1 } } impl Key> { pub fn new() -> Self { Self(Vec::new(), TS_DEFAULT) } /// Create a `KeyVec` from a `Vec` and a ts. Will be removed in week 3. pub fn from_vec_with_ts(key: Vec, ts: u64) -> Self { Self(key, ts) } /// Clears the key and set ts to 0. pub fn clear(&mut self) { self.0.clear() } /// Append a slice to the end of the key pub fn append(&mut self, data: &[u8]) { self.0.extend(data) } pub fn set_ts(&mut self, ts: u64) { self.1 = ts; } /// Set the key from a slice without re-allocating. pub fn set_from_slice(&mut self, key_slice: KeySlice) { self.0.clear(); self.0.extend(key_slice.0); self.1 = key_slice.1; } pub fn as_key_slice(&self) -> KeySlice { Key(self.0.as_slice(), self.1) } pub fn into_key_bytes(self) -> KeyBytes { Key(self.0.into(), self.1) } pub fn key_ref(&self) -> &[u8] { self.0.as_ref() } pub fn ts(&self) -> u64 { self.1 } pub fn for_testing_key_ref(&self) -> &[u8] { self.0.as_ref() } pub fn for_testing_from_vec_no_ts(key: Vec) -> Self { Self(key, TS_DEFAULT) } } impl Key { pub fn new() -> Self { Self(Bytes::new(), TS_DEFAULT) } pub fn as_key_slice(&self) -> KeySlice { Key(&self.0, self.1) } /// Create a `KeyBytes` from a `Bytes` and a ts. pub fn from_bytes_with_ts(bytes: Bytes, ts: u64) -> KeyBytes { Key(bytes, ts) } pub fn key_ref(&self) -> &[u8] { self.0.as_ref() } pub fn ts(&self) -> u64 { self.1 } pub fn for_testing_from_bytes_no_ts(bytes: Bytes) -> KeyBytes { Key(bytes, TS_DEFAULT) } pub fn for_testing_key_ref(&self) -> &[u8] { self.0.as_ref() } } impl<'a> Key<&'a [u8]> { pub fn to_key_vec(self) -> KeyVec { Key(self.0.to_vec(), self.1) } /// Create a key slice from a slice. Will be removed in week 3. pub fn from_slice(slice: &'a [u8], ts: u64) -> Self { Self(slice, ts) } pub fn key_ref(self) -> &'a [u8] { self.0 } pub fn ts(&self) -> u64 { self.1 } pub fn for_testing_key_ref(self) -> &'a [u8] { self.0 } pub fn for_testing_from_slice_no_ts(slice: &'a [u8]) -> Self { Self(slice, TS_DEFAULT) } pub fn for_testing_from_slice_with_ts(slice: &'a [u8], ts: u64) -> Self { Self(slice, ts) } } impl + Debug> Debug for Key { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.0.fmt(f) } } impl + Default> Default for Key { fn default() -> Self { Self(T::default(), TS_DEFAULT) } } impl + PartialEq> PartialEq for Key { fn eq(&self, other: &Self) -> bool { (self.0.as_ref(), self.1).eq(&(other.0.as_ref(), other.1)) } } impl + Eq> Eq for Key {} impl + Clone> Clone for Key { fn clone(&self) -> Self { Self(self.0.clone(), self.1) } } impl + Copy> Copy for Key {} impl + PartialOrd> PartialOrd for Key { fn partial_cmp(&self, other: &Self) -> Option { (self.0.as_ref(), Reverse(self.1)).partial_cmp(&(other.0.as_ref(), Reverse(other.1))) } } impl + Ord> Ord for Key { fn cmp(&self, other: &Self) -> std::cmp::Ordering { (self.0.as_ref(), Reverse(self.1)).cmp(&(other.0.as_ref(), Reverse(other.1))) } }