pub struct CKey { /* private fields */ }
Expand description
CKey implements a consistent hash key.
Theory here: https://en.wikipedia.org/wiki/Consistent_hashing
§Examples
use ckey::CKey;
let k1 = CKey::from(0.1);
let k2 = k1.next();
let k3 = k2 + 10u8;
assert!(k2.inside(k1, k3));
let k4 = CKey::from(1000u16);
assert_eq!("0.015258789", format!("{}", k4));
Implementations§
source§impl CKey
impl CKey
sourcepub fn digest(data: impl AsRef<[u8]>) -> Self
pub fn digest(data: impl AsRef<[u8]>) -> Self
Make a digest from bytes and returns a new key from it.
Typical usage is to create a a CKey from a string.
§Examples
use ckey::CKey;
let k = CKey::digest("/a/unique/path");
assert_eq!("3b818742b0f27cfc10f4de1e5ba5594c975d580c412a31011ad58d36a2b17cdc", format!("{:?}",k));
sourcepub fn serial<T>(v: T) -> Selfwhere
T: Serialize,
pub fn serial<T>(v: T) -> Selfwhere
T: Serialize,
Make a hash from serialized data and returns a new key from it.
Typical usage is to create a a CKey from some object content.
Note: this is not using the Hash trait, and instead serializes the complete data. You could achieve “build a CKey from a hashable object” easily by doing a digest on the hash. This is not recommended, as you could get many more collisions, and it defeats the purpose of having 256-bit keys.
§Examples
use ckey::CKey;
use serde::Serialize;
#[derive(Serialize)]
struct Obj {
a: usize,
b: usize,
}
let obj = Obj{a: 10, b: 100};
let k = CKey::serial(obj);
assert_eq!("fc6326e9af50c0ae08d34921f61afa012988998fac0269dbcf2dbe30748ed4eb", format!("{:?}",k));
// DONT'DO THIS
use ckey::CKey;
use std::collections::hash_map::DefaultHasher;
use bincode::serialize;
use std::hash::{Hash, Hasher};
#[derive(Hash)]
struct Obj {
a: usize,
b: usize,
}
let obj = Obj{a: 10, b: 100};
let mut s = DefaultHasher::new();
obj.hash(&mut s);
let h = s.finish();
let data = serialize(&h).unwrap();
let k = CKey::digest(data);
// The code above works, but has 2 caveats:
// 1 - since DefaultHasher is randomized, results are unpredictable;
// 2 - risks of collision, as we are only using 64 bits.
println!("{}", k);
sourcepub fn rand() -> Self
pub fn rand() -> Self
Generate a random key.
This can be time consuming as it is using the OS random generation, which is better from a cryptographic point of view, but possibly slower than a standard prng.
§Examples
use ckey::CKey;
let k = CKey::rand();
print!("k: {:?}", k);
sourcepub fn zero() -> Self
pub fn zero() -> Self
Generate a key with the value 0.
§Examples
use ckey::CKey;
let k = CKey::zero();
assert_eq!("0000000000000000000000000000000000000000000000000000000000000000", format!("{:?}", k));
sourcepub fn unit() -> Self
pub fn unit() -> Self
Generate a key with the value 1, the smallest key possible just after zero.
§Examples
use ckey::CKey;
let k = CKey::unit();
assert_eq!("0000000000000000000000000000000000000000000000000000000000000001", format!("{:?}", k));
sourcepub fn last() -> Self
pub fn last() -> Self
Generate a key with the last, highest possible value.
§Examples
use ckey::CKey;
let k = CKey::last();
assert_eq!("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", format!("{:?}", k));
sourcepub fn halfway() -> Self
pub fn halfway() -> Self
Generate a key which is exactly in the middle of the ring.
§Examples
use ckey::CKey;
let k = CKey::halfway();
assert_eq!("8000000000000000000000000000000000000000000000000000000000000000", format!("{:?}", k));
sourcepub fn inside(self, lower: CKey, upper: CKey) -> bool
pub fn inside(self, lower: CKey, upper: CKey) -> bool
Returns true if self is inside lower and upper. Lower limit is excluded, upper is included. This is typically used in a ring to know if a given key is handled by a node. You would ask if key is inside previous node (lower) and this node (upper) and if true -> yes, this is the right node to handle it.
§Examples
use ckey::CKey;
let k1 = CKey::from(0.1);
let k2 = CKey::from(0.3);
let k3 = CKey::from(0.9);
assert!(k2.inside(k1, k3));
sourcepub fn incr(&mut self)
pub fn incr(&mut self)
Increment current key by one.
§Examples
use ckey::CKey;
let mut k = CKey::zero();
k.incr();
assert_eq!(CKey::unit(), k);
sourcepub fn decr(&mut self)
pub fn decr(&mut self)
Decrement current key by one.
§Examples
use ckey::CKey;
let mut k = CKey::zero();
k.decr();
assert_eq!(CKey::last(), k);
sourcepub fn next(self) -> CKey
pub fn next(self) -> CKey
Return current key plus one.
§Examples
use ckey::CKey;
let k = CKey::zero();
assert_eq!(CKey::unit(), k.next());
sourcepub fn prev(self) -> CKey
pub fn prev(self) -> CKey
Return current key minus one.
§Examples
use ckey::CKey;
let k = CKey::zero();
assert_eq!(CKey::last(), k.prev());
sourcepub fn parse(value: &str) -> Result<CKey, <Self as TryFrom<&str>>::Error>
pub fn parse(value: &str) -> Result<CKey, <Self as TryFrom<&str>>::Error>
Try to convert from a &str.
§Examples
use ckey::CKey;
let k = CKey::parse("12345678ffffffff01234567fffffffff00123456ffffffff0012345ffffffff").unwrap();
assert_eq!("12345678ffffffff01234567fffffffff00123456ffffffff0012345ffffffff", format!("{:?}", k));
sourcepub fn set(data: impl AsRef<[u8]>) -> Self
pub fn set(data: impl AsRef<[u8]>) -> Self
Set value from bytes, big endian.
The data can be longer or shorter than 32 bytes. Extra bytes will be ignored. Missing bytes will be replaced by zeroes.
§Examples
use ckey::CKey;
let bytes: [u8; 3] = [4, 2, 1];
let k = CKey::set(bytes);
assert_eq!("0402010000000000000000000000000000000000000000000000000000000000", format!("{:?}", k));
sourcepub fn bytes(&self) -> Vec<u8>
pub fn bytes(&self) -> Vec<u8>
Get value as bytes, big endian.
§Examples
use ckey::CKey;
let k = CKey::from(42u8);
let bytes = k.bytes();
assert_eq!(32, bytes.len());
assert_eq!(42, bytes[0]);
for byte in &bytes[1..] {
assert_eq!(0, *byte);
}
sourcepub fn sort(v: &mut Vec<CKey>, start: CKey)
pub fn sort(v: &mut Vec<CKey>, start: CKey)
Sort an array of keys, using a start reference.
There is no way to sort keys in an absolute way, since they are virtually on a circle and wrapping, everything depends on where you start from.
This is why there’s a start parameter.
§Examples
use ckey::CKey;
let start = CKey::from(0.7);
let k1 = CKey::from(0.2);
let k2 = CKey::from(0.4);
let k3 = CKey::from(0.3);
let k4 = CKey::from(0.9);
let mut sorted = vec![k1, k2, k3, k4];
CKey::sort(&mut sorted, start);
assert_eq!(4, sorted.len());
assert_eq!("0.900000000", format!("{}", sorted[0]));
assert_eq!("0.200000000", format!("{}", sorted[1]));
assert_eq!("0.300000000", format!("{}", sorted[2]));
assert_eq!("0.400000000", format!("{}", sorted[3]));
Trait Implementations§
source§impl Add<f32> for CKey
impl Add<f32> for CKey
source§impl Add<f64> for CKey
impl Add<f64> for CKey
source§impl Add<i16> for CKey
impl Add<i16> for CKey
source§impl Add<i32> for CKey
impl Add<i32> for CKey
source§impl Add<i64> for CKey
impl Add<i64> for CKey
source§impl Add<i8> for CKey
impl Add<i8> for CKey
source§impl Add<u16> for CKey
impl Add<u16> for CKey
source§impl Add<u32> for CKey
impl Add<u32> for CKey
source§impl Add<u64> for CKey
impl Add<u64> for CKey
source§impl Add<u8> for CKey
impl Add<u8> for CKey
source§impl Add for CKey
impl Add for CKey
source§fn add(self, other: CKey) -> CKey
fn add(self, other: CKey) -> CKey
Add another key.
If the result is outside key space, will loop back, as in wrapping mode. So the result is always within key space.
§Examples
use ckey::CKey;
let k1 = CKey::from(0.6f64);
let k2 = CKey::from(0.8f64);
let k_sum = k1 + k2;
assert_eq!("0.400000000", String::from(k_sum));
source§impl Debug for CKey
impl Debug for CKey
source§fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>
Debug-print a key.
The representation we use is an hex dump, the way you would write down the 2^256 integer corresponding to the key.
§Examples
use ckey::CKey;
use std::convert::TryFrom;
let k = CKey::parse("12345678ffffffff01234567fffffffff00123456ffffffff0012345ffffffff").unwrap();
assert_eq!("12345678ffffffff01234567fffffffff00123456ffffffff0012345ffffffff", format!("{:?}", k));
source§impl<'de> Deserialize<'de> for CKey
impl<'de> Deserialize<'de> for CKey
source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
source§impl Display for CKey
impl Display for CKey
source§fn fmt(&self, f: &mut Formatter<'_>) -> Result
fn fmt(&self, f: &mut Formatter<'_>) -> Result
Pretty-print a key.
The representation we use is a 9-digits decimal float number, 11 chars in total, including a leading “0.”.
The reason for this is -> 1 billion keys is enough to tell them apart, there CAN be collisions, but it should remain rare. To check for equality, use == operator, do not compare string reprs.
At the same time, decimals between 0 and 1 are easier to reason about when debugging, much more than 64 chars hexa dumps.
§Examples
use ckey::CKey;
use std::convert::TryFrom;
let k = CKey::parse("12345678ffffffff01234567fffffffff00123456ffffffff0012345ffffffff").unwrap();
assert_eq!("0.071111111", format!("{}", k));
source§impl From<&Vec<u8>> for CKey
impl From<&Vec<u8>> for CKey
source§fn from(v: &Vec<u8>) -> CKey
fn from(v: &Vec<u8>) -> CKey
Convert from a vector of bytes.
The vector can be any length, extra bytes are ignored, missing bytes are replaced with zeros.
§Examples
use ckey::CKey;
let k = CKey::from(&vec![4, 5, 6, 7]);
assert_eq!("0405060700000000000000000000000000000000000000000000000000000000", format!("{:?}", k));
source§impl From<CKey> for String
impl From<CKey> for String
source§fn from(k: CKey) -> String
fn from(k: CKey) -> String
Convert to a String.
The representation it gives is the fmt::Display impl, which gives a short (not complete/unique) yet readable representation of the key, as a floating point from 0 to 1.
§Examples
use ckey::CKey;
let k = CKey::from(0.6 as f64);
assert_eq!("0.600000000", String::from(k));
source§impl From<Vec<u8>> for CKey
impl From<Vec<u8>> for CKey
source§fn from(v: Vec<u8>) -> CKey
fn from(v: Vec<u8>) -> CKey
Convert from a vector of bytes.
The vector can be any length, extra bytes are ignored, missing bytes are replaced with zeros.
§Examples
use ckey::CKey;
let k = CKey::from(vec![1, 2, 3]);
assert_eq!("0102030000000000000000000000000000000000000000000000000000000000", format!("{:?}", k));
source§impl PartialEq for CKey
impl PartialEq for CKey
source§impl Sub<f32> for CKey
impl Sub<f32> for CKey
source§impl Sub<f64> for CKey
impl Sub<f64> for CKey
source§impl Sub<i16> for CKey
impl Sub<i16> for CKey
source§impl Sub<i32> for CKey
impl Sub<i32> for CKey
source§impl Sub<i64> for CKey
impl Sub<i64> for CKey
source§impl Sub<i8> for CKey
impl Sub<i8> for CKey
source§impl Sub<u16> for CKey
impl Sub<u16> for CKey
source§impl Sub<u32> for CKey
impl Sub<u32> for CKey
source§impl Sub<u64> for CKey
impl Sub<u64> for CKey
source§impl Sub<u8> for CKey
impl Sub<u8> for CKey
source§impl Sub for CKey
impl Sub for CKey
source§fn sub(self, other: CKey) -> CKey
fn sub(self, other: CKey) -> CKey
Sub another key.
If the result is outside key space, will loop back, as in wrapping mode. So the result is always within key space.
§Examples
use ckey::CKey;
let k1 = CKey::from(0.5f64);
let k2 = CKey::from(0.9f64);
let k_diff = k1 - k2;
assert_eq!("0.600000000", String::from(k_diff));
source§impl TryFrom<&str> for CKey
impl TryFrom<&str> for CKey
source§fn try_from(value: &str) -> Result<CKey, Self::Error>
fn try_from(value: &str) -> Result<CKey, Self::Error>
Try to convert from a &str.
§Examples
use ckey::CKey;
let k = CKey::try_from("12345678ffffffff01234567fffffffff00123456ffffffff0012345ffffffff").unwrap();
assert_eq!("12345678ffffffff01234567fffffffff00123456ffffffff0012345ffffffff", format!("{:?}", k));
§type Error = FromHexError
type Error = FromHexError
source§impl TryFrom<String> for CKey
impl TryFrom<String> for CKey
source§fn try_from(value: String) -> Result<CKey, Self::Error>
fn try_from(value: String) -> Result<CKey, Self::Error>
Try to convert from a String.
§Examples
use ckey::CKey;
let k = CKey::try_from(String::from("12345678ffffffff01234567fffffffff00123456ffffffff0012345ffffffff")).unwrap();
assert_eq!("12345678ffffffff01234567fffffffff00123456ffffffff0012345ffffffff", format!("{:?}", k));