1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
//! Wraps a value in [`TreeNode`] all in one function, of any scale.

use super::raw_def::TreeNode;
use std::cell::RefCell;
use std::ptr::{null, null_mut};
use std::rc::Rc;

/// Create a [`RefCell<TreeNode>`] with given value.
///
/// This function is trivial. It only lets you avoid writing bunches of boiler plate code "::new(...)".
///
/// # Examples
///
/// ```
/// use leetcode_test_utils::tree::shortcuts::new_cell;
/// let cell = new_cell(42);
/// assert_eq!(cell.borrow().val, 42);
/// ```
#[inline]
pub fn new_cell(val: i32) -> RefCell<TreeNode> {
    RefCell::new(TreeNode::new(val))
}

/// Create a [`Rc<RefCell<TreeNode>>`] with given value.
///
/// This function is trivial. It only lets you avoid writing bunches of boiler plate code "::new(...)".
///
/// # Examples
///
/// ```
/// use leetcode_test_utils::tree::shortcuts::new_rc;
/// let rc = new_rc(42);
/// assert_eq!(rc.borrow().val, 42);
/// ```
#[inline]
pub fn new_rc(val: i32) -> Rc<RefCell<TreeNode>> {
    Rc::new(RefCell::new(TreeNode::new(val)))
}

/// Create a complete node([`Option<Rc<RefCell<TreeNode>>>`]) with given value.
///
/// This function is trivial. It only lets you avoid writing bunches of boiler plate code "::new(...)".
///
/// # Examples
///
/// ```
/// use leetcode_test_utils::tree::shortcuts::new_node;
/// let node = new_node(42);
/// assert_eq!(node.unwrap().borrow().val, 42);
/// ```
#[inline]
pub fn new_node(val: i32) -> Option<Rc<RefCell<TreeNode>>> {
    Some(Rc::new(RefCell::new(TreeNode::new(val))))
}

/// Access the value pointed by the given pointer.
///
/// This function is a shortcut for getting the value pointed by `p`.
/// It is often used for pointer gotten by calling `as_ptr()` on whatever coerces to [`RefCell<TreeNode>`].
///
/// # Safety
///
/// - The pointer **must not** be null, or the program will crash.
///
/// # Examples
///
/// ```
/// use leetcode_test_utils::tree::shortcuts::{new_node, val};
/// let node = new_node(42);
/// let pointer = node.as_ref().unwrap().as_ptr();
/// assert_eq!(val(pointer), 42);
/// ```
#[inline]
pub fn val(p: *const TreeNode) -> i32 {
    unsafe { (*p).val }
}

/// Convert the rust style mutable pointer(specified in leetcode) into C/C++ style immutable pointer.
///
/// Returns the immutable pointer handled by `root` if it is [`Some`], or [`std::ptr::null()`] is returned.
/// Rust is so famous for its safety, in which the most safe way to operate on a pointer is to
/// borrow a [`RefCell`] at runtime. But sometimes you really want to let the program perform the
/// best(yeah, you do not want to be penalized anyway) as if you run the corresponding raw C/C++ code.
/// This function provides the highway for you. **Be careful**!
///
/// # Examples
///
/// ```
/// use leetcode_test_utils::tree::shortcuts::{new_node, to_ptr};
/// use leetcode_test_utils::btree;
/// let root = btree!(42, 10);  // ok, `root->left->val` is 10
/// unsafe{
///     assert_eq!((*to_ptr((*to_ptr(root.as_ref())).left.as_ref())).val, 10);
/// }
/// assert_eq!(to_ptr(None), std::ptr::null());
/// ```
#[inline]
pub fn to_ptr(root: Option<&Rc<RefCell<TreeNode>>>) -> *const TreeNode {
    root.map_or(null(), |r| r.as_ptr())
}

/// Convert the rust style mutable pointer(specified in leetcode) into C/C++ style mutable pointer.
///
/// Returns the mutable pointer handled by `root` if is [`Some`], or [`std::ptr::null_mut()`] is
/// returned. Rust is so famous for its safety, in which the most safe way to operate on a pointer
/// is to borrow a [`RefCell`] at runtime. But sometimes you really want to let the program perform
/// the best(yeah, you do not want to be penalized anyway) as if you run the corresponding raw C/C++
/// code. This function provides the railway for you. **Be CAREFUL**!
///
/// # Examples
///
/// ```
/// use leetcode_test_utils::tree::shortcuts::to_ptr_mut;
/// use leetcode_test_utils::tree::T;
/// use leetcode_test_utils::btree;
///
/// let root = btree!(42, null, 50);
/// let ptr_root_right = to_ptr_mut(root.as_ref());
/// unsafe{
///     (*ptr_root_right).val = 45;
/// }
/// let tree1 = T(root);
/// let tree2 = T(btree!(45, null, 50));
/// assert_eq!(tree1, tree2);
/// ```
#[inline]
pub fn to_ptr_mut(root: Option<&Rc<RefCell<TreeNode>>>) -> *mut TreeNode {
    root.map_or(null_mut(), |r| r.as_ptr())
}