add nix_hash
This commit is contained in:
parent
af8b7b2384
commit
e4826c62df
16
rust/nix_hash/Cargo.lock
generated
Normal file
16
rust/nix_hash/Cargo.lock
generated
Normal file
|
@ -0,0 +1,16 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "data-encoding"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2"
|
||||
|
||||
[[package]]
|
||||
name = "nix_hash"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"data-encoding",
|
||||
]
|
7
rust/nix_hash/Cargo.toml
Normal file
7
rust/nix_hash/Cargo.toml
Normal file
|
@ -0,0 +1,7 @@
|
|||
[package]
|
||||
name = "nix_hash"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
data-encoding = "2.6.0"
|
64
rust/nix_hash/src/main.rs
Normal file
64
rust/nix_hash/src/main.rs
Normal file
|
@ -0,0 +1,64 @@
|
|||
use data_encoding::BitOrder;
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut binary = data_encoding::HEXLOWER
|
||||
.decode(b"3a99595f4daedd5f52d646e413ea1c989abb910cd2ea18fd98ccddeab68f0883")?;
|
||||
|
||||
let mut spec = data_encoding::Specification::new();
|
||||
spec.symbols.push_str("0123456789abcdfghijklmnpqrsvwxyz");
|
||||
spec.bit_order = BitOrder::LeastSignificantFirst;
|
||||
|
||||
println!(
|
||||
"Found: {}",
|
||||
spec.encoding()?
|
||||
.encode(&binary)
|
||||
.chars()
|
||||
.rev()
|
||||
.collect::<String>()
|
||||
);
|
||||
println!("Expected: 10q8iyvfmpfck3yiisnj1j8vp6lq3km17r26sr95zpdf9mgmk69s");
|
||||
println!("Found: {}", encode_nix32(&binary));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
static NIX32_CHARS: &[u8; 32] = b"0123456789abcdfghijklmnpqrsvwxyz";
|
||||
|
||||
fn encode_nix32(input: &[u8]) -> String {
|
||||
let length = if input.len() == 0 {
|
||||
0
|
||||
} else {
|
||||
// ceil(input.len() * 8 / 5)
|
||||
(input.len() * 8 - 1) / 5 + 1
|
||||
};
|
||||
let mut output = String::with_capacity(length);
|
||||
|
||||
// nix32 hashes feel like they're a bug that stuck
|
||||
// The output is backwards and bits are grouped
|
||||
// from the least significant bit in each byte
|
||||
// instead of the most significant bit.
|
||||
// e.g. encoding "Meow" gives us:
|
||||
// Char: M (0x4d) e (0x65) o (0x6f) w (0x77)
|
||||
// Value: 0 1 0 0 1 1 0 1 | 0 1 1 0 0 1 0 1 | 0 1 1 0 1 1 1 1 | 0 1 1 1 0 1 1 1
|
||||
// Out No.: 5 5 5 6 6 6 6 6 | 3 4 4 4 4 4 5 5 | 2 2 2 2 3 3 3 3 | 0 0 1 1 1 1 1 2
|
||||
// Out Bit: 2 1 0 4 3 2 1 0 | 0 5 4 3 2 1 4 3 | 3 2 1 0 4 3 2 1 | 1 0 4 3 2 1 0 4
|
||||
//
|
||||
// where "Out No." is the index of the output charater responsible for a given bit,
|
||||
// and 2**"Out Bit" is the value of a given bit for its output character.
|
||||
//
|
||||
// In this example, characters 0 to 6 have values
|
||||
// 0x01, 0x1b, 0x16, 0x1e, 0x19, 0xa, 0xd.
|
||||
// Indexing into the alphabet gives us "1vnyrad"
|
||||
|
||||
for char_no in 0..length {
|
||||
let bit_no = (length - char_no - 1) * 5;
|
||||
let byte_no = bit_no / 8;
|
||||
let offset = bit_no % 8;
|
||||
|
||||
let next_byte = input.get(byte_no + 1).unwrap_or(&0);
|
||||
let value = (input[byte_no] as u16 >> offset) | ((*next_byte as u16) << (8 - offset));
|
||||
output.push(NIX32_CHARS[(value & 0x1f) as usize] as char);
|
||||
}
|
||||
|
||||
output
|
||||
}
|
Loading…
Reference in a new issue