pub trait LexicographicKey {
fn encode_key(&self, out: &mut Vec<u8>);
fn encoded_key(&self) -> Vec<u8> {
let mut out = Vec::new();
self.encode_key(&mut out);
out
}
}
impl LexicographicKey for str {
fn encode_key(&self, out: &mut Vec<u8>) {
out.extend_from_slice(self.as_bytes());
}
}
impl LexicographicKey for String {
fn encode_key(&self, out: &mut Vec<u8>) {
self.as_str().encode_key(out);
}
}
impl LexicographicKey for u64 {
fn encode_key(&self, out: &mut Vec<u8>) {
out.extend_from_slice(&self.to_be_bytes());
}
}
impl LexicographicKey for i64 {
fn encode_key(&self, out: &mut Vec<u8>) {
let sortable = (*self as u64) ^ (1_u64 << 63);
sortable.encode_key(out);
}
}
impl LexicographicKey for f64 {
fn encode_key(&self, out: &mut Vec<u8>) {
let bits = self.to_bits();
let sortable = if bits & (1_u64 << 63) == 0 {
bits + (1_u64 << 63)
} else {
!bits
};
sortable.encode_key(out);
}
}
impl LexicographicKey for bool {
fn encode_key(&self, out: &mut Vec<u8>) {
out.push(u8::from(*self));
}
}
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct KeyEncoder {
bytes: Vec<u8>,
}
impl KeyEncoder {
pub fn new() -> Self {
Self::default()
}
pub fn push_field<K: LexicographicKey + ?Sized>(&mut self, field: &K) -> &mut Self {
if !self.bytes.is_empty() {
self.bytes.push(0);
}
field.encode_key(&mut self.bytes);
self
}
pub fn finish(self) -> Vec<u8> {
self.bytes
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn compound_keys_preserve_field_order() {
let a = KeyEncoder::new()
.push_field("ComputeTask")
.push_field("aa")
.push_field(&7_u64)
.clone()
.finish();
let b = KeyEncoder::new()
.push_field("ComputeTask")
.push_field("aa")
.push_field(&8_u64)
.clone()
.finish();
assert!(a < b);
}
#[test]
fn signed_integers_sort_by_numeric_order() {
assert!((-1_i64).encoded_key() < 1_i64.encoded_key());
}
#[test]
fn floats_sort_by_numeric_order() {
assert!((-10.0_f64).encoded_key() < 0.0_f64.encoded_key());
assert!(0.0_f64.encoded_key() < 10.0_f64.encoded_key());
}
}