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