leetcode_test_utils/tree/
shortcuts.rs

1//! Wraps a value in [`TreeNode`] all in one function, of any scale.
2
3use super::raw_def::TreeNode;
4use std::cell::RefCell;
5use std::ptr::{null, null_mut};
6use std::rc::Rc;
7
8/// Create a [`RefCell<TreeNode>`] with given value.
9///
10/// This function is trivial. It only lets you avoid writing bunches of boiler plate code "::new(...)".
11///
12/// # Examples
13///
14/// ```
15/// use leetcode_test_utils::tree::shortcuts::new_cell;
16/// let cell = new_cell(42);
17/// assert_eq!(cell.borrow().val, 42);
18/// ```
19#[inline]
20pub fn new_cell(val: i32) -> RefCell<TreeNode> {
21    RefCell::new(TreeNode::new(val))
22}
23
24/// Create a [`Rc<RefCell<TreeNode>>`] with given value.
25///
26/// This function is trivial. It only lets you avoid writing bunches of boiler plate code "::new(...)".
27///
28/// # Examples
29///
30/// ```
31/// use leetcode_test_utils::tree::shortcuts::new_rc;
32/// let rc = new_rc(42);
33/// assert_eq!(rc.borrow().val, 42);
34/// ```
35#[inline]
36pub fn new_rc(val: i32) -> Rc<RefCell<TreeNode>> {
37    Rc::new(RefCell::new(TreeNode::new(val)))
38}
39
40/// Create a complete node([`Option<Rc<RefCell<TreeNode>>>`]) with given value.
41///
42/// This function is trivial. It only lets you avoid writing bunches of boiler plate code "::new(...)".
43///
44/// # Examples
45///
46/// ```
47/// use leetcode_test_utils::tree::shortcuts::new_node;
48/// let node = new_node(42);
49/// assert_eq!(node.unwrap().borrow().val, 42);
50/// ```
51#[inline]
52pub fn new_node(val: i32) -> Option<Rc<RefCell<TreeNode>>> {
53    Some(Rc::new(RefCell::new(TreeNode::new(val))))
54}
55
56/// Access the value pointed by the given pointer.
57///
58/// This function is a shortcut for getting the value pointed by `p`.
59/// It is often used for pointer gotten by calling `as_ptr()` on whatever coerces to [`RefCell<TreeNode>`].
60///
61/// # Safety
62///
63/// - The pointer **must not** be null, or the program will crash.
64///
65/// # Examples
66///
67/// ```
68/// use leetcode_test_utils::tree::shortcuts::{new_node, val};
69/// let node = new_node(42);
70/// let pointer = node.as_ref().unwrap().as_ptr();
71/// assert_eq!(val(pointer), 42);
72/// ```
73#[inline]
74pub fn val(p: *const TreeNode) -> i32 {
75    unsafe { (*p).val }
76}
77
78/// Convert the rust style mutable pointer(specified in leetcode) into C/C++ style immutable pointer.
79///
80/// Returns the immutable pointer handled by `root` if it is [`Some`], or [`std::ptr::null()`] is returned.
81/// Rust is so famous for its safety, in which the most safe way to operate on a pointer is to
82/// borrow a [`RefCell`] at runtime. But sometimes you really want to let the program perform the
83/// best(yeah, you do not want to be penalized anyway) as if you run the corresponding raw C/C++ code.
84/// This function provides the highway for you. **Be careful**!
85///
86/// # Examples
87///
88/// ```
89/// use leetcode_test_utils::tree::shortcuts::{new_node, to_ptr};
90/// use leetcode_test_utils::btree;
91/// let root = btree!(42, 10);  // ok, `root->left->val` is 10
92/// unsafe{
93///     assert_eq!((*to_ptr((*to_ptr(root.as_ref())).left.as_ref())).val, 10);
94/// }
95/// assert_eq!(to_ptr(None), std::ptr::null());
96/// ```
97#[inline]
98pub fn to_ptr(root: Option<&Rc<RefCell<TreeNode>>>) -> *const TreeNode {
99    root.map_or(null(), |r| r.as_ptr())
100}
101
102/// Convert the rust style mutable pointer(specified in leetcode) into C/C++ style mutable pointer.
103///
104/// Returns the mutable pointer handled by `root` if is [`Some`], or [`std::ptr::null_mut()`] is
105/// returned. Rust is so famous for its safety, in which the most safe way to operate on a pointer
106/// is to borrow a [`RefCell`] at runtime. But sometimes you really want to let the program perform
107/// the best(yeah, you do not want to be penalized anyway) as if you run the corresponding raw C/C++
108/// code. This function provides the railway for you. **Be CAREFUL**!
109///
110/// # Examples
111///
112/// ```
113/// use leetcode_test_utils::tree::shortcuts::to_ptr_mut;
114/// use leetcode_test_utils::tree::T;
115/// use leetcode_test_utils::btree;
116///
117/// let root = btree!(42, null, 50);
118/// let ptr_root_right = to_ptr_mut(root.as_ref());
119/// unsafe{
120///     (*ptr_root_right).val = 45;
121/// }
122/// let tree1 = T(root);
123/// let tree2 = T(btree!(45, null, 50));
124/// assert_eq!(tree1, tree2);
125/// ```
126#[inline]
127pub fn to_ptr_mut(root: Option<&Rc<RefCell<TreeNode>>>) -> *mut TreeNode {
128    root.map_or(null_mut(), |r| r.as_ptr())
129}