diff --git a/Cargo.lock b/Cargo.lock index 6efc0cc..d94797d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,9 +19,9 @@ dependencies = [ [[package]] name = "platform-num" -version = "0.6.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51306628a5a0398b4216348a9b826866c83f9709661dd994865baf2a486b052b" +checksum = "2c4ca8e18138b1c90ad802aff931f946a0e6bd760c35af30f1ff2489489ab54a" dependencies = [ "num-traits", ] @@ -30,6 +30,5 @@ dependencies = [ name = "platform-trees" version = "0.2.0" dependencies = [ - "num-traits", "platform-num", ] diff --git a/Cargo.toml b/Cargo.toml index 5cb014b..4776015 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,8 +19,7 @@ name = "platform_trees" path = "src/lib.rs" [dependencies] -num-traits = "0.2.19" -platform-num = "0.6.0" +platform-num = "0.8.0" [lints.rust] unsafe_code = "allow" diff --git a/README.md b/README.md index c236007..b5a7161 100644 --- a/README.md +++ b/README.md @@ -163,7 +163,6 @@ impl AbsoluteCircularLinkedList for MyListStorage {} ## Depend on -- [num-traits](https://crates.io/crates/num-traits) - [platform-num](https://crates.io/crates/platform-num) ([Numbers](https://github.com/linksplatform/Numbers)) diff --git a/changelog.d/20260414_replace_linktype_with_linkreference.md b/changelog.d/20260414_replace_linktype_with_linkreference.md new file mode 100644 index 0000000..8a71940 --- /dev/null +++ b/changelog.d/20260414_replace_linktype_with_linkreference.md @@ -0,0 +1,13 @@ +--- +bump: minor +--- + +### Changed + +- **Breaking:** Removed `LinkType` trait entirely — use `LinkReference` from `platform-num` instead +- All trait bounds now use `T: LinkReference` instead of `T: LinkType` +- Replaced all `funty()` calls with `from_byte()` from `LinkReference` +- Re-exported `LinkReference` from `platform_num` in the public API +- Removed direct `num-traits` dependency (now provided transitively via `platform-num`) +- Upgraded `platform-num` from 0.6.0 to 0.8.0 +- Added `u128` support via `LinkReference` diff --git a/experiments/test_funty_compatibility.rs b/experiments/test_funty_compatibility.rs index 45a9e03..86ac2af 100644 --- a/experiments/test_funty_compatibility.rs +++ b/experiments/test_funty_compatibility.rs @@ -1,14 +1,8 @@ -// Experiment: Verify that removing the `funty` crate dependency from trees-rs -// does NOT break the public `funty()` method API. +// Experiment: Verify that `LinkReference::from_byte()` works correctly. // -// Key finding: The `funty` crate and the `funty()` method are different things. -// - `funty` crate: provides `funty::Unsigned` trait -// - `funty()` method: a convenience method on the `LinkType` trait for creating -// small integer values from u8 -// -// PR #9 removed the `funty` crate dependency but PRESERVED the `funty()` method -// on the `LinkType` trait. The `funty()` method now uses `num_traits::Unsigned` -// instead of `funty::Unsigned` for the trait bound, but the method signature -// and behavior are identical. +// History: +// - `funty` crate was removed in PR #9, but `funty()` method was preserved +// - Issue #30 replaced both `LinkType` and `funty()` with `LinkReference` +// and `from_byte()` from `platform-num`, unifying the trait hierarchy // // See tests/funty_compatibility.rs for the runnable test version. diff --git a/src/lib.rs b/src/lib.rs index 877a47b..e0aff8c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,7 +12,7 @@ //! //! | Trait | Description | //! |---|---| -//! | [`LinkType`] | Marker trait for unsigned integer types usable as node indices | +//! | [`LinkReference`] | Unsigned integer type usable as a node index (from `platform-num`) | //! | [`LinkedList`] | Base doubly-linked list with `get_previous`/`get_next` | //! | [`AbsoluteLinkedList`] | List with direct `first`/`last`/`size` access | //! | [`RelativeLinkedList`] | List with head-relative `first`/`last`/`size` | @@ -24,9 +24,8 @@ //! ## Quick start //! //! ```rust -//! use platform_trees::{ -//! LinkType, LinkedList, AbsoluteLinkedList, AbsoluteCircularLinkedList, -//! }; +//! use platform_trees::{LinkedList, AbsoluteLinkedList, AbsoluteCircularLinkedList}; +//! use platform_num::LinkReference; //! //! // 1. Define your storage //! #[derive(Default, Clone, Copy)] @@ -70,14 +69,13 @@ //! assert_eq!(list.get_last(), 2); //! ``` -mod link_type; mod lists; mod trees; -pub use link_type::LinkType; pub use lists::{ AbsoluteCircularLinkedList, AbsoluteLinkedList, LinkedList, RelativeCircularLinkedList, RelativeLinkedList, }; +pub use platform_num::LinkReference; pub use trees::{IterativeSizeBalancedTree, RecursiveSizeBalancedTree}; diff --git a/src/link_type.rs b/src/link_type.rs deleted file mode 100644 index 6eb4038..0000000 --- a/src/link_type.rs +++ /dev/null @@ -1,51 +0,0 @@ -use num_traits::{FromPrimitive, Unsigned}; -use platform_num::Number; -use std::convert::TryFrom; - -/// Trait for unsigned integer types that can serve as node indices -/// in trees and linked lists. -/// -/// `LinkType` combines [`Number`], [`Unsigned`], [`TryFrom`], and -/// [`FromPrimitive`] and adds a convenience [`funty`](LinkType::funty) -/// method for creating small constants. -/// -/// # Blanket implementation -/// -/// Every type that satisfies the supertraits automatically implements -/// `LinkType`, so standard unsigned types (`u8`, `u16`, `u32`, `u64`, -/// `usize`) work out of the box: -/// -/// ``` -/// use platform_trees::LinkType; -/// -/// assert_eq!(u32::funty(0), 0u32); -/// assert_eq!(u64::funty(1), 1u64); -/// assert_eq!(usize::funty(42), 42usize); -/// ``` -pub trait LinkType: Number + Unsigned + Sized + TryFrom + FromPrimitive { - /// Convert a `u8` value to `Self`. - /// - /// This is a convenience method used internally for zero, one, - /// and other small constants needed by tree and list algorithms. - /// - /// # Examples - /// - /// ``` - /// use platform_trees::LinkType; - /// - /// let zero = usize::funty(0); - /// let one = u32::funty(1); - /// assert_eq!(zero, 0); - /// assert_eq!(one, 1); - /// ``` - fn funty(n: u8) -> Self; -} - -impl + FromPrimitive> LinkType for T { - #[inline] - fn funty(n: u8) -> Self { - T::try_from(n).unwrap_or_else(|_| { - unreachable!("u8 conversion should always succeed for unsigned types") - }) - } -} diff --git a/src/lists/absolute_circular_linked_list.rs b/src/lists/absolute_circular_linked_list.rs index 3220827..0ef196f 100644 --- a/src/lists/absolute_circular_linked_list.rs +++ b/src/lists/absolute_circular_linked_list.rs @@ -1,4 +1,5 @@ -use crate::{AbsoluteLinkedList, LinkType}; +use crate::AbsoluteLinkedList; +use platform_num::LinkReference; /// Circular doubly-linked list with absolute (direct) head/tail access. /// @@ -8,7 +9,7 @@ use crate::{AbsoluteLinkedList, LinkType}; /// /// All methods have default implementations — an empty `impl` block /// is sufficient once [`AbsoluteLinkedList`] is implemented. -pub trait AbsoluteCircularLinkedList: AbsoluteLinkedList { +pub trait AbsoluteCircularLinkedList: AbsoluteLinkedList { /// Inserts `new_element` immediately before `base_element`. /// /// If `base_element` is the current first element, the first @@ -47,7 +48,7 @@ pub trait AbsoluteCircularLinkedList: AbsoluteLinkedList { /// with its previous and next pointers pointing to itself. fn attach_as_first(&mut self, element: T) { let first = self.get_first(); - if first == T::funty(0) { + if first == T::from_byte(0) { self.set_first(element); self.set_last(element); self.set_previous(element, element); @@ -63,7 +64,7 @@ pub trait AbsoluteCircularLinkedList: AbsoluteLinkedList { /// If the list is empty, delegates to [`attach_as_first`](Self::attach_as_first). fn attach_as_last(&mut self, element: T) { let last = self.get_last(); - if last == T::funty(0) { + if last == T::from_byte(0) { self.attach_as_first(element); } else { self.attach_after(last, element); @@ -73,13 +74,13 @@ pub trait AbsoluteCircularLinkedList: AbsoluteLinkedList { /// Removes `element` from the list. /// /// Updates head/tail pointers as needed and clears the element's - /// previous and next pointers to `T::funty(0)`. + /// previous and next pointers to `T::from_byte(0)`. fn detach(&mut self, element: T) { let element_previous = self.get_previous(element); let element_next = self.get_next(element); if element_next == element { - self.set_first(T::funty(0)); - self.set_last(T::funty(0)); + self.set_first(T::from_byte(0)); + self.set_last(T::from_byte(0)); } else { self.set_next(element_previous, element_next); self.set_previous(element_next, element_previous); @@ -90,8 +91,8 @@ pub trait AbsoluteCircularLinkedList: AbsoluteLinkedList { self.set_last(element_previous); } } - self.set_previous(element, T::funty(0)); - self.set_next(element, T::funty(0)); + self.set_previous(element, T::from_byte(0)); + self.set_next(element, T::from_byte(0)); self.dec_size(); } } diff --git a/src/lists/absolute_linked_list.rs b/src/lists/absolute_linked_list.rs index 245e9be..56be452 100644 --- a/src/lists/absolute_linked_list.rs +++ b/src/lists/absolute_linked_list.rs @@ -1,4 +1,5 @@ -use crate::{LinkType, LinkedList}; +use crate::LinkedList; +use platform_num::LinkReference; /// Linked list with direct (absolute) access to the first and last /// elements and a size counter. @@ -6,11 +7,11 @@ use crate::{LinkType, LinkedList}; /// This is typically used when a single list instance owns its own /// head/tail/size metadata. For multiple lists sharing the same /// storage, see [`RelativeLinkedList`](super::RelativeLinkedList). -pub trait AbsoluteLinkedList: LinkedList { - /// Returns the first element (head) of the list, or `T::funty(0)` if empty. +pub trait AbsoluteLinkedList: LinkedList { + /// Returns the first element (head) of the list, or `T::from_byte(0)` if empty. fn get_first(&self) -> T; - /// Returns the last element (tail) of the list, or `T::funty(0)` if empty. + /// Returns the last element (tail) of the list, or `T::from_byte(0)` if empty. fn get_last(&self) -> T; /// Returns the number of elements in the list. @@ -27,11 +28,11 @@ pub trait AbsoluteLinkedList: LinkedList { /// Increments the list size by one. fn inc_size(&mut self) { - self.set_size(self.get_size() + T::funty(1)); + self.set_size(self.get_size() + T::from_byte(1)); } /// Decrements the list size by one. fn dec_size(&mut self) { - self.set_size(self.get_size() - T::funty(1)); + self.set_size(self.get_size() - T::from_byte(1)); } } diff --git a/src/lists/linked_list.rs b/src/lists/linked_list.rs index 5408fc3..0f7b4e4 100644 --- a/src/lists/linked_list.rs +++ b/src/lists/linked_list.rs @@ -1,4 +1,4 @@ -use crate::LinkType; +use platform_num::LinkReference; /// Base doubly-linked list trait providing node-level navigation. /// @@ -28,7 +28,7 @@ use crate::LinkType; /// list.set_next(1, 2); /// assert_eq!(list.get_next(1), 2); /// ``` -pub trait LinkedList { +pub trait LinkedList { /// Returns the previous element of `element`. fn get_previous(&self, element: T) -> T; diff --git a/src/lists/relative_circular_linked_list.rs b/src/lists/relative_circular_linked_list.rs index ab12ac8..5e672b6 100644 --- a/src/lists/relative_circular_linked_list.rs +++ b/src/lists/relative_circular_linked_list.rs @@ -1,4 +1,5 @@ -use crate::{LinkType, RelativeLinkedList}; +use crate::RelativeLinkedList; +use platform_num::LinkReference; /// Circular doubly-linked list with head-relative positioning. /// @@ -8,7 +9,7 @@ use crate::{LinkType, RelativeLinkedList}; /// /// All methods have default implementations — an empty `impl` block /// is sufficient once [`RelativeLinkedList`] is implemented. -pub trait RelativeCircularLinkedList: RelativeLinkedList { +pub trait RelativeCircularLinkedList: RelativeLinkedList { /// Inserts `new_element` immediately before `base_element` in the /// list identified by `head`. fn attach_before(&mut self, head: T, base_element: T, new_element: T) { @@ -41,7 +42,7 @@ pub trait RelativeCircularLinkedList: RelativeLinkedList { /// by `head`. fn attach_as_first(&mut self, head: T, element: T) { let first = self.get_first(head); - if first == T::funty(0) { + if first == T::from_byte(0) { self.set_first(head, element); self.set_last(head, element); self.set_previous(element, element); @@ -56,7 +57,7 @@ pub trait RelativeCircularLinkedList: RelativeLinkedList { /// by `head`. fn attach_as_last(&mut self, head: T, element: T) { let last = self.get_last(head); - if last == T::funty(0) { + if last == T::from_byte(0) { self.attach_as_first(head, element); } else { self.attach_after(head, last, element); @@ -68,8 +69,8 @@ pub trait RelativeCircularLinkedList: RelativeLinkedList { let element_previous = self.get_previous(element); let element_next = self.get_next(element); if element_next == element { - self.set_first(head, T::funty(0)); - self.set_last(head, T::funty(0)); + self.set_first(head, T::from_byte(0)); + self.set_last(head, T::from_byte(0)); } else { self.set_next(element_previous, element_next); self.set_previous(element_next, element_previous); @@ -80,8 +81,8 @@ pub trait RelativeCircularLinkedList: RelativeLinkedList { self.set_last(head, element_previous); } } - self.set_previous(element, T::funty(0)); - self.set_next(element, T::funty(0)); + self.set_previous(element, T::from_byte(0)); + self.set_next(element, T::from_byte(0)); self.dec_size(head); } } diff --git a/src/lists/relative_doubly_linked_list.rs b/src/lists/relative_doubly_linked_list.rs index 189866e..d00c4f0 100644 --- a/src/lists/relative_doubly_linked_list.rs +++ b/src/lists/relative_doubly_linked_list.rs @@ -1,11 +1,12 @@ -use crate::{LinkType, LinkedList}; +use crate::LinkedList; +use platform_num::LinkReference; /// Linked list with head-relative access to first, last, and size. /// /// Unlike [`AbsoluteLinkedList`](super::AbsoluteLinkedList), this trait /// stores head/tail/size per `head` index, allowing multiple independent /// lists to share the same underlying node storage. -pub trait RelativeLinkedList: LinkedList { +pub trait RelativeLinkedList: LinkedList { /// Returns the first element of the list identified by `head`. fn get_first(&self, head: T) -> T; @@ -26,11 +27,11 @@ pub trait RelativeLinkedList: LinkedList { /// Increments the size of the list identified by `head` by one. fn inc_size(&mut self, head: T) { - self.set_size(head, self.get_size(head) + T::funty(1)); + self.set_size(head, self.get_size(head) + T::from_byte(1)); } /// Decrements the size of the list identified by `head` by one. fn dec_size(&mut self, head: T) { - self.set_size(head, self.get_size(head) - T::funty(1)); + self.set_size(head, self.get_size(head) - T::from_byte(1)); } } diff --git a/src/trees/iterative_size_balanced_tree.rs b/src/trees/iterative_size_balanced_tree.rs index 731d522..ae30aee 100644 --- a/src/trees/iterative_size_balanced_tree.rs +++ b/src/trees/iterative_size_balanced_tree.rs @@ -1,4 +1,5 @@ -use crate::{LinkType, RecursiveSizeBalancedTree}; +use crate::RecursiveSizeBalancedTree; +use platform_num::LinkReference; /// Extends [`RecursiveSizeBalancedTree`] with iterative `attach` and /// `detach` operations. @@ -15,15 +16,15 @@ use crate::{LinkType, RecursiveSizeBalancedTree}; /// /// All methods are `unsafe` — the caller must ensure that `root` points /// to a valid, writable location and that `node` indices are valid. -pub trait IterativeSizeBalancedTree: RecursiveSizeBalancedTree { +pub trait IterativeSizeBalancedTree: RecursiveSizeBalancedTree { /// Inserts `node` into the tree rooted at `*root`. /// /// If `*root` is zero (empty tree), `node` becomes the root with /// size 1. Otherwise the tree is rebalanced after insertion. unsafe fn attach(&mut self, root: *mut T, node: T) { unsafe { - if *root == T::funty(0) { - self.set_size(node, T::funty(1)); + if *root == T::from_byte(0) { + self.set_size(node, T::from_byte(1)); *root = node; return; } @@ -48,14 +49,14 @@ pub trait IterativeSizeBalancedTree: RecursiveSizeBalancedTree { let right = self.get_mut_right_reference(*root); let right_size = self.get_size_or_zero(*right); if self.first_is_to_the_left_of_second(node, *root) { - if *left == T::funty(0) { + if *left == T::from_byte(0) { self.inc_size(*root); - self.set_size(node, T::funty(1)); + self.set_size(node, T::from_byte(1)); *left = node; return; } if self.first_is_to_the_left_of_second(node, *left) { - if (left_size + T::funty(1)) > right_size { + if (left_size + T::from_byte(1)) > right_size { self.right_rotate(root); } else { self.inc_size(*root); @@ -63,13 +64,13 @@ pub trait IterativeSizeBalancedTree: RecursiveSizeBalancedTree { } } else { let left_right_size = self.get_size_or_zero(self.get_right(*left)); - if (left_right_size + T::funty(1)) > right_size { - if left_right_size == T::funty(0) && right_size == T::funty(0) { + if (left_right_size + T::from_byte(1)) > right_size { + if left_right_size == T::from_byte(0) && right_size == T::from_byte(0) { self.set_left(node, *left); self.set_right(node, *root); - self.set_size(node, left_size + T::funty(1) + T::funty(1)); - self.set_left(*root, T::funty(0)); - self.set_size(*root, T::funty(1)); + self.set_size(node, left_size + T::from_byte(1) + T::from_byte(1)); + self.set_left(*root, T::from_byte(0)); + self.set_size(*root, T::from_byte(1)); *root = node; return; } @@ -81,14 +82,14 @@ pub trait IterativeSizeBalancedTree: RecursiveSizeBalancedTree { } } } else { - if *right == T::funty(0) { + if *right == T::from_byte(0) { self.inc_size(*root); - self.set_size(node, T::funty(1)); + self.set_size(node, T::from_byte(1)); *right = node; return; } if self.first_is_to_the_right_of_second(node, *right) { - if (right_size + T::funty(1)) > left_size { + if (right_size + T::from_byte(1)) > left_size { self.left_rotate(root); } else { self.inc_size(*root); @@ -96,13 +97,13 @@ pub trait IterativeSizeBalancedTree: RecursiveSizeBalancedTree { } } else { let right_left_size = self.get_size_or_zero(self.get_left(*right)); - if (right_left_size + T::funty(1)) > left_size { - if right_left_size == T::funty(0) && left_size == T::funty(0) { + if (right_left_size + T::from_byte(1)) > left_size { + if right_left_size == T::from_byte(0) && left_size == T::from_byte(0) { self.set_left(node, *root); self.set_right(node, *right); - self.set_size(node, right_size + T::funty(1) + T::funty(1)); - self.set_right(*root, T::funty(0)); - self.set_size(*root, T::funty(1)); + self.set_size(node, right_size + T::from_byte(1) + T::from_byte(1)); + self.set_right(*root, T::from_byte(0)); + self.set_size(*root, T::from_byte(1)); *root = node; return; } @@ -126,7 +127,7 @@ pub trait IterativeSizeBalancedTree: RecursiveSizeBalancedTree { let right = self.get_mut_right_reference(*root); let right_size = self.get_size_or_zero(*right); if self.first_is_to_the_left_of_second(node, *root) { - let decremented_left_size = left_size - T::funty(1); + let decremented_left_size = left_size - T::from_byte(1); if self.get_size_or_zero(self.get_right_or_default(*right)) > decremented_left_size { @@ -141,7 +142,7 @@ pub trait IterativeSizeBalancedTree: RecursiveSizeBalancedTree { root = left; } } else if self.first_is_to_the_right_of_second(node, *root) { - let decremented_right_size = right_size - T::funty(1); + let decremented_right_size = right_size - T::from_byte(1); if self.get_size_or_zero(self.get_left_or_default(*left)) > decremented_right_size { @@ -156,7 +157,7 @@ pub trait IterativeSizeBalancedTree: RecursiveSizeBalancedTree { root = right; } } else { - if left_size > T::funty(0) && right_size > T::funty(0) { + if left_size > T::from_byte(0) && right_size > T::from_byte(0) { let replacement; if left_size > right_size { replacement = self.get_rightest(*left); @@ -169,12 +170,12 @@ pub trait IterativeSizeBalancedTree: RecursiveSizeBalancedTree { self.set_right(replacement, *right); self.set_size(replacement, left_size + right_size); *root = replacement; - } else if left_size > T::funty(0) { + } else if left_size > T::from_byte(0) { *root = *left; - } else if right_size > T::funty(0) { + } else if right_size > T::from_byte(0) { *root = *right; } else { - *root = T::funty(0); + *root = T::from_byte(0); } self.clear_node(node); return; diff --git a/src/trees/recursive_size_balanced_tree.rs b/src/trees/recursive_size_balanced_tree.rs index 819b5a9..794a9e5 100644 --- a/src/trees/recursive_size_balanced_tree.rs +++ b/src/trees/recursive_size_balanced_tree.rs @@ -1,4 +1,4 @@ -use crate::LinkType; +use platform_num::LinkReference; /// Base trait for a size-balanced binary search tree (SBT). /// @@ -17,7 +17,7 @@ use crate::LinkType; /// All methods are `unsafe` because they operate on raw node indices /// without bounds checking — the caller must ensure that every index /// passed to these methods refers to a valid, allocated node. -pub trait RecursiveSizeBalancedTree { +pub trait RecursiveSizeBalancedTree { /// Returns a mutable raw pointer to the left-child field of `node`. unsafe fn get_mut_left_reference(&mut self, node: T) -> *mut T; @@ -54,22 +54,22 @@ pub trait RecursiveSizeBalancedTree { /// Returns `true` if `first` should be placed to the right of `second`. unsafe fn first_is_to_the_right_of_second(&self, first: T, second: T) -> bool; - /// Returns the left child of `node`, or `T::funty(0)` if `node` is zero. + /// Returns the left child of `node`, or `T::from_byte(0)` if `node` is zero. unsafe fn get_left_or_default(&self, node: T) -> T { unsafe { - if node == T::funty(0) { - T::funty(0) + if node == T::from_byte(0) { + T::from_byte(0) } else { self.get_left(node) } } } - /// Returns the right child of `node`, or `T::funty(0)` if `node` is zero. + /// Returns the right child of `node`, or `T::from_byte(0)` if `node` is zero. unsafe fn get_right_or_default(&self, node: T) -> T { unsafe { - if node == T::funty(0) { - T::funty(0) + if node == T::from_byte(0) { + T::from_byte(0) } else { self.get_right(node) } @@ -79,8 +79,8 @@ pub trait RecursiveSizeBalancedTree { /// Returns the size of `node`, or zero if `node` is zero. unsafe fn get_size_or_zero(&self, node: T) -> T { unsafe { - if node == T::funty(0) { - T::funty(0) + if node == T::from_byte(0) { + T::from_byte(0) } else { self.get_size(node) } @@ -90,14 +90,14 @@ pub trait RecursiveSizeBalancedTree { /// Increments the subtree size of `node` by one. unsafe fn inc_size(&mut self, node: T) { unsafe { - self.set_size(node, self.get_size(node) + T::funty(1)); + self.set_size(node, self.get_size(node) + T::from_byte(1)); } } /// Decrements the subtree size of `node` by one. unsafe fn dec_size(&mut self, node: T) { unsafe { - self.set_size(node, self.get_size(node) - T::funty(1)); + self.set_size(node, self.get_size(node) - T::from_byte(1)); } } @@ -117,7 +117,7 @@ pub trait RecursiveSizeBalancedTree { unsafe { self.set_size( node, - (self.get_left_size(node) + self.get_right_size(node)) + T::funty(1), + (self.get_left_size(node) + self.get_right_size(node)) + T::from_byte(1), ); } } @@ -166,7 +166,7 @@ pub trait RecursiveSizeBalancedTree { unsafe fn get_rightest(&self, mut current: T) -> T { unsafe { let mut current_right = self.get_right(current); - while current_right != T::funty(0) { + while current_right != T::from_byte(0) { current = current_right; current_right = self.get_right(current); } @@ -178,7 +178,7 @@ pub trait RecursiveSizeBalancedTree { unsafe fn get_leftest(&self, mut current: T) -> T { unsafe { let mut current_left = self.get_left(current); - while current_left != T::funty(0) { + while current_left != T::from_byte(0) { current = current_left; current_left = self.get_left(current); } @@ -199,7 +199,7 @@ pub trait RecursiveSizeBalancedTree { /// Returns `true` if `node` exists in the tree rooted at `root`. unsafe fn contains(&self, node: T, mut root: T) -> bool { unsafe { - while root != T::funty(0) { + while root != T::from_byte(0) { if self.first_is_to_the_left_of_second(node, root) { root = self.get_left(root); } else if self.first_is_to_the_right_of_second(node, root) { @@ -215,9 +215,9 @@ pub trait RecursiveSizeBalancedTree { /// Resets `node`'s left, right, and size fields to zero. unsafe fn clear_node(&mut self, node: T) { unsafe { - self.set_left(node, T::funty(0)); - self.set_right(node, T::funty(0)); - self.set_size(node, T::funty(0)); + self.set_left(node, T::from_byte(0)); + self.set_right(node, T::from_byte(0)); + self.set_size(node, T::from_byte(0)); } } } diff --git a/tests/funty_compatibility.rs b/tests/funty_compatibility.rs index c0d5abc..d27dcfd 100644 --- a/tests/funty_compatibility.rs +++ b/tests/funty_compatibility.rs @@ -1,81 +1,66 @@ -// Experiment: Verify that removing the `funty` crate dependency from trees-rs -// does NOT break the public `funty()` method API. -// -// Key finding: The `funty` crate and the `funty()` method are different things. -// - `funty` crate: provides `funty::Unsigned` trait -// - `funty()` method: a convenience method on the `LinkType` trait for creating -// small integer values from u8 -// -// PR #9 removed the `funty` crate dependency but PRESERVED the `funty()` method -// on the `LinkType` trait. The `funty()` method now uses `num_traits::Unsigned` -// instead of `funty::Unsigned` for the trait bound, but the method signature -// and behavior are identical. -// -// This test demonstrates that the `funty()` method works correctly with all -// standard unsigned integer types used in downstream crates like doublets-rs. +// Verify that `from_byte()` (the replacement for the old `funty()` method) +// works correctly via `LinkReference` from `platform-num`. #[cfg(test)] mod tests { - use platform_trees::LinkType; + use platform_num::LinkReference; - /// Verify `T::funty(0)` works - used extensively in doublets-rs for null/zero checks. #[test] - fn test_funty_zero_all_types() { - assert_eq!(u8::funty(0), 0u8); - assert_eq!(u16::funty(0), 0u16); - assert_eq!(u32::funty(0), 0u32); - assert_eq!(u64::funty(0), 0u64); - assert_eq!(usize::funty(0), 0usize); + fn test_from_byte_zero_all_types() { + assert_eq!(u8::from_byte(0), 0u8); + assert_eq!(u16::from_byte(0), 0u16); + assert_eq!(u32::from_byte(0), 0u32); + assert_eq!(u64::from_byte(0), 0u64); + assert_eq!(u128::from_byte(0), 0u128); + assert_eq!(usize::from_byte(0), 0usize); } - /// Verify `T::funty(1)` works - used in doublets-rs for range starts. #[test] - fn test_funty_one_all_types() { - assert_eq!(u8::funty(1), 1u8); - assert_eq!(u16::funty(1), 1u16); - assert_eq!(u32::funty(1), 1u32); - assert_eq!(u64::funty(1), 1u64); - assert_eq!(usize::funty(1), 1usize); + fn test_from_byte_one_all_types() { + assert_eq!(u8::from_byte(1), 1u8); + assert_eq!(u16::from_byte(1), 1u16); + assert_eq!(u32::from_byte(1), 1u32); + assert_eq!(u64::from_byte(1), 1u64); + assert_eq!(u128::from_byte(1), 1u128); + assert_eq!(usize::from_byte(1), 1usize); } - /// Verify `T::funty(2)` works - used in data-rs for `default_target_part`. #[test] - fn test_funty_two_all_types() { - assert_eq!(u8::funty(2), 2u8); - assert_eq!(u16::funty(2), 2u16); - assert_eq!(u32::funty(2), 2u32); - assert_eq!(u64::funty(2), 2u64); - assert_eq!(usize::funty(2), 2usize); + fn test_from_byte_two_all_types() { + assert_eq!(u8::from_byte(2), 2u8); + assert_eq!(u16::from_byte(2), 2u16); + assert_eq!(u32::from_byte(2), 2u32); + assert_eq!(u64::from_byte(2), 2u64); + assert_eq!(u128::from_byte(2), 2u128); + assert_eq!(usize::from_byte(2), 2usize); } - /// Verify funty works in generic context - how doublets-rs actually uses it. - fn generic_funty_usage() -> (T, T, T) { - (T::funty(0), T::funty(1), T::funty(2)) + fn generic_from_byte_usage() -> (T, T, T) { + (T::from_byte(0), T::from_byte(1), T::from_byte(2)) } #[test] - fn test_generic_funty_usage() { - let (zero, one, two) = generic_funty_usage::(); + fn test_generic_from_byte_usage() { + let (zero, one, two) = generic_from_byte_usage::(); assert_eq!(zero, 0u32); assert_eq!(one, 1u32); assert_eq!(two, 2u32); - let (zero, one, two) = generic_funty_usage::(); + let (zero, one, two) = generic_from_byte_usage::(); assert_eq!(zero, 0u64); assert_eq!(one, 1u64); assert_eq!(two, 2u64); - let (zero, one, two) = generic_funty_usage::(); + let (zero, one, two) = generic_from_byte_usage::(); assert_eq!(zero, 0usize); assert_eq!(one, 1usize); assert_eq!(two, 2usize); } - /// Verify comparison patterns used in doublets-rs. #[test] - fn test_funty_comparison_patterns() { - fn check_null(value: T) -> bool { - value == T::funty(0) + fn test_from_byte_comparison_patterns() { + fn check_null(value: T) -> bool { + value == T::from_byte(0) } assert!(check_null(0u32)); @@ -84,15 +69,14 @@ mod tests { assert!(!check_null(42u64)); } - /// Verify arithmetic patterns used in trees-rs itself for `inc_size`/`dec_size`. #[test] - fn test_funty_arithmetic_patterns() { - fn inc_value(val: T) -> T { - val + T::funty(1) + fn test_from_byte_arithmetic_patterns() { + fn inc_value(val: T) -> T { + val + T::from_byte(1) } - fn dec_value(val: T) -> T { - val - T::funty(1) + fn dec_value(val: T) -> T { + val - T::from_byte(1) } assert_eq!(inc_value(5u32), 6u32); @@ -100,4 +84,14 @@ mod tests { assert_eq!(inc_value(0u64), 1u64); assert_eq!(dec_value(10u64), 9u64); } + + #[test] + fn test_link_reference_accepted_by_traits() { + fn accepts_link_reference(_val: T) {} + + accepts_link_reference(42u32); + accepts_link_reference(42u64); + accepts_link_reference(42usize); + accepts_link_reference(42u128); + } } diff --git a/tests/list_tests.rs b/tests/list_tests.rs index 9faeaf4..7049739 100644 --- a/tests/list_tests.rs +++ b/tests/list_tests.rs @@ -7,38 +7,38 @@ use platform_trees::{ }; // ============================================================================= -// LinkType trait tests +// LinkReference trait tests // ============================================================================= -mod link_type_tests { - use platform_trees::LinkType; +mod link_reference_tests { + use platform_num::LinkReference; #[test] - fn test_funty_zero() { - assert_eq!(usize::funty(0), 0usize); - assert_eq!(u8::funty(0), 0u8); - assert_eq!(u16::funty(0), 0u16); - assert_eq!(u32::funty(0), 0u32); - assert_eq!(u64::funty(0), 0u64); + fn test_from_byte_zero() { + assert_eq!(usize::from_byte(0), 0usize); + assert_eq!(u8::from_byte(0), 0u8); + assert_eq!(u16::from_byte(0), 0u16); + assert_eq!(u32::from_byte(0), 0u32); + assert_eq!(u64::from_byte(0), 0u64); } #[test] - fn test_funty_one() { - assert_eq!(usize::funty(1), 1usize); - assert_eq!(u8::funty(1), 1u8); - assert_eq!(u16::funty(1), 1u16); - assert_eq!(u32::funty(1), 1u32); - assert_eq!(u64::funty(1), 1u64); + fn test_from_byte_one() { + assert_eq!(usize::from_byte(1), 1usize); + assert_eq!(u8::from_byte(1), 1u8); + assert_eq!(u16::from_byte(1), 1u16); + assert_eq!(u32::from_byte(1), 1u32); + assert_eq!(u64::from_byte(1), 1u64); } #[test] - fn test_funty_various_values() { + fn test_from_byte_various_values() { for i in 0..=255u8 { - assert_eq!(u8::funty(i), i); - assert_eq!(u16::funty(i), u16::from(i)); - assert_eq!(u32::funty(i), u32::from(i)); - assert_eq!(u64::funty(i), u64::from(i)); - assert_eq!(usize::funty(i), i as usize); + assert_eq!(u8::from_byte(i), i); + assert_eq!(u16::from_byte(i), u16::from(i)); + assert_eq!(u32::from_byte(i), u32::from(i)); + assert_eq!(u64::from_byte(i), u64::from(i)); + assert_eq!(usize::from_byte(i), i as usize); } } }