diff --git a/README.md b/README.md new file mode 100644 index 0000000..3233600 --- /dev/null +++ b/README.md @@ -0,0 +1,64 @@ +# LinkedList + + Linked lists that supports arbitrary removal in constant time. + + It is based on the linked list implementation in [Rust-for-Linux][1]. + + [1]: https://github.com/Rust-for-Linux/linux/blob/rust/rust/kernel/linked_list.rs + + In more general use cases, shoud not use [`RawList`] directly, + suggest use smart pointers of nodes and move ownership of smart + pointers to List. + +## Examples + + ```rust + use linked_list::{GetLinks, Links, List}; + + type InnerType = usize; + + pub struct ExampleNode { + pub inner: InnerType, + links: Links, + } + + impl GetLinks for ExampleNode { + type EntryType = Self; + + fn get_links(t: &Self) -> &Links { + &t.links + } + } + + impl ExampleNode { + fn new(inner: InnerType) -> Self { + Self { + inner, + links: Links::new() + } + } + + fn inner(&self) -> &InnerType { + &self.inner + } + } + + let node1 = Box::new(ExampleNode::new(0)); + let node2 = Box::new(ExampleNode::new(1)); + let mut list = List::>::new(); + + list.push_back(node1); + list.push_back(node2); + + //Support Iter + for (i,e) in list.iter().enumerate() { + assert!(*e.inner() == i); + } + + // Pop drop + assert!(*list.pop_front().unwrap().inner() == 0); + assert!(*list.pop_front().unwrap().inner() == 1); + + ``` + + diff --git a/src/lib.rs b/src/lib.rs index d8cd79b..9525c66 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,105 +1,22 @@ -//! Linked lists that supports arbitrary removal in constant time. -//! -//! It is based on the linked list implementation in [Rust-for-Linux][1]. -//! -//! [1]: https://github.com/Rust-for-Linux/linux/blob/rust/rust/kernel/linked_list.rs -//! -//! In more general use cases, shoud not use RawList directly, -//! suggest use smart pointers of nodes and move ownership of smart -//! pointers to List: -//! -//! ``` -//! use linked_list::{GetLinks, Links, List}; -//! -//! type InnerType = usize; -//! -//! pub struct ExampleNode { -//! pub inner: InnerType, -//! links: Links, -//! } -//! -//! impl GetLinks for ExampleNode { -//! type EntryType = Self; -//! -//! fn get_links(t: &Self) -> &Links { -//! &t.links -//! } -//! } -//! -//! impl ExampleNode { -//! fn new(inner: InnerType) -> Self { -//! Self { -//! inner, -//! links: Links::new() -//! } -//! } -//! -//! fn inner(&self) -> &InnerType { -//! &self.inner -//! } -//! } -//! -//! let node1 = Box::new(ExampleNode::new(0)); -//! let node2 = Box::new(ExampleNode::new(1)); -//! let mut list = List::>::new(); -//! -//! list.push_back(node1); -//! list.push_back(node2); -//! -//! //Support Iter -//! for (i,e) in list.iter().enumerate() { -//! assert!(*e.inner() == i); -//! } -//! -//! // Pop drop -//! assert!(*list.pop_front().unwrap().inner() == 0); -//! assert!(*list.pop_front().unwrap().inner() == 1); -//! -//! ``` -//! - #![cfg_attr(not(test), no_std)] +#![doc = include_str!("../README.md")] mod linked_list; mod raw_list; pub use linked_list::List; pub use raw_list::{GetLinks, Links}; -/// Defines a new node type that wraps an inner type and includes links for List. -/// -/// # Parameters -/// -/// - `struct_name`: The name of the struct to define. -/// - `type`: The inner type to wrap. -/// -/// # Example -/// -/// ```rust -/// use linked_list::{def_node, List}; -/// -/// def_node!(ExampleNode, usize); -/// -/// let node1 = Box::new(ExampleNode::new(0)); -/// let node2 = Box::new(ExampleNode::new(1)); -/// let mut list = List::>::new(); -/// -/// list.push_back(node1); -/// list.push_back(node2); -/// -/// for (i,e) in list.iter().enumerate() { -/// assert!(*e.inner() == i); -/// } -/// ``` -#[macro_export] -macro_rules! def_node { - ($struct_name:ident, $type:ty) => { - #[doc = "A node wrapper for inner type "] - pub struct $struct_name { +#[macro_export(local_inner_macros)] +#[doc(hidden)] +macro_rules! __def_node_internal { + ($(#[$meta:meta])* ($($vis:tt)*) struct $name:ident($type:ty);) => { + $(#[$meta])* + $($vis)* struct $name { inner: $type, links: $crate::Links, } - impl $crate::GetLinks for $struct_name { + impl $crate::GetLinks for $name { type EntryType = Self; #[inline] @@ -108,9 +25,9 @@ macro_rules! def_node { } } - impl $struct_name { + impl $name { #[doc = "Create a node"] - pub const fn new(inner: $type) -> Self { + $($vis)* const fn new(inner: $type) -> Self { Self { inner, links: $crate::Links::new(), @@ -119,12 +36,12 @@ macro_rules! def_node { #[inline] #[doc = "Get inner"] - pub const fn inner(&self) -> &$type { + $($vis)* const fn inner(&self) -> &$type { &self.inner } } - impl core::ops::Deref for $struct_name { + impl core::ops::Deref for $name { type Target = $type; #[inline] @@ -133,44 +50,15 @@ macro_rules! def_node { } } }; -} -/// Defines a generic node type that wraps a generic inner type and includes links -/// for List. -/// -/// Similar to [`def_node`], but inner type is generic Type -/// -/// # Parameters -/// -/// - `struct_name`: The name of the struct to define. -/// -/// # Example -/// -/// ```rust -/// use linked_list::{def_generic_node, List}; -/// def_generic_node!(GenericExampleNode); -/// -/// let node1 = Box::new(GenericExampleNode::new(0)); -/// let node2 = Box::new(GenericExampleNode::new(1)); -/// let mut list = List::>>::new(); -/// -/// list.push_back(node1); -/// list.push_back(node2); -/// -/// for (i,e) in list.iter().enumerate() { -/// assert!(*e.inner() == i); -/// } -/// ``` -#[macro_export] -macro_rules! def_generic_node { - ($struct_name:ident) => { - #[doc = "A node wrapper include a generic type"] - pub struct $struct_name { - inner: T, + ($(#[$meta:meta])* ($($vis:tt)*) struct $name:ident<$gen:ident>($type:ty); $($t:tt)*) => { + $(#[$meta])* + $($vis)* struct $name<$gen> { + inner: $type, links: $crate::Links, } - impl $crate::GetLinks for $struct_name { + impl<$gen> $crate::GetLinks for $name<$gen> { type EntryType = Self; #[inline] @@ -179,9 +67,9 @@ macro_rules! def_generic_node { } } - impl $struct_name { + impl<$gen> $name<$gen> { #[doc = "Create a node"] - pub const fn new(inner: T) -> Self { + $($vis)* const fn new(inner: $type) -> Self { Self { inner, links: $crate::Links::new(), @@ -190,13 +78,13 @@ macro_rules! def_generic_node { #[inline] #[doc = "Get inner"] - pub const fn inner(&self) -> &T { + $($vis)* const fn inner(&self) -> &$type { &self.inner } } - impl core::ops::Deref for $struct_name { - type Target = T; + impl<$gen> core::ops::Deref for $name<$gen> { + type Target = $type; #[inline] fn deref(&self) -> &Self::Target { @@ -205,3 +93,77 @@ macro_rules! def_generic_node { } }; } + +/// A macro for create a node type that can be used in List. +/// +/// # Syntax +/// +/// ```ignore +/// def_node! { +/// /// A node with usize value. +/// [pub] struct UsizedNode(usize); +/// /// A node with generic inner type. +/// [pub] struct WrapperNode(T); +/// } +/// ``` +/// +/// # Example +/// +/// ```rust +/// use linked_list::{def_node, List}; +/// +/// def_node!( +/// /// An example Node with usize +/// struct ExampleNode(usize); +/// /// An example Node with generic Inner type +/// struct GenericNode(T); +/// ); +/// +/// let node1 = Box::new(ExampleNode::new(0)); +/// let node2 = Box::new(ExampleNode::new(1)); +/// let mut list = List::>::new(); +/// +/// list.push_back(node1); +/// list.push_back(node2); +/// +/// for (i,e) in list.iter().enumerate() { +/// assert!(*e.inner() == i); +/// } +/// +/// let node1 = Box::new(GenericNode::new(0)); +/// let node2 = Box::new(GenericNode::new(1)); +/// let mut list = List::>>::new(); +/// +/// list.push_back(node1); +/// list.push_back(node2); +/// +/// for (i,e) in list.iter().enumerate() { +/// assert!(*e.inner() == i); +/// } +/// ``` +/// +#[macro_export(local_inner_macros)] +macro_rules! def_node { + ($(#[$meta:meta])* struct $name:ident($type:ty); $($t:tt)*) => { + __def_node_internal!($(#[$meta])* () struct $name($type);); + def_node!($($t)*); + + }; + ($(#[$meta:meta])* pub struct $name:ident($type:ty); $($t:tt)*) => { + __def_node_internal!($(#[$meta])* (pub) struct $name($type);$($t)*); + def_node!($($t)*); + + }; + + ($(#[$meta:meta])* struct $name:ident<$gen:ident>($type:ty); $($t:tt)*) => { + __def_node_internal!($(#[$meta])* () struct $name<$gen>($type); $($t)*); + def_node!($($t)*); + + }; + ($(#[$meta:meta])* pub struct $name:ident<$gen:ident>($type:ty); $($t:tt)*) => { + __def_node_internal!($(#[$meta])* (pub) struct $name<$gen>($type);$($t)*); + def_node!($($t)*); + + }; + () => () +} diff --git a/src/linked_list.rs b/src/linked_list.rs index b963a43..1f4b9fb 100644 --- a/src/linked_list.rs +++ b/src/linked_list.rs @@ -97,6 +97,8 @@ where impl GetLinks for Box { type EntryType = T::EntryType; + + #[inline] fn get_links(data: &Self::EntryType) -> &Links { ::get_links(data) } @@ -224,7 +226,7 @@ pub struct CursorMut<'a, G: GetLinksWrapped> { } impl<'a, G: GetLinksWrapped> CursorMut<'a, G> { - fn new(cursor: raw_list::CursorMut<'a, G>) -> Self { + const fn new(cursor: raw_list::CursorMut<'a, G>) -> Self { Self { cursor } }