feat: node id
This commit is contained in:
parent
1c32f0bc65
commit
3c0d144b5f
4 changed files with 185 additions and 17 deletions
39
Cargo.lock
generated
39
Cargo.lock
generated
|
@ -261,6 +261,12 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
|
||||
|
||||
[[package]]
|
||||
name = "colored"
|
||||
version = "1.9.4"
|
||||
|
@ -1068,12 +1074,31 @@ version = "0.4.22"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
||||
|
||||
[[package]]
|
||||
name = "mac_address"
|
||||
version = "1.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8836fae9d0d4be2c8b4efcdd79e828a2faa058a90d005abf42f91cac5493a08e"
|
||||
dependencies = [
|
||||
"nix",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
version = "0.3.17"
|
||||
|
@ -1118,6 +1143,19 @@ dependencies = [
|
|||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
"memoffset",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.1.0"
|
||||
|
@ -1165,6 +1203,7 @@ dependencies = [
|
|||
"hex",
|
||||
"insta",
|
||||
"jetstream_wireformat",
|
||||
"mac_address",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha1",
|
||||
|
|
|
@ -15,6 +15,7 @@ enumflags2 = "0.7.10"
|
|||
git2 = { version = "0.18.3", optional = true, default-features = false }
|
||||
hex = { version = "0.4.3", features = ["serde"] }
|
||||
jetstream_wireformat = "6.0.0"
|
||||
mac_address = { version = "1.1.7", optional = true }
|
||||
serde = { version = "1.0.210", features = ["derive"] }
|
||||
serde_json = "1.0.128"
|
||||
sha1 = { version = "0.10.6", optional = true }
|
||||
|
@ -35,6 +36,7 @@ ulid = ["dep:ulid"]
|
|||
openapi = ["dep:utoipa"]
|
||||
git = ["dep:git2"]
|
||||
graphql = ["dep:async-graphql"]
|
||||
node = ["dep:mac_address"]
|
||||
|
||||
[dev-dependencies]
|
||||
insta = { version = "1.40.0", features = ["yaml"] }
|
||||
|
|
83
src/lib.rs
83
src/lib.rs
|
@ -4,7 +4,7 @@
|
|||
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use std::{fmt::Display, hash::Hash, path::PathBuf, str::FromStr};
|
||||
use std::{fmt::Display, hash::Hash, str::FromStr};
|
||||
|
||||
use digest::OutputSizeUser;
|
||||
|
||||
|
@ -28,6 +28,9 @@ pub const SEPARATOR: char = 'ː';
|
|||
pub mod blake3;
|
||||
/// fingerprint module
|
||||
pub mod fingerprint;
|
||||
#[cfg(feature = "node")]
|
||||
/// node module
|
||||
pub mod node;
|
||||
#[cfg(feature = "git")]
|
||||
/// git module
|
||||
pub mod oid;
|
||||
|
@ -72,6 +75,8 @@ pub(crate) enum BinaryType {
|
|||
Uuid = 1 << 5,
|
||||
// Fingerprint
|
||||
Fingerprint = 1 << 6,
|
||||
#[cfg(feature = "node")]
|
||||
Node = 1 << 7,
|
||||
}
|
||||
|
||||
impl From<char> for BinaryType {
|
||||
|
@ -90,6 +95,7 @@ impl From<char> for BinaryType {
|
|||
#[cfg(feature = "uuid")]
|
||||
'i' => Self::Uuid,
|
||||
'f' => Self::Fingerprint,
|
||||
'n' => Self::Node,
|
||||
_ => Self::Unknown,
|
||||
}
|
||||
}
|
||||
|
@ -99,19 +105,21 @@ impl BinaryType {
|
|||
fn char_code(&self) -> char {
|
||||
match self {
|
||||
#[cfg(feature = "sha1")]
|
||||
Self::Sha1 => '1',
|
||||
BinaryType::Sha1 => '1',
|
||||
#[cfg(feature = "sha2")]
|
||||
Self::Sha256 => '2',
|
||||
BinaryType::Sha256 => '2',
|
||||
#[cfg(feature = "sha3")]
|
||||
Self::Sha3_512 => '3',
|
||||
BinaryType::Sha3_512 => '3',
|
||||
#[cfg(feature = "blake3")]
|
||||
Self::Blake3 => 'b',
|
||||
BinaryType::Blake3 => 'b',
|
||||
#[cfg(feature = "ulid")]
|
||||
Self::Ulid => 'u',
|
||||
BinaryType::Ulid => 'u',
|
||||
#[cfg(feature = "uuid")]
|
||||
Self::Uuid => 'i',
|
||||
Self::Unknown => '0',
|
||||
Self::Fingerprint => 'f',
|
||||
BinaryType::Uuid => 'i',
|
||||
BinaryType::Unknown => '0',
|
||||
BinaryType::Fingerprint => 'f',
|
||||
#[cfg(feature = "node")]
|
||||
BinaryType::Node => 'n',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -120,19 +128,21 @@ impl Display for BinaryType {
|
|||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
#[cfg(feature = "sha1")]
|
||||
Self::Sha1 => write!(f, "sha1"),
|
||||
BinaryType::Sha1 => write!(f, "sha1"),
|
||||
#[cfg(feature = "sha2")]
|
||||
Self::Sha256 => write!(f, "sha256"),
|
||||
BinaryType::Sha256 => write!(f, "sha256"),
|
||||
#[cfg(feature = "sha3")]
|
||||
Self::Sha3_512 => write!(f, "sha3-512"),
|
||||
BinaryType::Sha3_512 => write!(f, "sha3-512"),
|
||||
#[cfg(feature = "blake3")]
|
||||
Self::Blake3 => write!(f, "blake3"),
|
||||
BinaryType::Blake3 => write!(f, "blake3"),
|
||||
#[cfg(feature = "ulid")]
|
||||
Self::Ulid => write!(f, "ulid"),
|
||||
BinaryType::Ulid => write!(f, "ulid"),
|
||||
#[cfg(feature = "uuid")]
|
||||
Self::Uuid => write!(f, "uuid"),
|
||||
Self::Unknown => write!(f, "unknown"),
|
||||
Self::Fingerprint => write!(f, "fingerprint"),
|
||||
BinaryType::Uuid => write!(f, "uuid"),
|
||||
BinaryType::Unknown => write!(f, "unknown"),
|
||||
BinaryType::Fingerprint => write!(f, "fingerprint"),
|
||||
#[cfg(feature = "node")]
|
||||
BinaryType::Node => write!(f, "node"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -193,6 +203,8 @@ impl PartialEq for OkId {
|
|||
(Digest::Uuid(_), _) => false,
|
||||
(Digest::Fingerprint(a), Digest::Fingerprint(b)) => a == b,
|
||||
(Digest::Fingerprint(_), _) => false,
|
||||
(Digest::Node(a), Digest::Node(b)) => a == b,
|
||||
(Digest::Node(_), _) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -219,6 +231,7 @@ impl Hash for OkId {
|
|||
Digest::Ulid(d) => d.hash(state),
|
||||
Digest::Uuid(d) => d.hash(state),
|
||||
Digest::Fingerprint(d) => d.hash(state),
|
||||
Digest::Node(d) => d.hash(state),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -322,6 +335,10 @@ fn parse_okid(s: &str) -> Result<OkId, Error> {
|
|||
hash_type,
|
||||
digest: Digest::Fingerprint(rest.parse()?),
|
||||
}),
|
||||
BinaryType::Node => Ok(OkId {
|
||||
hash_type,
|
||||
digest: Digest::Node(rest.parse()?),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -341,6 +358,8 @@ enum Digest {
|
|||
#[cfg(feature = "uuid")]
|
||||
Uuid(crate::uuid::Uuid),
|
||||
Fingerprint(crate::fingerprint::Fingerprint),
|
||||
#[cfg(feature = "node")]
|
||||
Node(crate::node::Node),
|
||||
}
|
||||
|
||||
impl Display for OkId {
|
||||
|
@ -361,6 +380,8 @@ impl Display for OkId {
|
|||
#[cfg(feature = "uuid")]
|
||||
Digest::Uuid(uuid) => uuid.fmt(f),
|
||||
Digest::Fingerprint(fingerprint) => fingerprint.fmt(f),
|
||||
#[cfg(feature = "node")]
|
||||
Digest::Node(node) => node.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -384,6 +405,8 @@ impl std::fmt::Debug for OkId {
|
|||
Digest::Uuid(uuid) => std::fmt::Display::fmt(uuid, f),
|
||||
|
||||
Digest::Fingerprint(fingerprint) => std::fmt::Display::fmt(fingerprint, f),
|
||||
#[cfg(feature = "node")]
|
||||
Digest::Node(node) => std::fmt::Display::fmt(node, f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -428,6 +451,7 @@ impl jetstream_wireformat::WireFormat for OkId {
|
|||
Digest::Ulid(_ulid) => 128 / 8,
|
||||
Digest::Uuid(_uuid) => 128 / 8,
|
||||
Digest::Fingerprint(_fingerprint) => 64 / 8,
|
||||
Digest::Node(_node) => 6 ,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -453,6 +477,9 @@ impl jetstream_wireformat::WireFormat for OkId {
|
|||
Digest::Fingerprint(fingerprint) => {
|
||||
u64::encode(&fingerprint.0, writer)?;
|
||||
}
|
||||
Digest::Node(node) => {
|
||||
Data::encode(&Data(node.0.into()), writer)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -536,6 +563,18 @@ impl jetstream_wireformat::WireFormat for OkId {
|
|||
digest: Digest::Fingerprint(crate::fingerprint::Fingerprint(data)),
|
||||
})
|
||||
}
|
||||
BinaryType::Node => {
|
||||
let data = Data::decode(reader)?;
|
||||
let data = data.get(0..6).unwrap();
|
||||
let mut buf = [0; 6];
|
||||
if data.len() == 6 {
|
||||
buf.copy_from_slice(data);
|
||||
}
|
||||
Ok(OkId {
|
||||
hash_type: BinaryType::Node,
|
||||
digest: Digest::Node(crate::node::Node(buf)),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -806,4 +845,14 @@ mod okid_tests {
|
|||
|
||||
assert_eq!(file, new_file);
|
||||
}
|
||||
|
||||
#[cfg(feature = "node")]
|
||||
#[test]
|
||||
fn test_node_display() {
|
||||
use mac_address::MacAddressIterator;
|
||||
let binary_id = OkId::from(
|
||||
MacAddressIterator::new().unwrap_or_else(|_| panic!("No mac address found")),
|
||||
);
|
||||
assert_eq!(binary_id.to_string().len(), 15);
|
||||
}
|
||||
}
|
||||
|
|
78
src/node.rs
Normal file
78
src/node.rs
Normal file
|
@ -0,0 +1,78 @@
|
|||
use std::{fmt::Display, str::FromStr};
|
||||
|
||||
use mac_address::{MacAddress, MacAddressIterator};
|
||||
|
||||
use crate::OkId;
|
||||
|
||||
/// Node ID type.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub(super) struct Node(pub(crate) [u8; 6]);
|
||||
|
||||
impl From<MacAddress> for OkId {
|
||||
fn from(mac: MacAddress) -> Self {
|
||||
OkId {
|
||||
hash_type: crate::BinaryType::Node,
|
||||
digest: crate::Digest::Node(Node(mac.bytes())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MacAddressIterator> for OkId {
|
||||
fn from(iter: MacAddressIterator) -> Self {
|
||||
let mut iter = iter.into_iter();
|
||||
let mut bytes_now = iter.next().unwrap().bytes();
|
||||
for bytes in iter {
|
||||
bytes_now
|
||||
.iter_mut()
|
||||
.zip(bytes.bytes().iter())
|
||||
.for_each(|(a, b)| *a ^= b);
|
||||
}
|
||||
OkId {
|
||||
hash_type: crate::BinaryType::Node,
|
||||
digest: crate::Digest::Node(Node(bytes_now)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Node {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
hex::encode(self.0).fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Node {
|
||||
type Err = super::Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Ok(Node(
|
||||
MacAddress::from_str(s)
|
||||
.map_err(|_| super::Error::InvalidFormat)?
|
||||
.bytes(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_node_from_mac_address() {
|
||||
let mac = MacAddress::new([0x00, 0x11, 0x22, 0x33, 0x44, 0x55]);
|
||||
let node = OkId::from(mac);
|
||||
assert_eq!(
|
||||
node,
|
||||
OkId {
|
||||
hash_type: crate::BinaryType::Node,
|
||||
digest: crate::Digest::Node(Node([0x00, 0x11, 0x22, 0x33, 0x44, 0x55])),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_node_from_mac_address_iterator() {
|
||||
let iter = MacAddressIterator::new().unwrap();
|
||||
let id = OkId::from(iter);
|
||||
assert_eq!(id.hash_type, crate::BinaryType::Node);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue