use num_bigint::ToBigInt;
use crate::classic::clvm::__type_compatibility__::{bi_one, bi_zero, Bytes};
use crate::classic::clvm::casts::{
bigint_from_bytes, bigint_to_bytes_clvm, bigint_to_bytes_unsigned,
};
use crate::util::Number;
pub fn compose_paths(path_0_: &Number, path_1_: &Number) -> Number {
let path_0 = path_0_.clone();
let mut path_1 = path_1_.clone();
let mut mask = bi_one();
let mut temp_path = path_0.clone();
while temp_path > bi_one() {
path_1 <<= 1;
mask <<= 1;
temp_path >>= 1;
}
mask -= bi_one();
path_1 | (path_0 & mask)
}
pub struct NodePath {
index: Number,
}
impl NodePath {
pub fn new(index: Option<Number>) -> Self {
match index {
Some(index) => {
if index < bi_zero() {
let bytes_repr = bigint_to_bytes_clvm(&index);
let unsigned = bigint_from_bytes(&bytes_repr, None);
NodePath { index: unsigned }
} else {
NodePath { index }
}
}
None => NodePath { index: bi_one() },
}
}
pub fn as_path(&self) -> Bytes {
bigint_to_bytes_unsigned(&self.index)
}
pub fn add(&self, other_node: NodePath) -> Self {
let composed_path = compose_paths(&self.index, &other_node.index);
NodePath::new(Some(composed_path))
}
pub fn first(&self) -> Self {
NodePath::new(Some(self.index.clone() * 2_u32.to_bigint().unwrap()))
}
pub fn rest(&self) -> Self {
NodePath::new(Some(
(self.index.clone() * 2_u32.to_bigint().unwrap()) + bi_one(),
))
}
}