use crate::internal::*;
pub struct Tree<'a, T: Contents> {
pub ptr: *mut IrminTree,
pub repo: UntypedRepo<'a>,
pub(crate) _t: std::marker::PhantomData<T>,
}
impl<'a, T: Contents> Drop for Tree<'a, T> {
fn drop(&mut self) {
unsafe { irmin_tree_free(self.ptr) }
}
}
impl<'a, T: Contents> PartialEq for Tree<'a, T> {
fn eq(&self, other: &Tree<'a, T>) -> bool {
unsafe { irmin_tree_equal(self.repo.ptr, self.ptr, other.ptr) }
}
}
impl<'a, T: Contents> Tree<'a, T> {
pub fn new(repo: &'a Repo<T>) -> Result<Tree<'a, T>, Error> {
unsafe {
let ptr = irmin_tree_new(repo.ptr);
check!(repo.ptr, ptr);
Ok(Tree {
ptr,
repo: UntypedRepo::new(repo),
_t: std::marker::PhantomData,
})
}
}
pub fn hash(&self) -> Result<Hash, Error> {
let h = unsafe { irmin_tree_hash(self.repo.ptr, self.ptr) };
check!(self.repo.ptr, h);
Ok(Hash {
ptr: h,
repo: self.repo.clone(),
})
}
pub fn key(&self) -> Result<Option<KindedKey>, Error> {
let h = unsafe { irmin_tree_key(self.repo.ptr, self.ptr) };
check_opt!(self.repo.ptr, h);
Ok(Some(KindedKey {
ptr: h,
repo: self.repo.clone(),
}))
}
pub fn of_hash(repo: &'a Repo<T>, h: &Hash) -> Result<Option<Tree<'a, T>>, Error> {
let ptr = unsafe { irmin_tree_of_hash(repo.ptr, h.ptr) };
check_opt!(repo.ptr, ptr);
Ok(Some(Tree {
ptr,
repo: UntypedRepo::new(repo),
_t: std::marker::PhantomData,
}))
}
pub fn of_key(repo: &'a Repo<T>, k: &KindedKey) -> Result<Option<Tree<'a, T>>, Error> {
let ptr = unsafe { irmin_tree_of_key(repo.ptr, k.ptr) };
check_opt!(repo.ptr, ptr);
Ok(Some(Tree {
ptr,
repo: UntypedRepo::new(repo),
_t: std::marker::PhantomData,
}))
}
pub fn add(
&mut self,
path: &Path,
value: &T,
metadata: Option<&Metadata>,
) -> Result<(), Error> {
let x = unsafe {
let value = value.to_value()?;
let meta = match metadata {
Some(m) => m.ptr,
None => std::ptr::null_mut(),
};
irmin_tree_add(self.repo.ptr, self.ptr, path.ptr, value.ptr as *mut _, meta)
};
check!(self.repo.ptr, x, false);
Ok(())
}
pub fn add_tree(&mut self, path: &Path, tree: &Tree<T>) -> Result<(), Error> {
let x = unsafe { irmin_tree_add_tree(self.repo.ptr, self.ptr, path.ptr, tree.ptr) };
check!(self.repo.ptr, x, false);
Ok(())
}
pub fn mem(&self, path: &Path) -> bool {
unsafe { irmin_tree_mem(self.repo.ptr, self.ptr, path.ptr) }
}
pub fn mem_tree(&self, path: &Path) -> bool {
unsafe { irmin_tree_mem_tree(self.repo.ptr, self.ptr, path.ptr) }
}
pub fn remove(&mut self, path: &Path) -> Result<(), Error> {
let x = unsafe { irmin_tree_remove(self.repo.ptr, self.ptr, path.ptr) };
check!(self.repo.ptr, x, false);
Ok(())
}
pub fn find(&self, path: &Path) -> Result<Option<T>, Error> {
unsafe {
let ptr = irmin_tree_find(self.repo.ptr, self.ptr, path.ptr);
check!(self.repo.ptr, ptr);
if ptr.is_null() {
return Ok(None);
}
let ty = T::ty()?;
let x = Value {
ptr: ptr as *mut _,
ty,
};
let value = T::from_value(&x)?;
Ok(Some(value))
}
}
pub fn find_tree(&self, path: &Path) -> Result<Option<Tree<T>>, Error> {
unsafe {
let ptr = irmin_tree_find_tree(self.repo.ptr, self.ptr, path.ptr);
check_opt!(self.repo.ptr, ptr);
let x = Tree {
ptr,
repo: self.repo.clone(),
_t: std::marker::PhantomData,
};
Ok(Some(x))
}
}
pub fn list(&self, path: &Path) -> Result<Vec<Path>, Error> {
let p = unsafe { irmin_tree_list(self.repo.ptr, self.ptr, path.ptr) };
check!(self.repo.ptr, p);
let len = unsafe { irmin_path_array_length(self.repo.ptr, p) };
let mut dest = Vec::new();
for i in 0..len {
let path = unsafe { irmin_path_array_get(self.repo.ptr, p, i) };
if path.is_null() {
continue;
}
dest.push(Path {
ptr: path,
repo: self.repo.clone(),
})
}
unsafe { irmin_path_array_free(p) }
Ok(dest)
}
}