pub fn from_long(value: i64) -> [u8; 8] {
let flipped = value ^ i64::MIN; flipped.to_be_bytes()
}
pub fn from_int(value: i32) -> [u8; 4] {
let flipped = value ^ i32::MIN; flipped.to_be_bytes()
}
pub fn float_to_int(value: f32) -> i32 {
sortable_float_bits(f32::to_bits(value) as i32)
}
pub fn double_to_long(value: f64) -> i64 {
sortable_double_bits(f64::to_bits(value) as i64)
}
pub fn from_float(value: f32) -> [u8; 4] {
from_int(float_to_int(value))
}
pub fn from_double(value: f64) -> [u8; 8] {
from_long(double_to_long(value))
}
fn sortable_float_bits(bits: i32) -> i32 {
bits ^ ((bits >> 31) & 0x7FFFFFFF)
}
fn sortable_double_bits(bits: i64) -> i64 {
bits ^ ((bits >> 63) & 0x7FFFFFFFFFFFFFFF)
}
#[cfg(test)]
mod tests {
use super::*;
fn sortable_bytes_to_long(bytes: &[u8; 8]) -> i64 {
let v = i64::from_be_bytes(*bytes);
v ^ i64::MIN
}
fn sortable_bytes_to_int(bytes: &[u8; 4]) -> i32 {
let v = i32::from_be_bytes(*bytes);
v ^ i32::MIN
}
fn sortable_int_to_float(encoded: i32) -> f32 {
f32::from_bits(sortable_float_bits(encoded) as u32)
}
fn sortable_long_to_double(encoded: i64) -> f64 {
f64::from_bits(sortable_double_bits(encoded) as u64)
}
#[test]
fn test_from_long_zero() {
let bytes = from_long(0);
assert_eq!(bytes, [0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
}
#[test]
fn test_from_long_positive() {
let bytes = from_long(1);
assert_eq!(bytes, [0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]);
}
#[test]
fn test_from_long_negative() {
let bytes = from_long(-1);
assert_eq!(bytes, [0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]);
}
#[test]
fn test_from_long_min() {
let bytes = from_long(i64::MIN);
assert_eq!(bytes, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
}
#[test]
fn test_from_long_max() {
let bytes = from_long(i64::MAX);
assert_eq!(bytes, [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]);
}
#[test]
fn test_long_sortable_ordering() {
let neg = from_long(-100);
let zero = from_long(0);
let pos = from_long(100);
assert_lt!(neg, zero);
assert_lt!(zero, pos);
}
#[test]
fn test_long_roundtrip() {
for &v in &[0i64, 1, -1, i64::MIN, i64::MAX, 42, -42, 1000000] {
let bytes = from_long(v);
assert_eq!(sortable_bytes_to_long(&bytes), v);
}
}
#[test]
fn test_from_int_zero() {
let bytes = from_int(0);
assert_eq!(bytes, [0x80, 0x00, 0x00, 0x00]);
}
#[test]
fn test_int_roundtrip() {
for &v in &[0i32, 1, -1, i32::MIN, i32::MAX, 42, -42] {
let bytes = from_int(v);
assert_eq!(sortable_bytes_to_int(&bytes), v);
}
}
#[test]
fn test_float_to_int_roundtrip() {
for &v in &[
0.0f32,
-0.0,
1.0,
-1.0,
42.5,
-42.5,
f32::INFINITY,
f32::NEG_INFINITY,
] {
let encoded = float_to_int(v);
let decoded = sortable_int_to_float(encoded);
assert_eq!(v.to_bits(), decoded.to_bits(), "roundtrip failed for {v}");
}
}
#[test]
fn test_float_to_int_nan() {
let encoded = float_to_int(f32::NAN);
let decoded = sortable_int_to_float(encoded);
assert!(decoded.is_nan());
}
#[test]
fn test_float_sortable_ordering() {
let neg = float_to_int(-1.0);
let zero = float_to_int(0.0);
let pos = float_to_int(1.0);
let inf = float_to_int(f32::INFINITY);
let nan = float_to_int(f32::NAN);
assert_lt!(neg, zero);
assert_lt!(zero, pos);
assert_lt!(pos, inf);
assert_lt!(inf, nan); }
#[test]
fn test_double_to_long_roundtrip() {
for &v in &[
0.0f64,
-0.0,
1.0,
-1.0,
42.5,
-42.5,
f64::INFINITY,
f64::NEG_INFINITY,
] {
let encoded = double_to_long(v);
let decoded = sortable_long_to_double(encoded);
assert_eq!(v.to_bits(), decoded.to_bits(), "roundtrip failed for {v}");
}
}
#[test]
fn test_double_to_long_nan() {
let encoded = double_to_long(f64::NAN);
let decoded = sortable_long_to_double(encoded);
assert!(decoded.is_nan());
}
#[test]
fn test_double_sortable_ordering() {
let neg = double_to_long(-1.0);
let zero = double_to_long(0.0);
let pos = double_to_long(1.0);
let inf = double_to_long(f64::INFINITY);
let nan = double_to_long(f64::NAN);
assert_lt!(neg, zero);
assert_lt!(zero, pos);
assert_lt!(pos, inf);
assert_lt!(inf, nan);
}
#[test]
fn test_from_float_roundtrip() {
for &v in &[0.0f32, 1.0, -1.0, 42.5, f32::INFINITY] {
let bytes = from_float(v);
let int_val = sortable_bytes_to_int(&bytes);
let decoded = sortable_int_to_float(int_val);
assert_eq!(
v.to_bits(),
decoded.to_bits(),
"byte roundtrip failed for {v}"
);
}
}
#[test]
fn test_from_double_roundtrip() {
for &v in &[0.0f64, 1.0, -1.0, 42.5, f64::INFINITY] {
let bytes = from_double(v);
let long_val = sortable_bytes_to_long(&bytes);
let decoded = sortable_long_to_double(long_val);
assert_eq!(
v.to_bits(),
decoded.to_bits(),
"byte roundtrip failed for {v}"
);
}
}
}