Skip to content

Instantly share code, notes, and snippets.

@ubolonton
Last active August 1, 2019 00:41
Show Gist options
  • Save ubolonton/98dfa7bd302d140ec49b10508d8b9c11 to your computer and use it in GitHub Desktop.
Save ubolonton/98dfa7bd302d140ec49b10508d8b9c11 to your computer and use it in GitHub Desktop.
use std::{mem, ptr, os, rc::Rc, cell:RefCell, marker::PhantomData};
// -------------------------------------------------------------------
// Structs declared in a C header.
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct C_Tree {
_unused: [u8; 0],
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct C_Cursor {
pub tree: *const os::raw::c_void,
pub id: *const ::os::raw::c_void,
pub context: [u32; 2usize],
}
// -------------------------------------------------------------------
pub struct Tree(*mut C_Tree);
// Cursor must not outlive the tree, hence the lifetime param.
pub struct Cursor<'tree>(C_Cursor, PhantomData<&'tree ()>);
impl<'tree> Drop for Cursor<'tree> {
fn drop(&mut self) {
unsafe { c_delete_cursor(&mut self.0) }
}
}
// -------------------------------------------------------------------
const CURSOR_LEN: usize = mem::size_of::<Cursor>();
pub type RawCursor = [u8; CURSOR_LEN];
/// Wrapper struct that ref-counts the tree so that no lifetime is needed.
#[derive(Clone)]
pub struct WrappedCursor {
pub(crate) tree: Rc<RefCell<Tree>>,
depth: u8,
raw: RawCursor,
}
impl WrappedCursor {
pub unsafe fn new(tree: Rc<RefCell<Tree>>, inner: Cursor) -> Self {
let ptr = (&inner as *const Cursor) as *const RawCursor;
let raw = ptr.read();
Self { tree, raw, depth: 0 }
}
pub unsafe fn wrap(&self, inner: Cursor) -> Self {
let tree = self.tree.clone();
Self::new(tree, inner)
}
pub fn inner(&self) -> &Cursor {
let ptr = (&self.raw as *const RawCursor) as *const Cursor;
unsafe { &*ptr }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment