8bce4d7789
Co-authored-by: Rushmore Mushambi <rushmore@webenchanter.com> Co-authored-by: Mees Delzenne <DelSkayn@users.noreply.github.com>
164 lines
4 KiB
Rust
164 lines
4 KiB
Rust
use crate::vs::Versionstamp;
|
|
use std::fmt;
|
|
use thiserror::Error;
|
|
|
|
// u64_to_versionstamp converts a u64 to a 10-byte versionstamp
|
|
// assuming big-endian and the the last two bytes are zero.
|
|
pub fn u64_to_versionstamp(v: u64) -> [u8; 10] {
|
|
let mut buf = [0; 10];
|
|
buf[0] = (v >> 56) as u8;
|
|
buf[1] = (v >> 48) as u8;
|
|
buf[2] = (v >> 40) as u8;
|
|
buf[3] = (v >> 32) as u8;
|
|
buf[4] = (v >> 24) as u8;
|
|
buf[5] = (v >> 16) as u8;
|
|
buf[6] = (v >> 8) as u8;
|
|
buf[7] = v as u8;
|
|
buf
|
|
}
|
|
|
|
#[allow(unused)]
|
|
// u64_u16_to_versionstamp converts a u64 and a u16 to a 10-byte versionstamp
|
|
// assuming big-endian.
|
|
pub fn u64_u16_to_versionstamp(v: u64, v2: u16) -> [u8; 10] {
|
|
let mut buf = [0; 10];
|
|
buf[0] = (v >> 56) as u8;
|
|
buf[1] = (v >> 48) as u8;
|
|
buf[2] = (v >> 40) as u8;
|
|
buf[3] = (v >> 32) as u8;
|
|
buf[4] = (v >> 24) as u8;
|
|
buf[5] = (v >> 16) as u8;
|
|
buf[6] = (v >> 8) as u8;
|
|
buf[7] = v as u8;
|
|
buf[8] = (v2 >> 8) as u8;
|
|
buf[9] = v2 as u8;
|
|
buf
|
|
}
|
|
|
|
#[allow(unused)]
|
|
// u64_u16_to_versionstamp converts a u64 and a u16 to a 10-byte versionstamp
|
|
// assuming big-endian.
|
|
pub fn u16_u64_to_versionstamp(v: u16, v2: u64) -> [u8; 10] {
|
|
let mut buf = [0; 10];
|
|
buf[0] = (v >> 8) as u8;
|
|
buf[1] = v as u8;
|
|
buf[2] = (v2 >> 56) as u8;
|
|
buf[3] = (v2 >> 48) as u8;
|
|
buf[4] = (v2 >> 40) as u8;
|
|
buf[5] = (v2 >> 32) as u8;
|
|
buf[6] = (v2 >> 24) as u8;
|
|
buf[7] = (v2 >> 16) as u8;
|
|
buf[8] = (v2 >> 8) as u8;
|
|
buf[9] = v2 as u8;
|
|
buf
|
|
}
|
|
|
|
// u128_to_versionstamp converts a u128 to a 10-byte versionstamp
|
|
// assuming big-endian.
|
|
#[allow(unused)]
|
|
pub fn try_u128_to_versionstamp(v: u128) -> Result<[u8; 10], Error> {
|
|
if v >> 80 > 0 {
|
|
return Err(Error::InvalidVersionstamp);
|
|
}
|
|
|
|
let mut buf = [0; 10];
|
|
buf[0] = (v >> 72) as u8;
|
|
buf[1] = (v >> 64) as u8;
|
|
buf[2] = (v >> 56) as u8;
|
|
buf[3] = (v >> 48) as u8;
|
|
buf[4] = (v >> 40) as u8;
|
|
buf[5] = (v >> 32) as u8;
|
|
buf[6] = (v >> 24) as u8;
|
|
buf[7] = (v >> 16) as u8;
|
|
buf[8] = (v >> 8) as u8;
|
|
buf[9] = v as u8;
|
|
Ok(buf)
|
|
}
|
|
|
|
pub fn versionstamp_to_u64(vs: &Versionstamp) -> u64 {
|
|
u64::from_be_bytes(vs[..8].try_into().unwrap())
|
|
}
|
|
// to_u128_be converts a 10-byte versionstamp to a u128 assuming big-endian.
|
|
// This is handy for human comparing versionstamps.
|
|
#[allow(unused)]
|
|
pub fn to_u128_be(vs: [u8; 10]) -> u128 {
|
|
let mut buf = [0; 16];
|
|
let mut i = 0;
|
|
while i < 10 {
|
|
buf[i + 6] = vs[i];
|
|
i += 1;
|
|
}
|
|
u128::from_be_bytes(buf)
|
|
}
|
|
|
|
#[derive(Error)]
|
|
pub enum Error {
|
|
#[error("invalid versionstamp")]
|
|
// InvalidVersionstamp is returned when a versionstamp has an unexpected length.
|
|
InvalidVersionstamp,
|
|
}
|
|
|
|
impl fmt::Debug for Error {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
match self {
|
|
Error::InvalidVersionstamp => write!(f, "invalid versionstamp"),
|
|
}
|
|
}
|
|
}
|
|
|
|
// to_u64_be converts a 10-byte versionstamp to a u64 assuming big-endian.
|
|
// Only the first 8 bytes are used.
|
|
#[allow(unused)]
|
|
pub fn try_to_u64_be(vs: [u8; 10]) -> Result<u64, Error> {
|
|
let mut buf = [0; 8];
|
|
let mut i = 0;
|
|
while i < 8 {
|
|
buf[i] = vs[i];
|
|
i += 1;
|
|
}
|
|
if vs[8] != 0 || vs[9] != 0 {
|
|
return Err(Error::InvalidVersionstamp);
|
|
}
|
|
Ok(u64::from_be_bytes(buf))
|
|
}
|
|
|
|
// to_u128_le converts a 10-byte versionstamp to a u128 assuming little-endian.
|
|
// This is handy for producing human-readable versions of versionstamps.
|
|
#[allow(unused)]
|
|
pub fn to_u128_le(vs: [u8; 10]) -> u128 {
|
|
let mut buf = [0; 16];
|
|
let mut i = 0;
|
|
while i < 10 {
|
|
buf[i] = vs[i];
|
|
i += 1;
|
|
}
|
|
u128::from_be_bytes(buf)
|
|
}
|
|
|
|
mod tests {
|
|
#[test]
|
|
fn try_to_u64_be() {
|
|
use super::*;
|
|
// Overflow
|
|
let v = [255, 255, 255, 255, 255, 255, 255, 255, 0, 1];
|
|
let res = try_to_u64_be(v);
|
|
assert!(res.is_err());
|
|
// No overflow
|
|
let v = [255, 255, 255, 255, 255, 255, 255, 255, 0, 0];
|
|
let res = try_to_u64_be(v).unwrap();
|
|
assert_eq!(res, u64::MAX);
|
|
}
|
|
|
|
#[test]
|
|
fn try_u128_to_versionstamp() {
|
|
use super::*;
|
|
// Overflow
|
|
let v = u128::MAX;
|
|
let res = try_u128_to_versionstamp(v);
|
|
assert!(res.is_err());
|
|
// No overflow
|
|
let v = u128::MAX >> 48;
|
|
let res = try_u128_to_versionstamp(v).unwrap();
|
|
assert_eq!(res, [255, 255, 255, 255, 255, 255, 255, 255, 255, 255]);
|
|
}
|
|
}
|