pub mod crypto;
pub mod nohash_hasher;
pub use primitive_types::U256;
use std::fmt;
use std::str::FromStr;
use std::string::ToString;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash)]
#[serde(into = "String", try_from = "&str")]
#[repr(transparent)]
pub struct U120(pub u128);
impl U120 {
pub const ZERO: U120 = U120(0);
pub const MAX: U120 = U120((1_u128 << 120) - 1);
pub fn new(numb: u128) -> Option<Self> {
if numb >> 120 == 0 {
Some(U120(numb))
} else {
None
}
}
pub fn from_u128_unchecked(numb: u128) -> Self {
debug_assert_eq!(numb >> 120, 0_u128);
U120(numb)
}
pub fn wrapping_add(self, other: U120) -> U120 {
let res = self.0 + other.0;
U120(res & U120::MAX.0)
}
pub fn wrapping_sub(self, other: U120) -> U120 {
let other_complement =
U120::wrapping_add(U120(other.0 ^ U120::MAX.0), U120(1));
U120::wrapping_add(self, other_complement)
}
pub fn wrapping_mul(self, other: U120) -> U120 {
const LO_MASK: u128 = (1 << 60) - 1;
let a = self.0;
let b = other.0;
let a_lo = a & LO_MASK;
let a_hi = a >> 60;
let b_lo = b & LO_MASK;
let b_hi = b >> 60;
let s0 = a_lo * b_lo;
let s1 = ((a_hi * b_lo) & LO_MASK) << 60;
let s2 = ((b_hi * a_lo) & LO_MASK) << 60;
U120(s0).wrapping_add(U120(s1)).wrapping_add(U120(s2))
}
pub fn wrapping_div(self, other: U120) -> U120 {
U120(self.0 / other.0)
}
pub fn wrapping_rem(self, other: U120) -> U120 {
U120(self.0 % other.0)
}
pub fn wrapping_shl(self, other: U120) -> U120 {
U120((self.0 << (other.0 % 120)) & U120::MAX.0)
}
pub fn wrapping_shr(self, other: U120) -> U120 {
U120(self.0 >> (other.0 % 120))
}
pub fn to_hex_literal(&self) -> String {
format!("#x{:x}", self.0)
}
}
impl std::ops::Deref for U120 {
type Target = u128;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl TryFrom<u128> for U120 {
type Error = String;
fn try_from(numb: u128) -> Result<Self, Self::Error> {
if numb >> 120 != 0 {
Err(format!("Number {} does not fit in 120-bits.", numb))
} else {
Ok(U120(numb))
}
}
}
impl From<Name> for U120 {
fn from(num: Name) -> Self {
U120(*num)
}
}
impl fmt::Display for U120 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<U120> for String {
fn from(num: U120) -> Self {
num.to_string()
}
}
impl TryFrom<&str> for U120 {
type Error = String;
fn try_from(txt: &str) -> Result<Self, Self::Error> {
fn err_msg<E: fmt::Debug>(e: E) -> String {
format!("Invalid number string '{:?}'", e)
}
let mut chrs = txt.chars();
let is_hex = txt.chars().peekable().peek().map_or(false, |x| x == &'x');
if is_hex {
chrs.next();
let mut digits = 0;
let mut num = 0;
for char in chrs {
match char {
'0'..='9' => num = (num << 4) + ((char as u128) - ('0' as u128)),
'a'..='f' => num = (num << 4) + ((char as u128) - ('a' as u128) + 10),
'A'..='F' => num = (num << 4) + ((char as u128) - ('A' as u128) + 10),
_ => return Err(err_msg(txt)),
}
digits += 1;
if digits > 30 {
return Err(err_msg(txt));
}
}
Ok(U120(num))
} else {
let mut num = 0;
for char in chrs {
match char {
'0'..='9' => num = (num * 10) + ((char as u128) - ('0' as u128)),
_ => return Err(err_msg(txt)),
}
}
Ok(U120(num))
}
}
}
impl nohash_hasher::IsEnabled for U120 {}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash)]
#[serde(into = "String", try_from = "&str")]
#[repr(transparent)]
pub struct Name(pub u128);
impl nohash_hasher::IsEnabled for Name {}
pub fn char_to_code(chr: char) -> Result<u128, String> {
let num = match chr {
'.' => 0,
'0'..='9' => 1 + chr as u128 - '0' as u128,
'A'..='Z' => 11 + chr as u128 - 'A' as u128,
'a'..='z' => 37 + chr as u128 - 'a' as u128,
'_' => 63,
_ => {
return Err(format!("Invalid Kindelia Name letter '{}'.", chr));
}
};
Ok(num)
}
impl Name {
pub const MAX_BITS: usize = 72;
pub const MAX_CHARS: usize = Self::MAX_BITS / 6;
pub const _NONE: u128 = 0x3FFFF;
pub const EMPTY: Name = Name(0);
pub const NONE: Name = Name(Self::_NONE);
pub const fn new(name: u128) -> Option<Self> {
if name >> Self::MAX_BITS == 0 {
Some(Name(name))
} else {
None
}
}
pub const fn new_unsafe(name: u128) -> Self {
debug_assert!(name >> Self::MAX_BITS == 0);
Name(name)
}
pub fn is_empty(&self) -> bool {
self.0 == 0
}
pub fn is_none(&self) -> bool {
self.0 == Self::_NONE
}
pub const fn from_u128_unchecked(numb: u128) -> Self {
Name(numb)
}
pub fn from_str_unsafe(name_txt: &str) -> Name {
let mut num: u128 = 0;
for (i, chr) in name_txt.chars().enumerate() {
debug_assert!(i < Self::MAX_CHARS, "Name too big: `{}`.", name_txt);
num = (num << 6) + char_to_code(chr).unwrap();
}
Name(num)
}
pub fn show_hex(&self) -> String {
format!("#x{:0>30x}", **self)
}
}
impl std::ops::Deref for Name {
type Target = u128;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl fmt::Display for Name {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
let name: String = if self.is_none() {
String::from("~")
} else {
let mut name = String::new();
let mut num = self.0;
while num > 0 {
let chr = (num % 64) as u8;
let chr = match chr {
0 => '.',
1..=10 => (chr - 1 + b'0') as char,
11..=36 => (chr - 11 + b'A') as char,
37..=62 => (chr - 37 + b'a') as char,
63 => '_',
64.. => panic!("Impossible letter value."),
};
name.push(chr);
num /= 64;
}
name.chars().rev().collect()
};
f.write_str(&name)
}
}
impl TryFrom<&str> for Name {
type Error = String;
fn try_from(name_txt: &str) -> Result<Self, Self::Error> {
if name_txt == "~" {
Ok(Name::NONE)
} else if name_txt.len() > Self::MAX_CHARS {
Err(format!("Name '{}' exceeds {} letters.", name_txt, Self::MAX_CHARS))
} else {
let mut num: u128 = 0;
for chr in name_txt.chars() {
num = (num << 6) + char_to_code(chr)?;
}
Ok(Name(num))
}
}
}
impl TryFrom<u128> for Name {
type Error = String;
fn try_from(name: u128) -> Result<Self, Self::Error> {
if name >> Self::MAX_BITS != 0 {
Err(format!("Name does not fit in {}-bits.", Self::MAX_BITS))
} else {
Ok(Name(name))
}
}
}
impl From<U120> for Name {
fn from(num: U120) -> Self {
assert!(*num >> Name::MAX_BITS == 0);
Name(*num)
}
}
impl From<Name> for String {
fn from(name: Name) -> Self {
name.to_string()
}
}
impl FromStr for Name {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
s.try_into()
}
}