Repository: jaytaph/gosub-browser
File: crates/gosub-bindings/src/lib.rs (Rust)

Code before:
/// Takes a tree_iterator and returns a non-owning pointer to the next node
///
/// # Safety
/// Takes a tree_iterator pointer (owned by the C API generated by gosub_render_tree_iterator_init())
/// and modifies it to point to the next tree-order node in the tree. Any heap-allocated data
/// on the current node is free'd before pointing to the next node. Returns a ready-only pointer
/// to the next node.
#[no_mangle]
pub unsafe extern "C" fn gosub_render_tree_next_node(
    tree_iterator: *mut TreeIterator,
) -> *const Node {
    let next = (*tree_iterator).next();
    if let Some(next) = next {
        next.as_ptr() as *const Node
    } else {
        ptr::null()
    }
}

/// Fetch the node data according to the NodeType of the current node.
///
/// # Safety
/// Uses a read-only pointer obtained from gosub_render_tree_next_node()
/// and a mutable pointer owned by the C API to write (copy) the contents
/// of the read-only pointer into the mutable pointer.
#[no_mangle]
pub unsafe extern "C" fn gosub_render_tree_get_node_data(
    node: *const Node,
    node_data: *mut CTextNode,
) {
    if let NodeType::Text(text_node) = &(*node).node_type {
        *node_data = CTextNode::from(text_node);
    }
}

/// Free the iterator pointer obtained from gosub_render_tree_iterator_init()
///
/// # Safety
/// This takes ownership of the pointer from the C API and transfers it to Rust so it can
/// be deallocated.
#[no_mangle]
pub unsafe extern "C" fn gosub_render_tree_iterator_free(tree_iterator: *mut TreeIterator) {
    let _ = Box::from_raw(tree_iterator);
}

/// Free the render_tree pointer obtained from gosub_render_tree_init()
///
/// # Safety
/// This takes ownership of the pointer from the C API and transfers it to Rust so it can
/// be deallocated.
///

Review comment (suggestion):
new struct `CNode` introduced to more properly wrap the `node_t` struct from the C API. This is more generic than the previous `CTextNode` when we add more types

Code after:
///
/// # Safety
/// Takes a tree_iterator pointer (owned by the C API generated by gosub_render_tree_iterator_init())
/// and modifies it to point to the next tree-order node in the tree. Any heap-allocated data
/// on the current node is free'd before pointing to the next node. Returns a ready-only pointer
/// to the next node.
#[no_mangle]
pub unsafe extern "C" fn gosub_render_tree_next_node(
    tree_iterator: *mut TreeIterator,
) -> *const Node {
    let next = (*tree_iterator).next();
    if let Some(next) = next {
        next.as_ptr() as *const Node
    } else {
        ptr::null()
    }
}

/// Fetch the node data according to the NodeType of the current node.
///
/// # Safety
/// Uses a read-only pointer obtained from gosub_render_tree_next_node()
/// and a mutable pointer owned by the C API to write (copy) the contents
/// of the read-only pointer into the mutable pointer.
#[no_mangle]
pub unsafe extern "C" fn gosub_render_tree_get_node_data(node: *const Node, c_node: *mut CNode) {
    // Change this to a match when we have more types
    if let NodeType::Text(text_node) = &(*node).node_type {
        (*c_node) = CNode::new_text(&(*node).position, text_node);
    }
}

/// Free the iterator pointer obtained from gosub_render_tree_iterator_init()
///
/// # Safety
/// This takes ownership of the pointer from the C API and transfers it to Rust so it can
/// be deallocated.
#[no_mangle]
pub unsafe extern "C" fn gosub_render_tree_iterator_free(tree_iterator: *mut TreeIterator) {
    let _ = Box::from_raw(tree_iterator);
}

/// Free the render_tree pointer obtained from gosub_render_tree_init()
///
/// # Safety
/// This takes ownership of the pointer from the C API and transfers it to Rust so it can
/// be deallocated.
///
// INTERNAL NOTE: It seems there's a leak happening with the document handle (if you
// check with valgrind) although I cannot figure out how to resolve this memory leak...
// needs more investigation; I've tried various methods.