use codec::{Decode, Encode};
pub const JUNCTION_ID_LEN: usize = 32;
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Encode, Decode)]
pub enum DeriveJunction {
Soft([u8; JUNCTION_ID_LEN]),
Hard([u8; JUNCTION_ID_LEN]),
}
impl DeriveJunction {
pub fn soften(self) -> Self {
DeriveJunction::Soft(self.into_inner())
}
pub fn harden(self) -> Self {
DeriveJunction::Hard(self.into_inner())
}
pub fn soft<T: Encode>(index: T) -> Self {
let mut cc: [u8; JUNCTION_ID_LEN] = Default::default();
index.using_encoded(|data| {
if data.len() > JUNCTION_ID_LEN {
cc.copy_from_slice(&sp_crypto_hashing::blake2_256(data));
} else {
cc[0..data.len()].copy_from_slice(data);
}
});
DeriveJunction::Soft(cc)
}
pub fn hard<T: Encode>(index: T) -> Self {
Self::soft(index).harden()
}
pub fn into_inner(self) -> [u8; JUNCTION_ID_LEN] {
match self {
DeriveJunction::Hard(c) | DeriveJunction::Soft(c) => c,
}
}
pub fn inner(&self) -> &[u8; JUNCTION_ID_LEN] {
match self {
DeriveJunction::Hard(ref c) | DeriveJunction::Soft(ref c) => c,
}
}
pub fn is_soft(&self) -> bool {
matches!(*self, DeriveJunction::Soft(_))
}
pub fn is_hard(&self) -> bool {
matches!(*self, DeriveJunction::Hard(_))
}
}
impl<T: AsRef<str>> From<T> for DeriveJunction {
fn from(j: T) -> DeriveJunction {
let j = j.as_ref();
let (code, hard) = if let Some(stripped) = j.strip_prefix('/') {
(stripped, true)
} else {
(j, false)
};
let res = if let Ok(n) = str::parse::<u64>(code) {
DeriveJunction::soft(n)
} else {
DeriveJunction::soft(code)
};
if hard {
res.harden()
} else {
res
}
}
}