use crate::errors::MatterError;
use crate::keri::KERIError;
use base64::{engine::general_purpose, Engine};
use num_bigint::BigUint;
use num_traits::ToPrimitive;
use once_cell::sync::Lazy;
use std::any::Any;
use std::collections::HashMap;
use std::fmt::Display;
use std::{fmt, str};
pub mod bexter;
pub mod cigar;
pub mod counting;
pub mod dater;
pub mod diger;
pub mod ilker;
pub mod indexing;
pub mod labeler;
pub mod number;
pub mod pather;
pub mod prefixer;
pub mod saider;
pub mod seqner;
pub mod signing;
pub mod tagger;
pub mod texter;
pub mod tholder;
pub mod verfer;
#[derive(Debug, Clone, PartialEq)]
pub struct Versionage {
pub major: u32,
pub minor: u32,
}
pub const VERSION: Versionage = Versionage { major: 1, minor: 0 };
#[allow(dead_code)]
pub const VRSN_1_0: Versionage = Versionage { major: 1, minor: 0 };
#[allow(dead_code)]
pub const VRSN_2_0: Versionage = Versionage { major: 2, minor: 0 };
pub const PAD: &str = "_";
impl Display for Versionage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}.{}", self.major, self.minor)
}
}
impl From<String> for Versionage {
fn from(version_str: String) -> Self {
if let Ok(versionage) = Self::parse_version_string(&version_str) {
return versionage;
}
Versionage { major: 1, minor: 0 }
}
}
impl From<&str> for Versionage {
fn from(version_str: &str) -> Self {
Self::from(version_str.to_string())
}
}
impl Versionage {
pub fn to_vec(&self) -> Vec<u8> {
let mut vec = Vec::new();
vec.push(self.major as u8);
vec.push(self.minor as u8);
vec
}
fn parse_version_string(version_str: &str) -> Result<Self, KERIError> {
if version_str.len() < 6 {
return Err(KERIError::VersionError(format!(
"Version string too short: {}",
version_str
)));
}
if !version_str.starts_with("KERI") {
return Err(KERIError::VersionError(format!(
"Invalid version string prefix: {}",
version_str
)));
}
let major_char = version_str.chars().nth(4).unwrap();
let minor_char = version_str.chars().nth(5).unwrap();
let major = u32::from_str_radix(&major_char.to_string(), 16).map_err(|_| {
KERIError::VersionError(format!("Invalid major version: {}", major_char))
})?;
let minor = u32::from_str_radix(&minor_char.to_string(), 16).map_err(|_| {
KERIError::VersionError(format!("Invalid minor version: {}", minor_char))
})?;
Ok(Versionage { major, minor })
}
}
pub static B64_CHR_BY_IDX: Lazy<HashMap<u8, char>> = Lazy::new(|| {
let mut map = HashMap::new();
for (idx, c) in (65u8..91u8).enumerate() {
map.insert(idx as u8, c as char);
}
for (idx, c) in (97u8..123u8).enumerate() {
map.insert((idx + 26) as u8, c as char);
}
for (idx, c) in (48u8..58u8).enumerate() {
map.insert((idx + 52) as u8, c as char);
}
map.insert(62, '-');
map.insert(63, '_');
map
});
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Tiers {
LOW,
MED,
HIGH,
}
impl Tiers {
pub const LOW: &'static str = "low";
pub const MED: &'static str = "med";
pub const HIGH: &'static str = "high";
}
impl From<&str> for Tiers {
fn from(s: &str) -> Self {
match s {
"low" => Tiers::LOW,
"med" => Tiers::MED,
"high" => Tiers::HIGH,
_ => Tiers::LOW, }
}
}
impl Display for Tiers {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let str = match self {
Tiers::LOW => "low",
Tiers::MED => "med",
Tiers::HIGH => "high",
};
write!(f, "{}", str)
}
}
#[allow(dead_code)]
pub static B64_IDX_BY_CHR: Lazy<HashMap<char, u8>> = Lazy::new(|| {
let mut map = HashMap::new();
for (&idx, &c) in B64_CHR_BY_IDX.iter() {
map.insert(c, idx);
}
map
});
#[allow(dead_code)]
pub mod cold_dex {
use once_cell::sync::Lazy;
use std::collections::HashMap;
pub const ANB64: u8 = 0o0; pub const CTB64: u8 = 0o1; pub const OPB64: u8 = 0o2; pub const JSON: u8 = 0o3; pub const MGPK1: u8 = 0o4; pub const CBOR: u8 = 0o5; pub const MGPK2: u8 = 0o6; pub const CTOPB2: u8 = 0o7;
pub static MAP: Lazy<HashMap<&'static str, u8>> = Lazy::new(|| {
let mut map = HashMap::new();
map.insert("ANB64", ANB64);
map.insert("CTB64", CTB64);
map.insert("OPB64", OPB64);
map.insert("JSON,", JSON);
map.insert("MGPK1", MGPK1);
map.insert("CBOR,", CBOR);
map.insert("MGPK2", MGPK2);
map.insert("CTOPB2", CTOPB2);
map
});
pub static TUPLE: Lazy<Vec<u8>> =
Lazy::new(|| vec![ANB64, CTB64, OPB64, JSON, MGPK1, CBOR, MGPK2, CTOPB2]);
}
#[derive(Debug, Clone, PartialEq)]
pub struct Coldage {
pub msg: &'static str,
pub txt: &'static str,
pub bny: &'static str,
pub ano: &'static str,
}
impl Coldage {
pub fn new(msg: &'static str, txt: &'static str, bny: &'static str, ano: &'static str) -> Self {
Self { msg, txt, bny, ano }
}
}
impl Default for Coldage {
fn default() -> Self {
Self {
msg: "msg",
txt: "txt",
bny: "bny",
ano: "ano",
}
}
}
impl Display for Coldage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Coldage(msg='{}', txt='{}', bny='{}', ano='{}')",
self.msg, self.txt, self.bny, self.ano
)
}
}
pub const COLDS: Coldage = Coldage {
msg: "msg",
txt: "txt",
bny: "bny",
ano: "ano",
};
pub fn sniff(ims: &[u8]) -> Result<&'static str, MatterError> {
if ims.is_empty() {
return Err(MatterError::ShortageError("Need more bytes.".to_string()));
}
let tritet = ims[0] >> 5;
if tritet == cold_dex::JSON
|| tritet == cold_dex::MGPK1
|| tritet == cold_dex::CBOR
|| tritet == cold_dex::MGPK2
{
return Ok(COLDS.msg);
}
if tritet == cold_dex::CTB64 || tritet == cold_dex::OPB64 {
return Ok(COLDS.txt);
}
if tritet == cold_dex::CTOPB2 {
return Ok(COLDS.bny);
}
if tritet == cold_dex::ANB64 {
return Ok(COLDS.ano);
}
Err(MatterError::ColdStartError(format!(
"Unexpected tritet={} at stream start.",
tritet
)))
}
#[allow(dead_code)]
pub mod trait_dex {
use once_cell::sync::Lazy;
use std::collections::HashMap;
pub const EST_ONLY: &str = "EO";
pub const DO_NOT_DELEGATE: &str = "DND";
pub const REGISTRAR_BACKERS: &str = "RB";
pub const NO_BACKERS: &str = "NB";
pub const NO_REGISTRAR_BACKERS: &str = "NRB";
pub const DELEGATE_IS_DELEGATOR: &str = "DID";
pub static MAP: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
let mut map = HashMap::new();
map.insert("EST_ONLY", EST_ONLY);
map.insert("DO_NOT_DELEGATE", DO_NOT_DELEGATE);
map.insert("REGISTRAR_BACKERS", REGISTRAR_BACKERS);
map.insert("NO_BACKERS", NO_BACKERS);
map.insert("NO_REGISTRAR_BACKERS", NO_REGISTRAR_BACKERS);
map.insert("DELEGATE_IS_DELEGATOR", DELEGATE_IS_DELEGATOR);
map
});
pub static TUPLE: [&'static str; 6] = [
EST_ONLY,
DO_NOT_DELEGATE,
REGISTRAR_BACKERS,
NO_BACKERS,
NO_REGISTRAR_BACKERS,
DELEGATE_IS_DELEGATOR,
];
}
#[allow(dead_code)]
pub mod mtr_dex {
pub const ED25519_SEED: &str = "A"; pub const ED25519N: &str = "B"; pub const X25519: &str = "C"; pub const ED25519: &str = "D"; pub const BLAKE3_256: &str = "E"; pub const BLAKE2B_256: &str = "F"; pub const BLAKE2S_256: &str = "G"; pub const SHA3_256: &str = "H"; pub const SHA2_256: &str = "I"; pub const ECDSA_256K1_SEED: &str = "J"; pub const ED448_SEED: &str = "K"; pub const X448: &str = "L"; pub const SHORT: &str = "M"; pub const BIG: &str = "N"; pub const X25519_PRIVATE: &str = "O"; pub const X25519_CIPHER_SEED: &str = "P"; pub const ECDSA_256R1_SEED: &str = "Q"; pub const TALL: &str = "R"; pub const LARGE: &str = "S"; pub const GREAT: &str = "T"; pub const VAST: &str = "U"; pub const LABEL1: &str = "V"; pub const LABEL2: &str = "W"; pub const TAG3: &str = "X"; pub const TAG7: &str = "Y"; pub const BLIND: &str = "Z"; pub const SALT_128: &str = "0A"; pub const ED25519_SIG: &str = "0B"; pub const ECDSA_256K1_SIG: &str = "0C"; pub const BLAKE3_512: &str = "0D"; pub const BLAKE2B_512: &str = "0E"; pub const SHA3_512: &str = "0F"; pub const SHA2_512: &str = "0G"; pub const LONG: &str = "0H"; pub const ECDSA_256R1_SIG: &str = "0I"; pub const TAG1: &str = "0J"; pub const TAG2: &str = "0K"; pub const TAG5: &str = "0L"; pub const TAG6: &str = "0M"; pub const TAG9: &str = "0N"; pub const TAG10: &str = "0O"; pub const GRAM_HEAD_NECK: &str = "0P"; pub const GRAM_HEAD: &str = "0Q"; pub const GRAM_HEAD_AID_NECK: &str = "0R"; pub const GRAM_HEAD_AID: &str = "0S"; pub const ECDSA_256K1N: &str = "1AAA"; pub const ECDSA_256K1: &str = "1AAB"; pub const ED448N: &str = "1AAC"; pub const ED448: &str = "1AAD"; pub const ED448_SIG: &str = "1AAE"; pub const TAG4: &str = "1AAF"; pub const DATE_TIME: &str = "1AAG"; pub const X25519_CIPHER_SALT: &str = "1AAH"; pub const ECDSA_256R1N: &str = "1AAI"; pub const ECDSA_256R1: &str = "1AAJ"; pub const NULL: &str = "1AAK"; pub const NO: &str = "1AAL"; pub const YES: &str = "1AAM"; pub const TAG8: &str = "1AAN"; pub const TBD0S: &str = "1__-"; pub const TBD0: &str = "1___"; pub const TBD1S: &str = "2__-"; pub const TBD1: &str = "2___"; pub const TBD2S: &str = "3__-"; pub const TBD2: &str = "3___"; pub const STR_B64_L0: &str = "4A"; pub const STR_B64_L1: &str = "5A"; pub const STR_B64_L2: &str = "6A"; pub const STR_B64_BIG_L0: &str = "7AAA"; pub const STR_B64_BIG_L1: &str = "8AAA"; pub const STR_B64_BIG_L2: &str = "9AAA"; pub const BYTES_L0: &str = "4B"; pub const BYTES_L1: &str = "5B"; pub const BYTES_L2: &str = "6B"; pub const BYTES_BIG_L0: &str = "7AAB"; pub const BYTES_BIG_L1: &str = "8AAB"; pub const BYTES_BIG_L2: &str = "9AAB"; pub const X25519_CIPHER_L0: &str = "4C"; pub const X25519_CIPHER_L1: &str = "5C"; pub const X25519_CIPHER_L2: &str = "6C"; pub const X25519_CIPHER_BIG_L0: &str = "7AAC"; pub const X25519_CIPHER_BIG_L1: &str = "8AAC"; pub const X25519_CIPHER_BIG_L2: &str = "9AAC"; pub const X25519_CIPHER_QB64_L0: &str = "4D"; pub const X25519_CIPHER_QB64_L1: &str = "5D"; pub const X25519_CIPHER_QB64_L2: &str = "6D"; pub const X25519_CIPHER_QB64_BIG_L0: &str = "7AAD"; pub const X25519_CIPHER_QB64_BIG_L1: &str = "8AAD"; pub const X25519_CIPHER_QB64_BIG_L2: &str = "9AAD"; pub const X25519_CIPHER_QB2_L0: &str = "4E"; pub const X25519_CIPHER_QB2_L1: &str = "5E"; pub const X25519_CIPHER_QB2_L2: &str = "6E"; pub const X25519_CIPHER_QB2_BIG_L0: &str = "7AAE"; pub const X25519_CIPHER_QB2_BIG_L1: &str = "8AAE"; pub const X25519_CIPHER_QB2_BIG_L2: &str = "9AAE"; }
#[allow(dead_code)]
pub static MTR_DEX_MAP: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
let mut map = HashMap::new();
map.insert("ED25519_SEED", mtr_dex::ED25519_SEED);
map.insert("ED25519N", mtr_dex::ED25519N);
map.insert("X25519", mtr_dex::X25519);
map.insert("ED25519", mtr_dex::ED25519);
map.insert("BLAKE3_256", mtr_dex::BLAKE3_256);
map.insert("BLAKE2B_256", mtr_dex::BLAKE2B_256);
map.insert("BLAKE2S_256", mtr_dex::BLAKE2S_256);
map.insert("SHA3_256", mtr_dex::SHA3_256);
map.insert("SHA2_256", mtr_dex::SHA2_256);
map.insert("ECDSA_256K1_SEED", mtr_dex::ECDSA_256K1_SEED);
map.insert("ED448_SEED", mtr_dex::ED448_SEED);
map.insert("X448", mtr_dex::X448);
map.insert("SHORT", mtr_dex::SHORT);
map.insert("BIG", mtr_dex::BIG);
map.insert("X25519_PRIVATE", mtr_dex::X25519_PRIVATE);
map.insert("X25519_CIPHER_SEED", mtr_dex::X25519_CIPHER_SEED);
map.insert("ECDSA_256R1_SEED", mtr_dex::ECDSA_256R1_SEED);
map.insert("TALL", mtr_dex::TALL);
map.insert("LARGE", mtr_dex::LARGE);
map.insert("GREAT", mtr_dex::GREAT);
map.insert("VAST", mtr_dex::VAST);
map.insert("LABEL1", mtr_dex::LABEL1);
map.insert("LABEL2", mtr_dex::LABEL2);
map.insert("TAG3", mtr_dex::TAG3);
map.insert("TAG7", mtr_dex::TAG7);
map.insert("BLIND", mtr_dex::BLIND);
map.insert("SALT_128", mtr_dex::SALT_128);
map.insert("ED25519_SIG", mtr_dex::ED25519_SIG);
map.insert("ECDSA_256K1_SIG", mtr_dex::ECDSA_256K1_SIG);
map.insert("BLAKE3_512", mtr_dex::BLAKE3_512);
map.insert("BLAKE2B_512", mtr_dex::BLAKE2B_512);
map.insert("SHA3_512", mtr_dex::SHA3_512);
map.insert("SHA2_512", mtr_dex::SHA2_512);
map.insert("LONG", mtr_dex::LONG);
map.insert("ECDSA_256R1_SIG", mtr_dex::ECDSA_256R1_SIG);
map.insert("TAG1", mtr_dex::TAG1);
map.insert("TAG2", mtr_dex::TAG2);
map.insert("TAG5", mtr_dex::TAG5);
map.insert("TAG6", mtr_dex::TAG6);
map.insert("TAG9", mtr_dex::TAG9);
map.insert("TAG10", mtr_dex::TAG10);
map.insert("GRAM_HEAD_NECK", mtr_dex::GRAM_HEAD_NECK);
map.insert("GRAM_HEAD", mtr_dex::GRAM_HEAD);
map.insert("GRAM_HEAD_AID_NECK", mtr_dex::GRAM_HEAD_AID_NECK);
map.insert("GRAM_HEAD_AID", mtr_dex::GRAM_HEAD_AID);
map.insert("ECDSA_256K1N", mtr_dex::ECDSA_256K1N);
map.insert("ECDSA_256K1", mtr_dex::ECDSA_256K1);
map.insert("ED448N", mtr_dex::ED448N);
map.insert("ED448", mtr_dex::ED448);
map.insert("ED448_SIG", mtr_dex::ED448_SIG);
map.insert("TAG4", mtr_dex::TAG4);
map.insert("DATE_TIME", mtr_dex::DATE_TIME);
map.insert("X25519_CIPHER_SALT", mtr_dex::X25519_CIPHER_SALT);
map.insert("ECDSA_256R1N", mtr_dex::ECDSA_256R1N);
map.insert("ECDSA_256R1", mtr_dex::ECDSA_256R1);
map.insert("NULL", mtr_dex::NULL);
map.insert("NO", mtr_dex::NO);
map.insert("YES", mtr_dex::YES);
map.insert("TAG8", mtr_dex::TAG8);
map.insert("TBD0S", mtr_dex::TBD0S);
map.insert("TBD0", mtr_dex::TBD0);
map.insert("TBD1S", mtr_dex::TBD1S);
map.insert("TBD1", mtr_dex::TBD1);
map.insert("TBD2S", mtr_dex::TBD2S);
map.insert("TBD2", mtr_dex::TBD2);
map.insert("STR_B64_L0", mtr_dex::STR_B64_L0);
map.insert("STR_B64_L1", mtr_dex::STR_B64_L1);
map.insert("STR_B64_L2", mtr_dex::STR_B64_L2);
map.insert("STR_B64_BIG_L0", mtr_dex::STR_B64_BIG_L0);
map.insert("STR_B64_BIG_L1", mtr_dex::STR_B64_BIG_L1);
map.insert("STR_B64_BIG_L2", mtr_dex::STR_B64_BIG_L2);
map.insert("BYTES_L0", mtr_dex::BYTES_L0);
map.insert("BYTES_L1", mtr_dex::BYTES_L1);
map.insert("BYTES_L2", mtr_dex::BYTES_L2);
map.insert("BYTES_BIG_L0", mtr_dex::BYTES_BIG_L0);
map.insert("BYTES_BIG_L1", mtr_dex::BYTES_BIG_L1);
map.insert("BYTES_BIG_L2", mtr_dex::BYTES_BIG_L2);
map.insert("X25519_CIPHER_L0", mtr_dex::X25519_CIPHER_L0);
map.insert("X25519_CIPHER_L1", mtr_dex::X25519_CIPHER_L1);
map.insert("X25519_CIPHER_L2", mtr_dex::X25519_CIPHER_L2);
map.insert("X25519_CIPHER_BIG_L0", mtr_dex::X25519_CIPHER_BIG_L0);
map.insert("X25519_CIPHER_BIG_L1", mtr_dex::X25519_CIPHER_BIG_L1);
map.insert("X25519_CIPHER_BIG_L2", mtr_dex::X25519_CIPHER_BIG_L2);
map.insert("X25519_CIPHER_QB64_L0", mtr_dex::X25519_CIPHER_QB64_L0);
map.insert("X25519_CIPHER_QB64_L1", mtr_dex::X25519_CIPHER_QB64_L1);
map.insert("X25519_CIPHER_QB64_L2", mtr_dex::X25519_CIPHER_QB64_L2);
map.insert(
"X25519_CIPHER_QB64_BIG_L0",
mtr_dex::X25519_CIPHER_QB64_BIG_L0,
);
map.insert(
"X25519_CIPHER_QB64_BIG_L1",
mtr_dex::X25519_CIPHER_QB64_BIG_L1,
);
map.insert(
"X25519_CIPHER_QB64_BIG_L2",
mtr_dex::X25519_CIPHER_QB64_BIG_L2,
);
map.insert("X25519_CIPHER_QB2_L0", mtr_dex::X25519_CIPHER_QB2_L0);
map.insert("X25519_CIPHER_QB2_L1", mtr_dex::X25519_CIPHER_QB2_L1);
map.insert("X25519_CIPHER_QB2_L2", mtr_dex::X25519_CIPHER_QB2_L2);
map.insert(
"X25519_CIPHER_QB2_BIG_L0",
mtr_dex::X25519_CIPHER_QB2_BIG_L0,
);
map.insert(
"X25519_CIPHER_QB2_BIG_L1",
mtr_dex::X25519_CIPHER_QB2_BIG_L1,
);
map.insert(
"X25519_CIPHER_QB2_BIG_L2",
mtr_dex::X25519_CIPHER_QB2_BIG_L2,
);
map
});
#[allow(dead_code)]
pub mod small_vrz_dex {
use once_cell::sync::Lazy;
use std::collections::HashMap;
pub const LEAD0: &str = "4"; pub const LEAD1: &str = "5"; pub const LEAD2: &str = "6";
pub static MAP: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
let mut map = HashMap::new();
map.insert("LEAD0", LEAD0);
map.insert("LEAD1", LEAD1);
map.insert("LEAD2", LEAD2);
map
});
pub static TUPLE: [&'static str; 3] = [LEAD0, LEAD1, LEAD2];
}
#[allow(dead_code)]
pub mod large_vrz_dex {
use once_cell::sync::Lazy;
use std::collections::HashMap;
pub const LEAD0_BIG: &str = "7"; pub const LEAD1_BIG: &str = "8"; pub const LEAD2_BIG: &str = "9";
pub static MAP: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
let mut map = HashMap::new();
map.insert("LEAD0_BIG", LEAD0_BIG);
map.insert("LEAD1_BIG", LEAD1_BIG);
map.insert("LEAD2_BIG", LEAD2_BIG);
map
});
pub static TUPLE: [&'static str; 3] = [LEAD0_BIG, LEAD1_BIG, LEAD2_BIG];
}
#[allow(dead_code)]
pub mod bex_dex {
pub const STR_B64_L0: &str = "4A";
pub const STR_B64_L1: &str = "5A";
pub const STR_B64_L2: &str = "6A";
pub const STR_B64_BIG_L0: &str = "7AAA";
pub const STR_B64_BIG_L1: &str = "8AAA";
pub const STR_B64_BIG_L2: &str = "9AAA";
pub const MAP: once_cell::sync::Lazy<std::collections::HashMap<&'static str, usize>> =
once_cell::sync::Lazy::new(|| {
let mut map = std::collections::HashMap::new();
map.insert(STR_B64_L0, 2);
map.insert(STR_B64_L1, 2);
map.insert(STR_B64_L2, 2);
map.insert(STR_B64_BIG_L0, 4);
map.insert(STR_B64_BIG_L1, 4);
map.insert(STR_B64_BIG_L2, 4);
map
});
pub const TUPLE: &[&str] = &[
STR_B64_L0,
STR_B64_L1,
STR_B64_L2,
STR_B64_BIG_L0,
STR_B64_BIG_L1,
STR_B64_BIG_L2,
];
}
#[allow(dead_code)]
pub mod tex_dex {
pub const BYTES_L0: &str = "4B";
pub const BYTES_L1: &str = "5B";
pub const BYTES_L2: &str = "6B";
pub const BYTES_BIG_L0: &str = "7AAB";
pub const BYTES_BIG_L1: &str = "8AAB";
pub const BYTES_BIG_L2: &str = "9AAB";
pub const MAP: once_cell::sync::Lazy<std::collections::HashMap<&'static str, usize>> =
once_cell::sync::Lazy::new(|| {
let mut map = std::collections::HashMap::new();
map.insert(BYTES_L0, 2);
map.insert(BYTES_L1, 2);
map.insert(BYTES_L2, 2);
map.insert(BYTES_BIG_L0, 4);
map.insert(BYTES_BIG_L1, 4);
map.insert(BYTES_BIG_L2, 4);
map
});
pub const TUPLE: &[&str] = &[
BYTES_L0,
BYTES_L1,
BYTES_L2,
BYTES_BIG_L0,
BYTES_BIG_L1,
BYTES_BIG_L2,
];
}
#[allow(dead_code)]
pub mod dig_dex {
use once_cell::sync::Lazy;
use std::collections::HashMap;
pub const BLAKE3_256: &str = "E";
pub const BLAKE2B_256: &str = "F";
pub const BLAKE2S_256: &str = "G";
pub const SHA3_256: &str = "H";
pub const SHA2_256: &str = "I";
pub const BLAKE3_512: &str = "0D";
pub const BLAKE2B_512: &str = "0E";
pub const SHA3_512: &str = "0F";
pub const SHA2_512: &str = "0G";
#[allow(dead_code)]
pub static MAP: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
let mut map = HashMap::new();
map.insert("BLAKE3_256", BLAKE3_256);
map.insert("BLAKE2B_256", BLAKE2B_256);
map.insert("BLAKE2S_256", BLAKE2S_256);
map.insert("SHA3_256", SHA3_256);
map.insert("SHA2_256", SHA2_256);
map.insert("BLAKE3_512", BLAKE3_512);
map.insert("BLAKE2B_512", BLAKE2B_512);
map.insert("SHA3_512", SHA3_512);
map.insert("SHA2_512", SHA2_512);
map
});
pub static TUPLE: [&'static str; 9] = [
BLAKE3_256,
BLAKE2B_256,
BLAKE2S_256,
SHA3_256,
SHA2_256,
BLAKE3_512,
BLAKE2B_512,
SHA3_512,
SHA2_512,
];
}
#[allow(dead_code)]
pub mod num_dex {
use once_cell::sync::Lazy;
use std::collections::HashMap;
pub const SHORT: &str = "M";
pub const LONG: &str = "0H";
pub const TALL: &str = "R";
pub const BIG: &str = "N";
pub const LARGE: &str = "S";
pub const GREAT: &str = "T";
pub const HUGE: &str = "0A";
pub const VAST: &str = "U";
pub static MAP: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
let mut map = HashMap::new();
map.insert(SHORT, "SHORT");
map.insert(LONG, "LONG");
map.insert(TALL, "TALL");
map.insert(BIG, "BIG");
map.insert(LARGE, "LARGE");
map.insert(GREAT, "GREAT");
map.insert(HUGE, "HUGE");
map.insert(VAST, "VAST");
map
});
pub static TUPLE: [&'static str; 8] = [SHORT, LONG, TALL, BIG, LARGE, GREAT, HUGE, VAST];
}
#[allow(dead_code)]
pub mod tag_dex {
use once_cell::sync::Lazy;
use std::collections::HashMap;
pub const TAG1: &str = "0J";
pub const TAG2: &str = "0K";
pub const TAG3: &str = "X";
pub const TAG4: &str = "1AAF";
pub const TAG5: &str = "0L";
pub const TAG6: &str = "0M";
pub const TAG7: &str = "Y";
pub const TAG8: &str = "1AAN";
pub const TAG9: &str = "0N";
pub const TAG10: &str = "0O";
pub static MAP: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
let mut map = HashMap::new();
map.insert("TAG1", TAG1);
map.insert("TAG2", TAG2);
map.insert("TAG3", TAG3);
map.insert("TAG4", TAG4);
map.insert("TAG5", TAG5);
map.insert("TAG6", TAG6);
map.insert("TAG7", TAG7);
map.insert("TAG8", TAG8);
map.insert("TAG9", TAG9);
map.insert("TAG10", TAG10);
map
});
}
#[allow(dead_code)]
pub mod label_dex {
use once_cell::sync::Lazy;
use std::collections::HashMap;
pub const TAG1: &str = "0J";
pub const TAG2: &str = "0K";
pub const TAG3: &str = "X";
pub const TAG4: &str = "1AAF";
pub const TAG5: &str = "0L";
pub const TAG6: &str = "0M";
pub const TAG7: &str = "Y";
pub const TAG8: &str = "1AAN";
pub const TAG9: &str = "0N";
pub const TAG10: &str = "0O";
pub const STRB64_L0: &str = "4A";
pub const STRB64_L1: &str = "5A";
pub const STRB64_L2: &str = "6A";
pub const STRB64_BIG_L0: &str = "7AAA";
pub const STRB64_BIG_L1: &str = "8AAA";
pub const STRB64_BIG_L2: &str = "9AAA";
pub const LABEL1: &str = "V";
pub const LABEL2: &str = "W";
pub const BYTES_L0: &str = "4B";
pub const BYTES_L1: &str = "5B";
pub const BYTES_L2: &str = "6B";
pub const BYTES_BIG_L0: &str = "7AAB";
pub const BYTES_BIG_L1: &str = "8AAB";
pub const BYTES_BIG_L2: &str = "9AAB";
pub static MAP: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
let mut map = HashMap::new();
map.insert("TAG1", TAG1);
map.insert("TAG2", TAG2);
map.insert("TAG3", TAG3);
map.insert("TAG4", TAG4);
map.insert("TAG5", TAG5);
map.insert("TAG6", TAG6);
map.insert("TAG7", TAG7);
map.insert("TAG8", TAG8);
map.insert("TAG9", TAG9);
map.insert("TAG10", TAG10);
map.insert("STRB64_L0", STRB64_L0);
map.insert("STRB64_L1", STRB64_L1);
map.insert("STRB64_L2", STRB64_L2);
map.insert("STRB64_BIG_L0", STRB64_BIG_L0);
map.insert("STRB64_BIG_L1", STRB64_BIG_L1);
map.insert("STRB64_BIG_L2", STRB64_BIG_L2);
map.insert("LABEL1", LABEL1);
map.insert("LABEL2", LABEL2);
map.insert("BYTES_L0", BYTES_L0);
map.insert("BYTES_L1", BYTES_L1);
map.insert("BYTES_L2", BYTES_L2);
map.insert("BYTES_BIG_L0", BYTES_BIG_L0);
map.insert("BYTES_BIG_L1", BYTES_BIG_L1);
map.insert("BYTES_BIG_L2", BYTES_BIG_L2);
map
});
}
#[allow(dead_code)]
pub mod pre_dex {
use once_cell::sync::Lazy;
use std::collections::HashMap;
pub const ED25519N: &str = "B";
pub const ED25519: &str = "D";
pub const BLAKE3_256: &str = "E";
pub const BLAKE2B_256: &str = "F";
pub const BLAKE2S_256: &str = "G";
pub const SHA3_256: &str = "H";
pub const SHA2_256: &str = "I";
pub const BLAKE3_512: &str = "0D";
pub const BLAKE2B_512: &str = "0E";
pub const SHA3_512: &str = "0F";
pub const SHA2_512: &str = "0G";
pub const ECDSA_256K1N: &str = "1AAA";
pub const ECDSA_256K1: &str = "1AAB";
pub const ED448N: &str = "1AAC";
pub const ED448: &str = "1AAD";
pub const ED448_SIG: &str = "1AAE";
pub const ECDSA_256R1N: &str = "1AAI";
pub const ECDSA_256R1: &str = "1AAJ";
pub static MAP: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
let mut map = HashMap::new();
map.insert("ED25519N", ED25519N);
map.insert("ED25519", ED25519);
map.insert("BLAKE3_256", BLAKE3_256);
map.insert("BLAKE2B_256", BLAKE2B_256);
map.insert("BLAKE2S_256", BLAKE2S_256);
map.insert("SHA3_256", SHA3_256);
map.insert("SHA2_256", SHA2_256);
map.insert("BLAKE3_512", BLAKE3_512);
map.insert("BLAKE2B_512", BLAKE2B_512);
map.insert("SHA3_512", SHA3_512);
map.insert("SHA2_512", SHA2_512);
map.insert("ECDSA_256K1N", ECDSA_256K1N);
map.insert("ECDSA_256K1", ECDSA_256K1);
map.insert("ED448N", ED448N);
map.insert("ED448", ED448);
map.insert("ED448_SIG", ED448_SIG);
map.insert("ECDSA_256R1N", ECDSA_256R1N);
map.insert("ECDSA_256R1", ECDSA_256R1);
map
});
pub static TUPLE: [&'static str; 18] = [
ED25519N,
ED25519,
BLAKE3_256,
BLAKE2B_256,
BLAKE2S_256,
SHA3_256,
SHA2_256,
BLAKE3_512,
BLAKE2B_512,
SHA3_512,
SHA2_512,
ECDSA_256K1N,
ECDSA_256K1,
ED448N,
ED448,
ED448_SIG,
ECDSA_256R1N,
ECDSA_256R1,
];
}
#[allow(dead_code)]
pub mod non_trans_dex {
use once_cell::sync::Lazy;
use std::collections::HashMap;
pub const ED25519N: &str = "B";
pub const ECDSA_256K1N: &str = "1AAA";
pub const ED448N: &str = "1AAC";
pub const ECDSA_256R1N: &str = "1AAI";
pub static MAP: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
let mut map = HashMap::new();
map.insert("ED25519N", ED25519N);
map.insert("ECDSA_256K1N", ECDSA_256K1N);
map.insert("ED448N", ED448N);
map.insert("ECDSA_256R1N", ECDSA_256R1N);
map
});
pub static TUPLE: [&'static str; 4] = [ED25519N, ECDSA_256K1N, ED448N, ECDSA_256R1N];
}
#[allow(dead_code)]
pub mod pre_non_dig_dex {
use once_cell::sync::Lazy;
use std::collections::HashMap;
pub const ED25519N: &str = "B";
pub const ED25519: &str = "D";
pub const ECDSA_256K1N: &str = "1AAA";
pub const ECDSA_256K1: &str = "1AAB";
pub const ED448N: &str = "1AAC";
pub const ED448: &str = "1AAD";
pub const ECDSA_256R1N: &str = "1AAI";
pub const ECDSA_256R1: &str = "1AAJ";
pub static MAP: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
let mut map = HashMap::new();
map.insert("ED25519N", ED25519N);
map.insert("ED25519", ED25519);
map.insert("ECDSA_256K1N", ECDSA_256K1N);
map.insert("ECDSA_256K1", ECDSA_256K1);
map.insert("ED448N", ED448N);
map.insert("ED448", ED448);
map.insert("ECDSA_256R1N", ECDSA_256R1N);
map.insert("ECDSA_256R1", ECDSA_256R1);
map
});
}
#[derive(Clone, Copy, Debug)]
pub struct Sizage {
pub hs: u32, pub ss: u32, pub xs: u32, pub fs: Option<u32>, pub ls: u32, }
pub fn get_sizes() -> HashMap<&'static str, Sizage> {
let mut sizes = HashMap::new();
sizes.insert(
"A",
Sizage {
hs: 1,
ss: 0,
xs: 0,
fs: Some(44),
ls: 0,
},
); sizes.insert(
"B",
Sizage {
hs: 1,
ss: 0,
xs: 0,
fs: Some(44),
ls: 0,
},
); sizes.insert(
"C",
Sizage {
hs: 1,
ss: 0,
xs: 0,
fs: Some(44),
ls: 0,
},
); sizes.insert(
"D",
Sizage {
hs: 1,
ss: 0,
xs: 0,
fs: Some(44),
ls: 0,
},
); sizes.insert(
"E",
Sizage {
hs: 1,
ss: 0,
xs: 0,
fs: Some(44),
ls: 0,
},
); sizes.insert(
"F",
Sizage {
hs: 1,
ss: 0,
xs: 0,
fs: Some(44),
ls: 0,
},
); sizes.insert(
"G",
Sizage {
hs: 1,
ss: 0,
xs: 0,
fs: Some(44),
ls: 0,
},
); sizes.insert(
"H",
Sizage {
hs: 1,
ss: 0,
xs: 0,
fs: Some(44),
ls: 0,
},
); sizes.insert(
"I",
Sizage {
hs: 1,
ss: 0,
xs: 0,
fs: Some(44),
ls: 0,
},
); sizes.insert(
"J",
Sizage {
hs: 1,
ss: 0,
xs: 0,
fs: Some(44),
ls: 0,
},
); sizes.insert(
"K",
Sizage {
hs: 1,
ss: 0,
xs: 0,
fs: Some(76),
ls: 0,
},
); sizes.insert(
"L",
Sizage {
hs: 1,
ss: 0,
xs: 0,
fs: Some(76),
ls: 0,
},
); sizes.insert(
"M",
Sizage {
hs: 1,
ss: 0,
xs: 0,
fs: Some(4),
ls: 0,
},
); sizes.insert(
"N",
Sizage {
hs: 1,
ss: 0,
xs: 0,
fs: Some(12),
ls: 0,
},
); sizes.insert(
"O",
Sizage {
hs: 1,
ss: 0,
xs: 0,
fs: Some(44),
ls: 0,
},
); sizes.insert(
"P",
Sizage {
hs: 1,
ss: 0,
xs: 0,
fs: Some(124),
ls: 0,
},
); sizes.insert(
"Q",
Sizage {
hs: 1,
ss: 0,
xs: 0,
fs: Some(44),
ls: 0,
},
); sizes.insert(
"R",
Sizage {
hs: 1,
ss: 0,
xs: 0,
fs: Some(8),
ls: 0,
},
); sizes.insert(
"S",
Sizage {
hs: 1,
ss: 0,
xs: 0,
fs: Some(16),
ls: 0,
},
); sizes.insert(
"U",
Sizage {
hs: 1,
ss: 0,
xs: 0,
fs: Some(20),
ls: 0,
},
); sizes.insert(
"V",
Sizage {
hs: 1,
ss: 0,
xs: 0,
fs: Some(24),
ls: 0,
},
); sizes.insert(
"W",
Sizage {
hs: 1,
ss: 0,
xs: 0,
fs: Some(4),
ls: 0,
},
); sizes.insert(
"X",
Sizage {
hs: 1,
ss: 3,
xs: 0,
fs: Some(4),
ls: 0,
},
); sizes.insert(
"Y",
Sizage {
hs: 1,
ss: 7,
xs: 0,
fs: Some(4),
ls: 0,
},
); sizes.insert(
"Z",
Sizage {
hs: 1,
ss: 0,
xs: 0,
fs: Some(8),
ls: 0,
},
); sizes.insert(
"0A",
Sizage {
hs: 2,
ss: 0,
xs: 0,
fs: Some(24),
ls: 0,
},
);
sizes.insert(
"0B",
Sizage {
hs: 2,
ss: 0,
xs: 0,
fs: Some(88),
ls: 0,
},
);
sizes.insert(
"0C",
Sizage {
hs: 2,
ss: 0,
xs: 0,
fs: Some(88),
ls: 0,
},
);
sizes.insert(
"0D",
Sizage {
hs: 2,
ss: 0,
xs: 0,
fs: Some(88),
ls: 0,
},
);
sizes.insert(
"0E",
Sizage {
hs: 2,
ss: 0,
xs: 0,
fs: Some(88),
ls: 0,
},
);
sizes.insert(
"0F",
Sizage {
hs: 2,
ss: 0,
xs: 0,
fs: Some(88),
ls: 0,
},
);
sizes.insert(
"0G",
Sizage {
hs: 2,
ss: 0,
xs: 0,
fs: Some(88),
ls: 0,
},
);
sizes.insert(
"0H",
Sizage {
hs: 2,
ss: 0,
xs: 0,
fs: Some(8),
ls: 0,
},
);
sizes.insert(
"0I",
Sizage {
hs: 2,
ss: 0,
xs: 0,
fs: Some(88),
ls: 0,
},
);
sizes.insert(
"0J",
Sizage {
hs: 2,
ss: 2,
xs: 1,
fs: Some(4),
ls: 0,
},
);
sizes.insert(
"0K",
Sizage {
hs: 2,
ss: 2,
xs: 0,
fs: Some(4),
ls: 0,
},
);
sizes.insert(
"0L",
Sizage {
hs: 2,
ss: 6,
xs: 1,
fs: Some(8),
ls: 0,
},
);
sizes.insert(
"0M",
Sizage {
hs: 2,
ss: 6,
xs: 0,
fs: Some(8),
ls: 0,
},
);
sizes.insert(
"0N",
Sizage {
hs: 2,
ss: 10,
xs: 1,
fs: Some(12),
ls: 0,
},
);
sizes.insert(
"0O",
Sizage {
hs: 2,
ss: 10,
xs: 0,
fs: Some(12),
ls: 0,
},
);
sizes.insert(
"0P",
Sizage {
hs: 2,
ss: 22,
xs: 0,
fs: Some(32),
ls: 0,
},
);
sizes.insert(
"0Q",
Sizage {
hs: 2,
ss: 22,
xs: 0,
fs: Some(28),
ls: 0,
},
);
sizes.insert(
"0R",
Sizage {
hs: 2,
ss: 22,
xs: 0,
fs: Some(76),
ls: 0,
},
);
sizes.insert(
"0S",
Sizage {
hs: 2,
ss: 22,
xs: 0,
fs: Some(72),
ls: 0,
},
);
sizes.insert(
"1AAA",
Sizage {
hs: 4,
ss: 0,
xs: 0,
fs: Some(48),
ls: 0,
},
);
sizes.insert(
"1AAB",
Sizage {
hs: 4,
ss: 0,
xs: 0,
fs: Some(48),
ls: 0,
},
);
sizes.insert(
"1AAC",
Sizage {
hs: 4,
ss: 0,
xs: 0,
fs: Some(80),
ls: 0,
},
);
sizes.insert(
"1AAD",
Sizage {
hs: 4,
ss: 0,
xs: 0,
fs: Some(80),
ls: 0,
},
);
sizes.insert(
"1AAE",
Sizage {
hs: 4,
ss: 0,
xs: 0,
fs: Some(156),
ls: 0,
},
);
sizes.insert(
"1AAF",
Sizage {
hs: 4,
ss: 4,
xs: 0,
fs: Some(8),
ls: 0,
},
);
sizes.insert(
"1AAG",
Sizage {
hs: 4,
ss: 0,
xs: 0,
fs: Some(36),
ls: 0,
},
);
sizes.insert(
"1AAH",
Sizage {
hs: 4,
ss: 0,
xs: 0,
fs: Some(100),
ls: 0,
},
);
sizes.insert(
"1AAI",
Sizage {
hs: 4,
ss: 0,
xs: 0,
fs: Some(48),
ls: 0,
},
);
sizes.insert(
"1AAJ",
Sizage {
hs: 4,
ss: 0,
xs: 0,
fs: Some(48),
ls: 0,
},
);
sizes.insert(
"1AAK",
Sizage {
hs: 4,
ss: 0,
xs: 0,
fs: Some(4),
ls: 0,
},
);
sizes.insert(
"1AAL",
Sizage {
hs: 4,
ss: 0,
xs: 0,
fs: Some(4),
ls: 0,
},
);
sizes.insert(
"1AAM",
Sizage {
hs: 4,
ss: 0,
xs: 0,
fs: Some(4),
ls: 0,
},
);
sizes.insert(
"1AAN",
Sizage {
hs: 4,
ss: 8,
xs: 0,
fs: Some(12),
ls: 0,
},
);
sizes.insert(
"1__-",
Sizage {
hs: 4,
ss: 2,
xs: 0,
fs: Some(12),
ls: 0,
},
);
sizes.insert(
"1___",
Sizage {
hs: 4,
ss: 0,
xs: 0,
fs: Some(8),
ls: 0,
},
);
sizes.insert(
"2__-",
Sizage {
hs: 4,
ss: 2,
xs: 1,
fs: Some(12),
ls: 1,
},
);
sizes.insert(
"2___",
Sizage {
hs: 4,
ss: 0,
xs: 0,
fs: Some(8),
ls: 1,
},
);
sizes.insert(
"3__-",
Sizage {
hs: 4,
ss: 2,
xs: 0,
fs: Some(12),
ls: 2,
},
);
sizes.insert(
"3___",
Sizage {
hs: 4,
ss: 0,
xs: 0,
fs: Some(8),
ls: 2,
},
);
sizes.insert(
"4A",
Sizage {
hs: 2,
ss: 2,
xs: 0,
fs: None,
ls: 0,
},
);
sizes.insert(
"5A",
Sizage {
hs: 2,
ss: 2,
xs: 0,
fs: None,
ls: 1,
},
);
sizes.insert(
"6A",
Sizage {
hs: 2,
ss: 2,
xs: 0,
fs: None,
ls: 2,
},
);
sizes.insert(
"7AAA",
Sizage {
hs: 4,
ss: 4,
xs: 0,
fs: None,
ls: 0,
},
);
sizes.insert(
"8AAA",
Sizage {
hs: 4,
ss: 4,
xs: 0,
fs: None,
ls: 1,
},
);
sizes.insert(
"9AAA",
Sizage {
hs: 4,
ss: 4,
xs: 0,
fs: None,
ls: 2,
},
);
sizes.insert(
"4B",
Sizage {
hs: 2,
ss: 2,
xs: 0,
fs: None,
ls: 0,
},
);
sizes.insert(
"5B",
Sizage {
hs: 2,
ss: 2,
xs: 0,
fs: None,
ls: 1,
},
);
sizes.insert(
"6B",
Sizage {
hs: 2,
ss: 2,
xs: 0,
fs: None,
ls: 2,
},
);
sizes.insert(
"7AAB",
Sizage {
hs: 4,
ss: 4,
xs: 0,
fs: None,
ls: 0,
},
);
sizes.insert(
"8AAB",
Sizage {
hs: 4,
ss: 4,
xs: 0,
fs: None,
ls: 1,
},
);
sizes.insert(
"9AAB",
Sizage {
hs: 4,
ss: 4,
xs: 0,
fs: None,
ls: 2,
},
);
sizes.insert(
"4C",
Sizage {
hs: 2,
ss: 2,
xs: 0,
fs: None,
ls: 0,
},
);
sizes.insert(
"5C",
Sizage {
hs: 2,
ss: 2,
xs: 0,
fs: None,
ls: 1,
},
);
sizes.insert(
"6C",
Sizage {
hs: 2,
ss: 2,
xs: 0,
fs: None,
ls: 2,
},
);
sizes.insert(
"7AAC",
Sizage {
hs: 4,
ss: 4,
xs: 0,
fs: None,
ls: 0,
},
);
sizes.insert(
"8AAC",
Sizage {
hs: 4,
ss: 4,
xs: 0,
fs: None,
ls: 1,
},
);
sizes.insert(
"9AAC",
Sizage {
hs: 4,
ss: 4,
xs: 0,
fs: None,
ls: 2,
},
);
sizes.insert(
"4D",
Sizage {
hs: 2,
ss: 2,
xs: 0,
fs: None,
ls: 0,
},
);
sizes.insert(
"5D",
Sizage {
hs: 2,
ss: 2,
xs: 0,
fs: None,
ls: 1,
},
);
sizes.insert(
"6D",
Sizage {
hs: 2,
ss: 2,
xs: 0,
fs: None,
ls: 2,
},
);
sizes.insert(
"7AAD",
Sizage {
hs: 4,
ss: 4,
xs: 0,
fs: None,
ls: 0,
},
);
sizes.insert(
"8AAD",
Sizage {
hs: 4,
ss: 4,
xs: 0,
fs: None,
ls: 1,
},
);
sizes.insert(
"9AAD",
Sizage {
hs: 4,
ss: 4,
xs: 0,
fs: None,
ls: 2,
},
);
sizes.insert(
"4E",
Sizage {
hs: 2,
ss: 2,
xs: 0,
fs: None,
ls: 0,
},
);
sizes.insert(
"5E",
Sizage {
hs: 2,
ss: 2,
xs: 0,
fs: None,
ls: 1,
},
);
sizes.insert(
"6E",
Sizage {
hs: 2,
ss: 2,
xs: 0,
fs: None,
ls: 2,
},
);
sizes.insert(
"7AAE",
Sizage {
hs: 4,
ss: 4,
xs: 0,
fs: None,
ls: 0,
},
);
sizes.insert(
"8AAE",
Sizage {
hs: 4,
ss: 4,
xs: 0,
fs: None,
ls: 1,
},
);
sizes.insert(
"9AAE",
Sizage {
hs: 4,
ss: 4,
xs: 0,
fs: None,
ls: 2,
},
);
sizes
}
pub fn hards() -> HashMap<u8, i32> {
let mut map: HashMap<u8, i32> = (b'A'..=b'Z').map(|c| (c, 1)).collect();
map.extend((b'a'..=b'z').map(|c| (c, 1)));
map.extend([
(b'0', 2),
(b'1', 4),
(b'2', 4),
(b'3', 4),
(b'4', 2),
(b'5', 2),
(b'6', 2),
(b'7', 4),
(b'8', 4),
(b'9', 4),
]);
map
}
fn code_b64_to_b2(c: u8) -> u8 {
match c {
b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'+' | b'/' => {
let val = match c {
b'A'..=b'Z' => c - b'A',
b'a'..=b'z' => c - b'a' + 26,
b'0'..=b'9' => c - b'0' + 52,
b'+' => 62,
b'/' => 63,
_ => unreachable!(),
};
val
}
_ => b'0',
}
}
pub fn get_bards() -> HashMap<u8, i32> {
let hards = hards();
let mut bards: HashMap<u8, i32> = hards
.iter()
.map(|(&c, &hs)| (code_b64_to_b2(c), hs))
.collect();
bards.insert(0xd0, 2);
bards
}
pub trait Matter: Any {
fn code(&self) -> &str;
fn raw(&self) -> &[u8];
fn qb64(&self) -> String;
fn qb64b(&self) -> Vec<u8>;
fn qb2(&self) -> Vec<u8>;
fn soft(&self) -> &str;
fn full_size(&self) -> usize;
fn size(&self) -> usize;
fn is_transferable(&self) -> bool;
fn is_digestive(&self) -> bool;
fn is_prefixive(&self) -> bool;
fn is_special(&self) -> bool;
fn as_any(&self) -> &dyn Any;
}
pub trait Parsable: Sized {
fn from_qb64b(data: &mut Vec<u8>, strip: Option<bool>) -> Result<Self, MatterError>;
fn from_qb2(data: &mut Vec<u8>, strip: Option<bool>) -> Result<Self, MatterError>;
}
#[derive(Debug, Clone)]
pub struct BaseMatter {
code: String,
soft: String,
raw: Vec<u8>,
}
impl TryFrom<Vec<u8>> for BaseMatter {
type Error = MatterError;
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
BaseMatter::from_qb64b(&mut value.clone(), None)
}
}
impl BaseMatter {
pub fn new(
raw: Option<&[u8]>,
code: Option<&str>,
soft: Option<&str>,
rize: Option<usize>,
) -> Result<Self, MatterError> {
let code = code.ok_or_else(|| {
MatterError::EmptyMaterial(
"Improper initialization need either (raw not None and code) or \
(code and soft) or qb64b or qb64 or qb2."
.to_string(),
)
})?;
let raw =
raw.ok_or_else(|| MatterError::TypeError(String::from("Raw data must be provided")))?;
let sizes = get_sizes();
if !sizes.contains_key(code) {
return Err(MatterError::InvalidCode(format!(
"Unsupported code={}",
code
)));
}
let size = sizes[code].clone(); let (_, ss, xs, fs, _) = (size.hs, size.ss, size.xs, size.fs, size.ls);
let hs;
let rize_val;
let mut soft_val = String::new();
let mut code_val = code.to_string();
if fs.is_none() {
rize_val = match rize {
Some(r) => r,
None => raw.len(),
};
let ls = ((3 - (rize_val % 3)) % 3) as u32;
let size = (rize_val + ls as usize) / 3;
if small_vrz_dex::TUPLE.contains(&&code[0..1]) {
if size <= (64_usize.pow(2) - 1) {
hs = 2;
let s = small_vrz_dex::TUPLE[ls as usize];
code_val = format!("{}{}", s, &code[1..hs as usize]);
soft_val = int_to_b64(size as u32, 2);
} else if size <= (64_usize.pow(4) - 1) {
hs = 4;
let s = large_vrz_dex::TUPLE[ls as usize];
code_val = format!("{}{}{}", s, "A".repeat(hs as usize - 2), &code[1..2]);
soft_val = int_to_b64(size as u32, 4);
} else {
return Err(MatterError::InvalidVarRawSize(format!(
"Unsupported raw size for code={}",
code
)));
}
} else if large_vrz_dex::TUPLE.contains(&&code[0..1]) {
if size <= (64_usize.pow(4) - 1) {
hs = 4;
let s = large_vrz_dex::TUPLE[ls as usize];
code_val = format!("{}{}", s, &code[1..hs as usize]);
soft_val = int_to_b64(size as u32, 4);
} else {
return Err(MatterError::InvalidVarRawSize(format!(
"Unsupported raw size for large code={}. {} <= {}",
code,
size,
64_usize.pow(4) - 1
)));
}
} else {
return Err(MatterError::InvalidVarRawSize(format!(
"Unsupported variable raw size code={}",
code
)));
}
} else {
rize_val = raw_size(&code_val)?;
if ss > 0 {
let soft_str = soft.unwrap_or("");
let trimmed_soft =
&soft_str[..std::cmp::min(soft_str.len(), ss as usize - xs as usize)];
if trimmed_soft.len() != ss as usize - xs as usize {
return Err(MatterError::SoftMaterial(format!(
"Not enough chars in soft={} with ss={} xs={} for code={}",
soft_str, ss, xs, code
)));
}
if !trimmed_soft
.chars()
.all(|c| c.is_ascii_alphanumeric() || c == '+' || c == '/' || c == '=')
{
return Err(MatterError::InvalidSoft(format!(
"Non Base64 chars in soft={}",
trimmed_soft
)));
}
soft_val = trimmed_soft.to_string();
}
}
if raw.len() < rize_val {
return Err(MatterError::RawMaterial(format!(
"Not enough raw bytes for code={} expected rize={} got {}",
code,
rize_val,
raw.len()
)));
}
let raw_val = Vec::from(&raw[..rize_val]);
Ok(BaseMatter {
code: code_val,
soft: soft_val,
raw: raw_val,
})
}
pub fn from_raw(raw: Option<&[u8]>) -> Result<Self, MatterError> {
BaseMatter::new(raw, Some(mtr_dex::ED25519N), None, None)
}
pub fn from_qb64(qb64: &str) -> Result<Self, MatterError> {
if qb64.is_empty() {
return Err(MatterError::ShortageError(
"Empty qb64, invalid".to_string(),
));
}
let first = &qb64[0..1];
let hards = hards();
let sizes = get_sizes();
if !hards.contains_key(&first.bytes().next().unwrap_or(b'A')) {
return if first == "-" {
Err(MatterError::UnexpectedCountCodeError(
"Unexpected count code start while extracting Matter.".to_string(),
))
} else if first == "_" {
Err(MatterError::UnexpectedOpCodeError(
"Unexpected op code start while extracting Matter.".to_string(),
))
} else {
Err(MatterError::UnexpectedCodeError(format!(
"Unsupported code start char={}",
first
)))
};
}
let hs = *hards.get(&first.bytes().next().unwrap_or(b'A')).unwrap();
if qb64.len() < hs as usize {
return Err(MatterError::ShortageError(format!(
"Need {} more characters.",
hs - qb64.len() as i32
)));
}
let hard = &qb64[0..hs as usize];
if !sizes.contains_key(hard) {
return Err(MatterError::UnexpectedCodeError(format!(
"Unsupported code ={}",
hard
)));
}
let size = *sizes.get(hard).unwrap();
let cs = hs as u32 + size.ss;
let soft = if size.ss > 0 {
&qb64[hs as usize..(hs as u32 + size.ss) as usize]
} else {
""
};
let xtra = if size.xs > 0 {
&soft[0..size.xs as usize]
} else {
""
};
let soft_without_xtra = if size.xs > 0 {
&soft[size.xs as usize..]
} else {
soft
};
if size.xs > 0 && xtra != &"A".repeat(size.xs as usize) {
return Err(MatterError::UnexpectedCodeError(format!(
"Invalid prepad xtra ={}",
xtra
)));
}
let fs = if size.fs.is_none() {
(b64_to_int(soft_without_xtra) * 4) + cs
} else {
size.fs.unwrap()
};
if qb64.len() < fs as usize {
return Err(MatterError::ShortageError(format!(
"Need {} more chars.",
fs - qb64.len() as u32
)));
}
let qb64 = &qb64[0..fs as usize];
let ps = cs % 4; let base = "A".repeat(ps as usize) + &qb64[cs as usize..]; let paw = decode_b64(&base)?;
let midpad = &paw[0..(ps + size.ls) as usize];
let pi = u32::from_be_bytes([
if midpad.len() > 0 { midpad[0] } else { 0 },
if midpad.len() > 1 { midpad[1] } else { 0 },
if midpad.len() > 2 { midpad[2] } else { 0 },
if midpad.len() > 3 { midpad[3] } else { 0 },
]);
if pi != 0 {
return Err(MatterError::ConversionError(format!(
"Nonzero midpad bytes=0x{:0width$x}.",
pi,
width = (ps + size.ls) as usize * 2
)));
}
let raw = paw[(ps + size.ls) as usize..].to_vec();
let expected_len = ((qb64.len() - cs as usize) * 3 / 4) - size.ls as usize;
if raw.len() != expected_len {
return Err(MatterError::ConversionError(format!(
"Improperly qualified material = {}",
qb64
)));
}
Ok(Self {
code: hard.to_string(),
soft: soft.to_string(),
raw,
})
}
pub fn bexfil(qb2: &[u8]) -> Result<Self, MatterError> {
if qb2.is_empty() {
return Err(MatterError::Shortage(
"Empty material, Need more bytes.".into(),
));
}
let first = nab_sextets(qb2, 1)?;
let bards = get_bards();
let hs = match bards.get(&first[0]) {
Some(hs) => *hs,
None => {
return if first[0] == 0xf8 {
Err(MatterError::UnexpectedCountCode(
"Unexpected count code start while extracting Matter.".into(),
))
} else if first[0] == 0xfc {
Err(MatterError::UnexpectedOpCode(
"Unexpected op code start while extracting Matter.".into(),
))
} else {
Err(MatterError::UnexpectedCode(format!(
"Unsupported code start sextet={:02x?}.",
first
)))
};
}
};
let bhs = ((hs as f64) * 3.0 / 4.0).ceil() as usize;
if qb2.len() < bhs {
return Err(MatterError::Shortage(format!(
"Need {} more bytes.",
bhs - qb2.len()
)));
}
let hard = code_b2_to_b64(qb2, hs as usize)?;
let sizes = get_sizes();
let size = sizes[hard.as_str()].clone();
let (hs, ss, xs, fs, ls) = (size.hs, size.ss, size.xs, size.fs, size.ls);
let cs = hs + ss;
let bcs = ((cs as f64) * 3.0 / 4.0).ceil() as usize;
if qb2.len() < bcs {
return Err(MatterError::Shortage(format!(
"Need {} more bytes.",
bcs - qb2.len()
)));
}
let both = code_b2_to_b64(qb2, cs as usize)?;
let mut soft = both[hs as usize..].to_string();
let xtra = if xs > 0 {
soft[..xs as usize].to_string()
} else {
String::new()
};
if xs > 0 {
soft = soft[xs as usize..].to_string();
}
if xs > 0 && xtra != PAD.to_string().repeat(xs as usize) {
return Err(MatterError::UnexpectedCode(format!(
"Invalid prepad xtra ={}",
xtra
)));
}
let calculated_fs = if fs.unwrap_or(0) == 0 {
if qb2.len() < bcs {
return Err(MatterError::Shortage(format!(
"Need {} more bytes.",
bcs - qb2.len()
)));
}
let soft_int = b64_to_int(&soft);
(soft_int * 4) + cs
} else {
fs.unwrap_or(0)
};
let bfs = ((calculated_fs as f64) * 3.0 / 4.0).ceil() as usize;
if qb2.len() < bfs {
return Err(MatterError::Shortage(format!(
"Need {} more bytes.",
bfs - qb2.len()
)));
}
let qb2 = &qb2[..bfs];
let ps = cs % 4; let pbs = 2 * ps;
if pbs > 0 {
let pi = qb2[bcs - 1];
let mask = (1 << pbs) - 1; if pi & mask != 0 {
return Err(MatterError::Conversion(format!(
"Nonzero code mid pad bits=0b{:0width$b}.",
pi & mask,
width = pbs as usize
)));
}
}
if ls > 0 {
let mut lead_bytes = vec![0u8; ls as usize];
lead_bytes.copy_from_slice(&qb2[bcs..bcs + ls as usize]);
let mut is_zero = true;
for byte in &lead_bytes {
if *byte != 0 {
is_zero = false;
break;
}
}
if !is_zero {
return Err(MatterError::Conversion(format!(
"Nonzero lead midpad bytes={:0width$x?}.",
lead_bytes,
width = (ls * 2) as usize
)));
}
}
let raw = if (bcs + ls as usize) < qb2.len() {
qb2[bcs + ls as usize..].to_vec()
} else {
Vec::new()
};
if raw.len() != (qb2.len() - bcs - ls as usize) {
return Err(MatterError::Conversion(format!(
"Improperly qualified material = {:?}",
qb2
)));
}
Ok(Self {
code: hard.to_string(),
soft,
raw,
})
}
fn from_soft_and_code(soft: &str, code: &str) -> Result<Self, MatterError> {
let sizes = get_sizes();
let size = sizes[code].clone();
let (hs, ss, xs, fs, ls) = (size.hs, size.ss, size.xs, size.fs.unwrap_or(0), size.ls);
if fs == 0 {
return Err(MatterError::InvalidSoftError(format!(
"Unsupported variable sized code={} with fs={} for special soft={}.",
code, fs, soft
)));
}
if !(ss > 0) || (fs == hs + ss && ls != 0) {
return Err(MatterError::InvalidSoftError(format!(
"Invalid soft size={} or lead={} or code={} fs={} when special soft.",
ss, ls, code, fs
)));
}
let trimmed_soft = if soft.len() >= (ss - xs) as usize {
&soft[0..(ss - xs) as usize]
} else {
return Err(MatterError::SoftMaterialError(format!(
"Not enough chars in soft={} with ss={} xs={} for code={}.",
soft, ss, xs, code
)));
};
if !is_base64(trimmed_soft) {
return Err(MatterError::InvalidSoftError(format!(
"Non Base64 chars in soft={}.",
trimmed_soft
)));
}
Ok(BaseMatter {
code: code.to_string(),
soft: trimmed_soft.to_string(),
raw: Vec::new(), })
}
fn infil(&self) -> Result<String, MatterError> {
let code = &self.code; let both = format!("{}{}", self.code, self.soft); let raw = &self.raw; let rs = raw.len();
let sizes = get_sizes();
let size = sizes[code.as_str()];
let (hs, ss, xs, fs, ls) = (size.hs, size.ss, size.xs, size.fs, size.ls);
let cs = hs + ss;
if cs != both.len() as u32 {
return Err(MatterError::InvalidCodeSize(format!(
"Invalid full code={} for sizes hs={} and ss={}.",
both, hs, ss
)));
}
let full = if fs.unwrap_or(0) == 0 {
if (ls + rs as u32) % 3 != 0 || cs % 4 != 0 {
return Err(MatterError::InvalidCodeSize(format!(
"Invalid full code both={} with variable raw size={} given cs={}, hs={}, ss={}, fs={}, and ls={}.",
both, rs, cs, hs, ss, fs.unwrap_or(0), ls
)));
}
let mut padded_raw = vec![0; ls as usize];
padded_raw.extend_from_slice(raw);
let encoded = encode_b64(&padded_raw);
format!("{}{}", both, encoded)
} else {
let ps = (3 - ((rs + ls as usize) % 3)) % 3;
if ps != (cs % 4) as usize {
return Err(MatterError::InvalidCodeSize(format!(
"Invalid full code both={} with fixed raw size={} given cs={}, hs={}, ss={}, fs={}, and ls={}.",
both, rs, cs, hs, ss, fs.unwrap_or(0), ls
)));
}
let mut padded_raw = vec![0; ps + ls as usize];
padded_raw.extend_from_slice(raw);
let encoded = encode_b64(&padded_raw);
format!("{}{}", both, &encoded[ps..])
};
if (full.len() % 4 != 0) || (fs.unwrap_or(0) > 0 && full.len() != fs.unwrap_or(0) as usize)
{
return Err(MatterError::InvalidCodeSize(format!(
"Invalid full size given code both={} with raw size={}, cs={}, hs={}, ss={}, xs={}, fs={}, and ls={}.",
both, rs, cs, hs, ss, xs, fs.unwrap_or(0), ls
)));
}
Ok(full)
}
pub fn binfil(&self) -> Result<Vec<u8>, MatterError> {
let code = &self.code; let both = format!("{}{}", &self.code, &self.soft); let raw = &self.raw;
let sizes = get_sizes();
let size = sizes[code.as_str()];
let (hs, ss, fs, ls) = (size.hs, size.ss, size.fs, size.ls);
let cs = hs + ss;
let n = ((cs * 3) as f64 / 4.0).ceil() as usize;
let b64_int = b64_to_int(&both);
let shift = 2 * (cs % 4);
let b64_shifted = b64_int << shift;
let bcode = b64_shifted.to_be_bytes()[b64_shifted.to_be_bytes().len() - n..].to_vec();
let mut full = Vec::new();
full.extend_from_slice(&bcode);
full.extend_from_slice(&vec![0; ls as usize]);
full.extend_from_slice(raw);
let bfs = full.len();
let calculated_fs = if fs.unwrap_or(0) == 0 {
hs + ss + ((raw.len() as u32 + ls) * 4) / 3
} else {
fs.unwrap()
};
if bfs % 3 != 0 || ((bfs * 4) / 3) != calculated_fs as usize {
return Err(MatterError::InvalidCodeSize(format!(
"Invalid full code={} for raw size={}.",
both,
raw.len()
)));
}
Ok(full)
}
}
impl Parsable for BaseMatter {
fn from_qb64b(data: &mut Vec<u8>, strip: Option<bool>) -> Result<Self, MatterError> {
let qb64b = data.as_slice();
let qb64 = str::from_utf8(qb64b).ok();
let mtr = BaseMatter::from_qb64(qb64.unwrap_or(""))?;
if strip.unwrap_or(false) {
let fs = mtr.full_size();
data.drain(..fs);
}
Ok(mtr)
}
fn from_qb2(data: &mut Vec<u8>, strip: Option<bool>) -> Result<Self, MatterError> {
let qb2 = data.as_slice();
let mtr = BaseMatter::bexfil(qb2)?;
if strip.unwrap_or(false) {
let fs = mtr.full_size();
data.drain(..fs);
}
Ok(mtr)
}
}
fn decode_b64(data: &str) -> Result<Vec<u8>, MatterError> {
general_purpose::URL_SAFE_NO_PAD
.decode(data)
.map_err(|_| MatterError::InvalidBase64)
}
fn encode_b64(data: &[u8]) -> String {
general_purpose::URL_SAFE_NO_PAD.encode(data)
}
pub fn b64_to_int(b64_str: &str) -> u32 {
let mut result = 0u32;
for c in b64_str.chars() {
result = result * 64
+ match c {
'A'..='Z' => c as u32 - 'A' as u32,
'a'..='z' => c as u32 - 'a' as u32 + 26,
'0'..='9' => c as u32 - '0' as u32 + 52,
'+' | '-' => 62,
'/' | '_' => 63,
_ => 0,
};
}
result
}
pub fn int_to_b64(num: u32, length: usize) -> String {
const B64_CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
let mut result = String::with_capacity(length);
let mut n = num;
for _ in 0..length {
let idx = (n % 64) as usize;
result.insert(0, B64_CHARS[idx] as char);
n /= 64;
}
result
}
pub fn raw_size(code: &str) -> Result<usize, MatterError> {
let sizes = get_sizes();
let size = sizes[code].clone();
let cs = size.hs + size.ss;
let fs = size
.fs
.ok_or_else(|| MatterError::InvalidCode(code.to_string()))?;
Ok((((fs - cs) * 3 / 4) - size.ls) as usize)
}
pub fn nab_sextets(b: &[u8], l: usize) -> Result<Vec<u8>, MatterError> {
let n = (l * 3 + 3) / 4;
if n > b.len() {
return Err(MatterError::ShortageError(format!(
"Not enough bytes in {:?} to nab {} sextets.",
b, l
)));
}
let bytes = &b[..n];
let mut i = BigUint::from_bytes_be(bytes);
let p = 2 * (l % 4);
if p > 0 {
i >>= p;
i <<= p;
}
let mut result = i.to_bytes_be();
if result.len() < n {
let padding = vec![0; n - result.len()];
let mut padded_result = padding;
padded_result.extend(result);
result = padded_result;
}
Ok(result)
}
pub fn code_b2_to_b64(b: &[u8], l: usize) -> Result<String, MatterError> {
let n = (l * 3 + 3) / 4;
if n > b.len() {
return Err(MatterError::ShortageError(format!(
"Not enough bytes in {:?} to nab {} sextets.",
b, l
)));
}
let bytes = &b[..n];
let i = BigUint::from_bytes_be(bytes);
let tbs = 2 * (l % 4);
let adjusted_i = if tbs > 0 { i >> tbs } else { i };
let result = adjusted_i.to_u64().unwrap_or_else(|| 0);
Ok(int_to_b64(result as u32, l))
}
fn is_base64(s: &str) -> bool {
s.chars().all(|c| {
(c >= 'A' && c <= 'Z')
|| (c >= 'a' && c <= 'z')
|| (c >= '0' && c <= '9')
|| c == '+'
|| c == '/'
|| c == '-'
|| c == '_'
})
}
impl Matter for BaseMatter {
fn code(&self) -> &str {
&self.code
}
fn raw(&self) -> &[u8] {
&self.raw
}
fn qb64(&self) -> String {
let result = self.infil();
result.unwrap()
}
fn qb64b(&self) -> Vec<u8> {
let result = self.infil();
result.unwrap().into_bytes()
}
fn qb2(&self) -> Vec<u8> {
let result = self.binfil();
result.unwrap()
}
fn soft(&self) -> &str {
&self.soft
}
fn full_size(&self) -> usize {
let sizes = get_sizes();
let size = sizes[self.code.as_str()];
let (hs, ss, fs) = (size.hs, size.ss, size.fs);
match fs {
Some(fixed_size) => fixed_size as usize,
None => {
(hs + ss) as usize + (self.size() * 4)
}
}
}
fn size(&self) -> usize {
let soft = self.soft();
if soft.len() == 0 {
0
} else {
b64_to_int(self.soft()) as usize
}
}
fn is_transferable(&self) -> bool {
!non_trans_dex::TUPLE.contains(&(self.code.as_str()))
}
fn is_digestive(&self) -> bool {
dig_dex::TUPLE.contains(&(self.code.as_str()))
}
fn is_prefixive(&self) -> bool {
pre_dex::TUPLE.contains(&(self.code.as_str()))
}
fn is_special(&self) -> bool {
let sizes = get_sizes();
let size = sizes[self.code.as_str()];
match size.fs {
Some(_) => size.ss > 0,
None => false,
}
}
fn as_any(&self) -> &dyn Any {
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_base_matter_from_qb64() {
let qb64 = "BGlOiUdp5sMmfotHfCWQKEzWR91C72AH0lT84c0um-Qj";
let expected_raw =
b"iN\x89Gi\xe6\xc3&~\x8bG|%\x90(L\xd6G\xddB\xef`\x07\xd2T\xfc\xe1\xcd.\x9b\xe4#";
let prebin: [u8; 33] = [
0x04, 0x69, 0x4E, 0x89, 0x47, 0x69, 0xE6, 0xC3, 0x26, 0x7E, 0x8B, 0x47, 0x7C, 0x25,
0x90, 0x28, 0x4C, 0xD6, 0x47, 0xDD, 0x42, 0xEF, 0x60, 0x07, 0xD2, 0x54, 0xFC, 0xE1,
0xCD, 0x2E, 0x9B, 0xE4, 0x23,
];
let matter = BaseMatter::from_qb64(qb64).expect("Failed to create BaseMatter from qb64");
assert_eq!(matter.raw(), expected_raw);
assert_eq!(matter.code(), "B");
assert_eq!(matter.qb64(), qb64);
assert_eq!(matter.qb2(), prebin.to_vec());
}
#[test]
fn test_base_matter_from_raw() {
let raw = b"iN\x89Gi\xe6\xc3&~\x8bG|%\x90(L\xd6G\xddB\xef`\x07\xd2T\xfc\xe1\xcd.\x9b\xe4#";
let prebin: [u8; 33] = [
0x04, 0x69, 0x4E, 0x89, 0x47, 0x69, 0xE6, 0xC3, 0x26, 0x7E, 0x8B, 0x47, 0x7C, 0x25,
0x90, 0x28, 0x4C, 0xD6, 0x47, 0xDD, 0x42, 0xEF, 0x60, 0x07, 0xD2, 0x54, 0xFC, 0xE1,
0xCD, 0x2E, 0x9B, 0xE4, 0x23,
];
let matter = BaseMatter::new(Some(raw), Some("B"), None, None).unwrap();
assert_eq!(matter.raw(), raw);
assert_eq!(matter.code(), "B");
assert_eq!(
matter.qb64(),
"BGlOiUdp5sMmfotHfCWQKEzWR91C72AH0lT84c0um-Qj"
);
assert_eq!(matter.qb2(), prebin.to_vec());
let matter1 = BaseMatter::from_raw(Some(raw)).unwrap();
assert_eq!(matter1.raw(), raw);
assert_eq!(matter1.code(), "B");
assert_eq!(
matter1.qb64(),
"BGlOiUdp5sMmfotHfCWQKEzWR91C72AH0lT84c0um-Qj"
);
assert_eq!(matter1.qb2(), prebin.to_vec());
let matter2 = BaseMatter::from_qb2(&mut prebin.to_vec(), None).unwrap();
assert_eq!(matter2.raw(), raw);
assert_eq!(matter2.code(), "B");
assert_eq!(
matter2.qb64(),
"BGlOiUdp5sMmfotHfCWQKEzWR91C72AH0lT84c0um-Qj"
);
}
#[test]
fn test_matter_codex() {
let sizes = get_sizes();
assert_eq!(mtr_dex::ED25519_SEED, "A");
assert_eq!(mtr_dex::ED25519N, "B");
assert_eq!(mtr_dex::X25519, "C");
assert_eq!(mtr_dex::ED25519, "D");
assert_eq!(mtr_dex::BLAKE3_256, "E");
assert_eq!(mtr_dex::BLAKE2B_256, "F");
assert_eq!(mtr_dex::BLAKE2S_256, "G");
assert_eq!(mtr_dex::SHA3_256, "H");
assert_eq!(mtr_dex::SHA2_256, "I");
let size = sizes[mtr_dex::ED25519_SEED];
assert_eq!(size.hs, 1);
assert_eq!(size.ss, 0);
assert_eq!(size.xs, 0);
assert_eq!(size.fs, Some(44));
assert_eq!(size.ls, 0);
let size = sizes[mtr_dex::ED25519N];
assert_eq!(size.hs, 1);
assert_eq!(size.ss, 0);
assert_eq!(size.xs, 0);
assert_eq!(size.fs, Some(44));
assert_eq!(size.ls, 0);
let size = sizes[mtr_dex::BLAKE3_256];
assert_eq!(size.hs, 1);
assert_eq!(size.ss, 0);
assert_eq!(size.xs, 0);
assert_eq!(size.fs, Some(44));
assert_eq!(size.ls, 0);
assert_eq!(raw_size(mtr_dex::ED25519).unwrap(), 32);
assert_eq!(raw_size(mtr_dex::ED25519N).unwrap(), 32);
assert_eq!(raw_size(mtr_dex::BLAKE3_256).unwrap(), 32);
}
#[test]
fn test_matter_basic() {
let result = BaseMatter::new(None, None, None, None);
assert!(result.is_err());
let verkey =
b"iN\x89Gi\xe6\xc3&~\x8bG|%\x90(L\xd6G\xddB\xef`\x07\xd2T\xfc\xe1\xcd.\x9b\xe4#";
let result = BaseMatter::new(Some(verkey), None, None, None);
assert!(result.is_err());
let result = BaseMatter::new(Some(verkey), Some(mtr_dex::ED25519N), None, None);
assert!(result.is_ok());
let matter = result.unwrap();
assert_eq!(matter.code(), mtr_dex::ED25519N);
assert_eq!(matter.raw(), verkey);
let qb64 = matter.qb64();
assert_eq!(qb64, "BGlOiUdp5sMmfotHfCWQKEzWR91C72AH0lT84c0um-Qj");
let matter2 = BaseMatter::from_qb64(&qb64).unwrap();
assert_eq!(matter2.code(), mtr_dex::ED25519N);
assert_eq!(matter2.raw(), verkey);
assert_eq!(matter2.qb64(), qb64);
let qb2 = matter.qb2();
let matter3 = BaseMatter::from_qb2(&mut qb2.to_vec(), None).unwrap();
assert_eq!(matter3.code(), mtr_dex::ED25519N);
assert_eq!(matter3.raw(), verkey);
assert_eq!(matter3.qb64(), qb64);
assert!(!matter.is_transferable());
let result = BaseMatter::new(Some(verkey), Some(mtr_dex::ED25519), None, None);
assert!(result.is_ok());
let matter = result.unwrap();
assert_eq!(matter.code(), mtr_dex::ED25519);
assert!(matter.is_transferable());
assert!(!matter.is_digestive());
let digest = [0u8; 32];
let result = BaseMatter::new(
Some(digest.as_slice()),
Some(mtr_dex::BLAKE3_256),
None,
None,
);
assert!(result.is_ok());
let matter = result.unwrap();
assert_eq!(matter.code(), mtr_dex::BLAKE3_256);
assert!(matter.is_digestive());
assert!(matter.is_prefixive());
}
#[test]
fn test_matter_from_qb64() {
let prefix = "BGlOiUdp5sMmfotHfCWQKEzWR91C72AH0lT84c0um-Qj";
let matter = BaseMatter::from_qb64(prefix).unwrap();
assert_eq!(matter.code(), mtr_dex::ED25519N);
assert_eq!(matter.qb64(), prefix);
let both = format!("{}:mystuff/mypath/toresource?query=what#fragment", prefix);
let matter = BaseMatter::from_qb64(&both).unwrap();
assert_eq!(matter.code(), mtr_dex::ED25519N);
assert_eq!(matter.qb64(), prefix);
assert!(!matter.is_transferable());
assert!(!matter.is_digestive());
assert!(matter.is_prefixive());
}
#[test]
fn test_matter_from_qb64b() {
let prefix = "BGlOiUdp5sMmfotHfCWQKEzWR91C72AH0lT84c0um-Qj";
let mut prefixb = prefix.as_bytes().to_vec();
let matter = BaseMatter::from_qb64b(&mut prefixb, None).unwrap();
assert_eq!(matter.code(), mtr_dex::ED25519N);
assert_eq!(matter.qb64(), prefix);
let both = format!("{}:mystuff/mypath/toresource?query=what#fragment", prefix);
let mut bothb = both.as_bytes().to_vec();
let matter = BaseMatter::from_qb64b(&mut bothb, None).unwrap();
assert_eq!(matter.code(), mtr_dex::ED25519N);
assert_eq!(matter.qb64(), prefix);
assert!(!matter.is_transferable());
assert!(!matter.is_digestive());
assert!(matter.is_prefixive());
}
#[test]
fn test_matter_from_qb2() {
let prefix = "BGlOiUdp5sMmfotHfCWQKEzWR91C72AH0lT84c0um-Qj";
let matter = BaseMatter::from_qb64(prefix).unwrap();
let mut qb2 = matter.qb2();
let matter2 = BaseMatter::from_qb2(&mut qb2, None).unwrap();
assert_eq!(matter2.code(), mtr_dex::ED25519N);
assert_eq!(matter2.qb64(), prefix);
assert!(!matter2.is_transferable());
assert!(!matter2.is_digestive());
assert!(matter2.is_prefixive());
}
#[test]
fn test_matter_with_fixed_sizes() {
let code = mtr_dex::TBD0;
let raw = b"abc";
let qb64 = "1___YWJj";
let matter = BaseMatter::new(Some(raw), Some(code), None, None).unwrap();
assert_eq!(matter.code(), code);
assert_eq!(matter.raw(), raw);
assert_eq!(matter.qb64(), qb64);
assert!(matter.is_transferable());
assert!(!matter.is_digestive());
assert!(!matter.is_prefixive());
let matter2 = BaseMatter::from_qb64(qb64).unwrap();
assert_eq!(matter2.code(), code);
assert_eq!(matter2.raw(), raw);
let code = mtr_dex::TBD1;
let raw = b"ab";
let qb64 = "2___AGFi";
let matter = BaseMatter::new(Some(raw), Some(code), None, None).unwrap();
assert_eq!(matter.code(), code);
assert_eq!(matter.raw(), raw);
assert_eq!(matter.qb64(), qb64);
assert!(matter.is_transferable());
assert!(!matter.is_digestive());
assert!(!matter.is_prefixive());
let matter2 = BaseMatter::from_qb64(qb64).unwrap();
assert_eq!(matter2.code(), code);
assert_eq!(matter2.raw(), raw);
let code = mtr_dex::TBD2;
let raw = b"z";
let qb64 = "3___AAB6";
let matter = BaseMatter::new(Some(raw), Some(code), None, None).unwrap();
assert_eq!(matter.code(), code);
assert_eq!(matter.raw(), raw);
assert_eq!(matter.qb64(), qb64);
assert!(matter.is_transferable());
assert!(!matter.is_digestive());
assert!(!matter.is_prefixive());
let matter2 = BaseMatter::from_qb64(qb64).unwrap();
assert_eq!(matter2.code(), code);
assert_eq!(matter2.raw(), raw);
}
#[test]
fn test_matter_with_variable_sizes() {
let code = mtr_dex::BYTES_L0;
let raw = b"abcdef";
let qb64 = "4BACYWJjZGVm";
let matter = BaseMatter::new(Some(raw), Some(code), None, None).unwrap();
assert_eq!(matter.code(), code);
assert_eq!(matter.raw(), raw);
assert_eq!(matter.qb64(), qb64);
assert!(matter.is_transferable());
assert!(!matter.is_digestive());
assert!(!matter.is_prefixive());
let matter2 = BaseMatter::from_qb64(qb64).unwrap();
assert_eq!(matter2.code(), code);
assert_eq!(matter2.raw(), raw);
let code = mtr_dex::BYTES_L1;
let raw = b"abcde";
let qb64 = "5BACAGFiY2Rl";
let matter = BaseMatter::new(Some(raw), Some(code), None, None).unwrap();
assert_eq!(matter.code(), code);
assert_eq!(matter.raw(), raw);
assert_eq!(matter.qb64(), qb64);
assert!(matter.is_transferable());
assert!(!matter.is_digestive());
assert!(!matter.is_prefixive());
let matter2 = BaseMatter::from_qb64(qb64).unwrap();
assert_eq!(matter2.code(), code);
assert_eq!(matter2.raw(), raw);
let code = mtr_dex::BYTES_L2;
let raw = b"abcd";
let qb64 = "6BACAABhYmNk";
let matter = BaseMatter::new(Some(raw), Some(code), None, None).unwrap();
assert_eq!(matter.code(), code);
assert_eq!(matter.raw(), raw);
assert_eq!(matter.qb64(), qb64);
assert!(matter.is_transferable());
assert!(!matter.is_digestive());
assert!(!matter.is_prefixive());
let matter2 = BaseMatter::from_qb64(qb64).unwrap();
assert_eq!(matter2.code(), code);
assert_eq!(matter2.raw(), raw);
}
#[test]
fn test_matter_with_special_codes() {
let code = mtr_dex::TAG3;
let soft = "icp";
let qb64 = "Xicp";
let raw = b"";
let matter = BaseMatter::from_soft_and_code(soft, code).unwrap();
assert_eq!(matter.code(), code);
assert_eq!(matter.soft.as_str(), soft);
assert_eq!(matter.raw(), raw);
assert_eq!(matter.qb64(), qb64);
assert!(matter.is_special());
let matter2 = BaseMatter::from_qb64(qb64).unwrap();
assert_eq!(matter2.code(), code);
assert_eq!(matter2.soft.as_str(), soft);
assert_eq!(matter2.raw(), raw);
}
#[test]
fn test_versionage_from_string() {
let version_str = "KERI10JSON000000_".to_string();
let versionage = Versionage::from(version_str);
assert_eq!(versionage.major, 1);
assert_eq!(versionage.minor, 0);
let version_str = "KERI25CBOR000123_".to_string();
let versionage = Versionage::from(version_str);
assert_eq!(versionage.major, 2);
assert_eq!(versionage.minor, 5);
let version_str = "KERI10JSON000000_";
let versionage = Versionage::from(version_str);
assert_eq!(versionage.major, 1);
assert_eq!(versionage.minor, 0);
}
#[test]
fn test_parse_version_string() {
let result = Versionage::parse_version_string("KERI10JSON000000_");
assert!(result.is_ok());
let versionage = result.unwrap();
assert_eq!(versionage.major, 1);
assert_eq!(versionage.minor, 0);
let result = Versionage::parse_version_string("XERI10JSON000000_");
assert!(result.is_err());
let result = Versionage::parse_version_string("KERI");
assert!(result.is_err());
let result = Versionage::parse_version_string("KERIGZJSON000000_");
assert!(result.is_err());
}
}