use crate::primitive::errors::{GeneralError, GeneralError::ParseError, Result};
pub trait KeyIdMapping<Id, K> {
fn map_key_to_id(&self, key: &K) -> Option<Id>;
fn map_id_to_public(&self, id: &Id) -> Option<K>;
fn map_keys_to_ids(&self, keys: &[K]) -> Vec<Option<Id>> {
keys.iter().map(|key| self.map_key_to_id(key)).collect()
}
fn map_ids_to_keys(&self, ids: &[Id]) -> Vec<Option<K>> {
ids.iter().map(|id| self.map_id_to_public(id)).collect()
}
}
pub trait ToHex {
fn to_hex(&self) -> String;
fn from_hex(str: &str) -> Result<Self>
where
Self: Sized;
}
pub trait BytesEncodable<const N: usize, E = GeneralError>:
Into<[u8; N]> + for<'a> TryFrom<&'a [u8], Error = E>
{
const SIZE: usize = N;
#[inline]
fn into_encoded(self) -> [u8; N] {
self.into()
}
#[inline]
fn into_boxed(self) -> Box<[u8]> {
Box::new(self.into_encoded())
}
}
pub trait BytesRepresentable<E = GeneralError>:
AsRef<[u8]> + for<'a> TryFrom<&'a [u8], Error = E>
{
const SIZE: usize;
#[inline]
fn into_boxed(self) -> Box<[u8]> {
self.as_ref().into()
}
}
impl<T: BytesRepresentable> ToHex for T {
fn to_hex(&self) -> String {
format!("0x{}", hex::encode(self.as_ref()))
}
fn from_hex(str: &str) -> Result<Self> {
if !str.is_empty() && str.len().is_multiple_of(2) {
let data = str
.strip_prefix("0x")
.or_else(|| str.strip_prefix("0X"))
.unwrap_or(str);
hex::decode(data)
.map_err(|e| ParseError(e.to_string()))
.and_then(|bytes| T::try_from(&bytes))
} else {
Err(ParseError("invalid hex length".into()))
}
}
}
impl<const N: usize> BytesRepresentable<std::array::TryFromSliceError> for [u8; N] {
const SIZE: usize = N;
}
pub trait UnitaryFloatOps: Sized {
fn mul_f64(&self, rhs: f64) -> Result<Self>;
fn div_f64(&self, rhs: f64) -> Result<Self>;
}
pub trait IntoEndian<const N: usize> {
fn from_be_bytes<T: AsRef<[u8]>>(bytes: T) -> Self;
fn from_le_bytes<T: AsRef<[u8]>>(bytes: T) -> Self;
fn to_le_bytes(self) -> [u8; N];
fn to_be_bytes(self) -> [u8; N];
}
pub trait AsUnixTimestamp {
fn as_unix_timestamp(&self) -> std::time::Duration;
}
impl AsUnixTimestamp for std::time::SystemTime {
fn as_unix_timestamp(&self) -> std::time::Duration {
self.saturating_sub(std::time::SystemTime::UNIX_EPOCH)
}
}
pub trait SaturatingSub {
fn saturating_sub(&self, earlier: std::time::SystemTime) -> std::time::Duration;
}
impl SaturatingSub for std::time::SystemTime {
fn saturating_sub(&self, earlier: std::time::SystemTime) -> std::time::Duration {
self.duration_since(earlier)
.unwrap_or(std::time::Duration::ZERO)
}
}