first commit

This commit is contained in:
sevki 2024-09-20 14:59:04 +01:00
commit 0722e3dac0
12 changed files with 1048 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target

589
Cargo.lock generated Normal file
View file

@ -0,0 +1,589 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "arrayref"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
[[package]]
name = "arrayvec"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]]
name = "blake3"
version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d82033247fd8e890df8f740e407ad4d038debb9eb1f40533fffb32e7d17dc6f7"
dependencies = [
"arrayref",
"arrayvec",
"cc",
"cfg-if",
"constant_time_eq",
]
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "bumpalo"
version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cc"
version = "1.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0"
dependencies = [
"shlex",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "console"
version = "0.15.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
dependencies = [
"encode_unicode",
"lazy_static",
"libc",
"windows-sys",
]
[[package]]
name = "constant_time_eq"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
[[package]]
name = "cpufeatures"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0"
dependencies = [
"libc",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]]
name = "encode_unicode"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]]
name = "enumflags2"
version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d"
dependencies = [
"enumflags2_derive",
]
[[package]]
name = "enumflags2_derive"
version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "getrandom"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"js-sys",
"libc",
"wasi",
"wasm-bindgen",
]
[[package]]
name = "hex"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
dependencies = [
"serde",
]
[[package]]
name = "insta"
version = "1.40.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6593a41c7a73841868772495db7dc1e8ecab43bb5c0b6da2059246c4b506ab60"
dependencies = [
"console",
"lazy_static",
"linked-hash-map",
"serde",
"similar",
]
[[package]]
name = "js-sys"
version = "0.3.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "keccak"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654"
dependencies = [
"cpufeatures",
]
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
version = "0.2.158"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
[[package]]
name = "linked-hash-map"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]]
name = "log"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "okid"
version = "0.1.1"
dependencies = [
"blake3",
"digest",
"enumflags2",
"hex",
"insta",
"serde",
"serde_bytes",
"sha1",
"sha2",
"sha3",
"ulid",
"uuid",
]
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "ppv-lite86"
version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
dependencies = [
"zerocopy",
]
[[package]]
name = "proc-macro2"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "serde"
version = "1.0.210"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_bytes"
version = "0.11.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a"
dependencies = [
"serde",
]
[[package]]
name = "serde_derive"
version = "1.0.210"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "sha1"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "sha2"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "sha3"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60"
dependencies = [
"digest",
"keccak",
]
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "similar"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e"
[[package]]
name = "syn"
version = "2.0.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "ulid"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04f903f293d11f31c0c29e4148f6dc0d033a7f80cebc0282bea147611667d289"
dependencies = [
"getrandom",
"rand",
"web-time",
]
[[package]]
name = "unicode-ident"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
[[package]]
name = "uuid"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5"
dependencies = [
"cfg-if",
"once_cell",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484"
[[package]]
name = "web-time"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "zerocopy"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [
"byteorder",
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

30
Cargo.toml Normal file
View file

@ -0,0 +1,30 @@
[package]
name = "okid"
version = "0.1.1"
edition = "2021"
publish = ["oksoftware"]
[dependencies]
blake3 = { version = "1.5.4", optional = true }
digest = "0.10.7"
enumflags2 = "0.7.10"
hex = { version = "0.4.3", features = ["serde"] }
serde = { version = "1.0.210", features = ["derive"] }
serde_bytes = "0.11.15"
sha1 = { version = "0.10.6", optional = true }
sha2 = { version = "0.10.8", optional = true }
sha3 = { version = "0.10.8", optional = true }
ulid = { version = "1.1.3", optional = true }
uuid = { version = "1.10.0", optional = true }
[features]
default = ["sha1", "sha2", "sha3", "blake3"]
sha1 = ["dep:sha1"]
sha2 = ["dep:sha2"]
sha3 = ["dep:sha3"]
blake3 = ["dep:blake3"]
uuid = ["dep:uuid"]
ulid = ["dep:ulid"]
[dev-dependencies]
insta = { version = "1.40.0", features = ["yaml"] }

5
README.md Normal file
View file

@ -0,0 +1,5 @@
# okid
<img src="https://assets.ok.software/okid.png" align="right" width="200">
IDs represented as self identifying strings.

BIN
okid.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 KiB

35
src/blake3.rs Normal file
View file

@ -0,0 +1,35 @@
use std::fmt::Display;
use crate::{BinaryId, BinaryType, Digest};
#[derive(Copy, Clone, Debug, PartialEq)]
pub(super) struct Blake3([u8; 32]);
impl From<blake3::Hasher> for BinaryId {
fn from(value: blake3::Hasher) -> Self {
let data = value.finalize();
let data = data.as_bytes();
let mut buf = [0; 32];
if data.len() == 32 {
buf.copy_from_slice(data);
}
Self {
hash_type: BinaryType::Blake3,
digest: Digest {
blake3: Blake3(buf),
},
}
}
}
impl Display for Blake3 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let buf = self.0;
// Write the hex digest
for byte in buf {
write!(f, "{:02x}", byte)?;
}
Ok(())
}
}

244
src/lib.rs Normal file
View file

@ -0,0 +1,244 @@
//! okid is a library for generating cannocial self-describing binary identifiers for
//! git commits, sha1, sha256, sha512 hashes, ULIDs, UUIDs, datatime, extended,
//! and random identifiers, etc.
#![doc(html_logo_url = "https://assets.ok.software/okid.png")]
#![doc(html_favicon_url = "https://assets.ok.software/okid.png")]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
#![deny(missing_docs)]
use std::fmt::Display;
use enumflags2::{bitflags, BitFlags};
use serde::{Deserialize, Serialize};
#[cfg(feature = "blake3")]
/// blake3 module
pub mod blake3;
#[cfg(feature = "sha1")]
/// sha1 module
pub mod sha1;
#[cfg(feature = "sha2")]
/// sha2 module
pub mod sha2;
#[cfg(feature = "sha3")]
/// sha3 module
pub mod sha3;
#[repr(u8)]
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Hash)]
pub(crate) enum BinaryType {
#[cfg(feature = "sha1")]
// Next bit means the size of the digest is of sha1 type
Sha1 = 1 << 0,
#[cfg(feature = "sha2")]
// Next bit means the size of the digest is of sha256 type
Sha256 = 1 << 1,
#[cfg(feature = "sha3")]
// Next bit means the size of the digest is of sha512 type
Sha3_512 = 1 << 2,
#[cfg(feature = "blake3")]
// Next bit means the size of the digest is of blake3 type
Blake3 = 1 << 3,
}
impl From<char> for BinaryType {
fn from(value: char) -> Self {
match value {
#[cfg(feature = "sha1")]
'1' => Self::Sha1,
#[cfg(feature = "sha2")]
'2' => Self::Sha256,
#[cfg(feature = "sha3")]
'3' => Self::Sha3_512,
#[cfg(feature = "blake3")]
'b' => Self::Blake3,
_ => panic!("Invalid binary type"),
}
}
}
impl BinaryType {
fn char_code(&self) -> char {
match self {
#[cfg(feature = "sha1")]
Self::Sha1 => '1',
#[cfg(feature = "sha2")]
Self::Sha256 => '2',
#[cfg(feature = "sha3")]
Self::Sha3_512 => '3',
#[cfg(feature = "blake3")]
Self::Blake3 => 'b',
}
}
}
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"),
#[cfg(feature = "sha2")]
Self::Sha256 => write!(f, "sha256"),
#[cfg(feature = "sha3")]
Self::Sha3_512 => write!(f, "sha3-512"),
#[cfg(feature = "blake3")]
Self::Blake3 => write!(f, "blake3"),
}
}
}
/// Bird is a binary identifier representable as data
pub struct BinaryId {
hash_type: BinaryType,
/// The digest of the binary identifier
digest: Digest,
}
#[bitflags]
#[repr(u8)]
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Hash)]
enum CommonSettings {
Git = 0b10000000,
Obfuscated = 0b01000000,
}
impl From<char> for CommonSettings {
fn from(value: char) -> Self {
match value {
'g' => Self::Git,
'o' => Self::Obfuscated,
_ => panic!("Invalid common setting"),
}
}
}
impl CommonSettings {
fn char_code(&self) -> char {
match self {
Self::Git => 'g',
Self::Obfuscated => 'o',
}
}
}
impl Display for CommonSettings {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let settings = BitFlags::from_flag(*self);
let buf = "+".to_string();
let settings = settings.iter().fold(vec![], |acc, x| {
let mut acc = acc;
acc.push(x.char_code());
acc
});
let settings = settings
.iter()
.fold(String::new(), |acc, x| acc + &x.to_string());
write!(f, "{}", buf + settings.as_str())
}
}
/// Digest of the binary identifier
union Digest {
/// u64 bit fp like hashes, probably not secure
u64: u64,
#[cfg(feature = "sha1")]
/// SHA-1 digest
sha1: crate::sha1::Sha1,
#[cfg(feature = "sha2")]
/// SHA-256 digest
sha256: crate::sha2::Sha256,
#[cfg(feature = "sha3")]
/// SHA-512 digest
sha512: crate::sha3::Sha512,
#[cfg(feature = "blake3")]
blake3: crate::blake3::Blake3,
}
impl From<u64> for Digest {
fn from(value: u64) -> Self {
Self { u64: value }
}
}
impl Display for BinaryId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// Write the binary type code
write!(f, "{}ː", self.hash_type.char_code())?;
unsafe {
match self.hash_type {
#[cfg(feature = "sha1")]
BinaryType::Sha1 => self.digest.sha1.fmt(f),
#[cfg(feature = "sha2")]
BinaryType::Sha256 => self.digest.sha256.fmt(f),
#[cfg(feature = "sha3")]
BinaryType::Sha3_512 => self.digest.sha512.fmt(f),
#[cfg(feature = "blake3")]
BinaryType::Blake3 => self.digest.blake3.fmt(f),
}
}
}
}
#[cfg(test)]
mod binary_id_tests {
#[cfg(feature = "sha1")]
use sha1::Digest as sha1digest;
use crate::BinaryId;
#[cfg(feature = "sha1")]
#[test]
fn test_display() {
let hasher = sha1::Sha1::new();
let binary_id = BinaryId::from(hasher);
insta::assert_yaml_snapshot!(binary_id.to_string(), @r###"
1ː00da39a3ee5e6b4b0d3255bfef95601890afd80709
"###);
}
#[cfg(feature = "sha1")]
#[test]
fn test_display_hello_world() {
let mut hasher = sha1::Sha1::new();
hasher.update(b"hello world");
let binary_id = BinaryId::from(hasher);
insta::assert_yaml_snapshot!(binary_id.to_string(), @r###"
1ː002aae6c35c94fcfb415dbe95f408b9ce91ee846ed
"###);
}
#[cfg(feature = "sha2")]
#[test]
fn test_display_hello_world_sha256() {
let mut hasher = sha2::Sha256::new();
hasher.update(b"hello world");
let binary_id = BinaryId::from(hasher);
insta::assert_yaml_snapshot!(binary_id.to_string(), @r###"
2ː00b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
"###);
}
#[cfg(feature = "sha3")]
#[test]
fn test_display_hello_world_sha3() {
let mut hasher = sha3::Sha3_512::new();
hasher.update(b"hello world");
let binary_id = BinaryId::from(hasher);
insta::assert_yaml_snapshot!(binary_id.to_string(), @r###"
3ː840006653e9ac9e95117a15c915caab81662918e925de9e004f774ff82d7079a40d4d27b1b372657c61d46d470304c88c788b3a4527ad074d1dccbee5dbaa99a
"###);
}
#[cfg(feature = "blake3")]
#[test]
fn test_display_hello_world_blake3() {
let mut hasher = blake3::Hasher::new();
hasher.update(b"hello world");
let binary_id = BinaryId::from(hasher);
insta::assert_yaml_snapshot!(binary_id.to_string(), @r###"
bːd74981efa70a0c880b8d8c1985d075dbcbf679b99a5f9914e5aaf96b831a9e24
"###);
}
}

49
src/sha1.rs Normal file
View file

@ -0,0 +1,49 @@
use std::fmt::Display;
use digest::core_api::CoreWrapper;
use enumflags2::BitFlags;
use super::{BinaryId, BinaryType, CommonSettings, Digest};
#[derive(Copy, Clone, Debug, PartialEq)]
pub(super) struct Sha1(BitFlags<CommonSettings>, [u8; 20]);
#[cfg(feature = "sha1")]
use sha1::Digest as sha1Digest;
#[cfg(feature = "sha1")]
impl From<sha1::Sha1> for BinaryId {
fn from(value: sha1::Sha1) -> Self {
let data = value.finalize();
let data = data.get(0..20).unwrap();
let mut buf = [0; 20];
if data.len() == 20 {
buf.copy_from_slice(data);
}
let empty: BitFlags<CommonSettings> = BitFlags::empty();
Self {
hash_type: BinaryType::Sha1,
digest: Digest {
sha1: Sha1(empty, buf),
},
}
}
}
impl From<sha1::Sha1Core> for BinaryId {
fn from(value: sha1::Sha1Core) -> Self {
CoreWrapper::from_core(value).into()
}
}
impl Display for Sha1 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let settings = self.0;
let buf = self.1;
write!(f, "{:02x}", settings.bits())?;
// Write the hex digest
for byte in buf {
write!(f, "{:02x}", byte)?;
}
Ok(())
}
}

41
src/sha2.rs Normal file
View file

@ -0,0 +1,41 @@
use enumflags2::BitFlags;
use sha2::Digest;
use std::fmt::Display;
use crate::BinaryId;
use super::CommonSettings;
#[derive(Copy, Clone, Debug, PartialEq)]
pub(super) struct Sha256(BitFlags<CommonSettings>, [u8; 32]);
impl From<sha2::Sha256> for BinaryId {
fn from(value: sha2::Sha256) -> Self {
let data = value.finalize();
let data = data.get(0..32).unwrap();
let mut buf = [0; 32];
if data.len() == 32 {
buf.copy_from_slice(data);
}
let empty: BitFlags<CommonSettings> = BitFlags::empty();
Self {
hash_type: super::BinaryType::Sha256,
digest: super::Digest {
sha256: Sha256(empty, buf),
},
}
}
}
impl Display for Sha256 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let settings = self.0;
let buf = self.1;
write!(f, "{:02x}", settings.bits())?;
// Write the hex digest
for byte in buf {
write!(f, "{:02x}", byte)?;
}
Ok(())
}
}

44
src/sha3.rs Normal file
View file

@ -0,0 +1,44 @@
use std::fmt::Display;
use digest::core_api::CoreWrapper;
use sha3::Digest;
use super::BinaryId;
#[derive(Copy, Clone, Debug, PartialEq)]
pub(super) struct Sha512([u8; 64]);
impl From<sha3::Sha3_512> for BinaryId {
fn from(value: sha3::Sha3_512) -> Self {
let data = value.finalize();
let data = data.get(0..64).unwrap();
let mut buf = [0; 64];
if data.len() == 64 {
buf.copy_from_slice(data);
}
Self {
hash_type: super::BinaryType::Sha3_512,
digest: super::Digest {
sha512: Sha512(buf),
},
}
}
}
impl From<sha3::Sha3_512Core> for BinaryId {
fn from(value: sha3::Sha3_512Core) -> Self {
CoreWrapper::from_core(value).into()
}
}
impl Display for Sha512 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let buf = self.0;
// Write the hex digest
for byte in buf {
write!(f, "{:02x}", byte)?;
}
Ok(())
}
}

View file

@ -0,0 +1,5 @@
---
source: src/lib.rs
expression: binary_id.to_string()
---
1ː00da39a3ee5e6b4b0d3255bfef95601890afd80709

View file

@ -0,0 +1,5 @@
---
source: src/lib.rs
expression: binary_id.to_string()
---
1ː002aae6c35c94fcfb415dbe95f408b9ce91ee846ed