-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Synchronize r4l linked_lists latest code, update to v0.2.0 -------- 1 Add List sample code 2 Add more test case 3 Remove iter_back, can directly use iter().rev() 4 Add def_node to make it easier to use 5 remove unused unsafe_list source code 6 node support innner() and into_inner() 7 Directly use vis in macro 8 Repo name from linked_list to linked_list_r4l 8 Linked list push to crates-io and update to v0.2.0 Signed-off-by: guoweikang <[email protected]>
- Loading branch information
1 parent
34c8db3
commit d18c1d0
Showing
6 changed files
with
976 additions
and
747 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,14 @@ | ||
[package] | ||
name = "linked_list" | ||
version = "0.1.0" | ||
name = "linked_list_r4l" | ||
version = "0.2.0" | ||
edition = "2021" | ||
authors = ["Wedson Almeida Filho <[email protected]>"] | ||
authors = ["Wedson Almeida Filho <[email protected]>", "WeiKang Guo <[email protected]>"] | ||
description = "Linked lists that supports arbitrary removal in constant time" | ||
license = "GPL-2.0-or-later" | ||
homepage = "https://github.com/arceos-org/arceos" | ||
repository = "https://github.com/arceos-org/linked_list" | ||
documentation = "https://arceos-org.github.io/linked_list" | ||
repository = "https://github.com/arceos-org/linked_list_r4l" | ||
documentation = "https://docs.rs/linked_list_r4l" | ||
keywords = ["list"] | ||
categories = ["no-std", "rust-patterns"] | ||
|
||
[dependencies] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
# LinkedList | ||
|
||
[](https://crates.io/crates/linked_list_r4l) | ||
[](https://docs.rs/linked_list_r4l) | ||
[](https://github.com/arceos-org/linked_list_r4l/actions/workflows/ci.yml) | ||
|
||
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 | ||
|
||
## Examples | ||
|
||
```rust | ||
use linked_list_r4l::{GetLinks, Links, List}; | ||
|
||
type InnerType = usize; | ||
|
||
pub struct ExampleNode { | ||
pub inner: InnerType, | ||
links: Links<Self>, | ||
} | ||
|
||
impl GetLinks for ExampleNode { | ||
type EntryType = Self; | ||
|
||
fn get_links(t: &Self) -> &Links<Self> { | ||
&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::<Box<ExampleNode>>::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); | ||
|
||
``` | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,178 @@ | ||
//! 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 | ||
#![no_std] | ||
#![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}; | ||
|
||
#[macro_export(local_inner_macros)] | ||
#[doc(hidden)] | ||
macro_rules! __def_node_internal { | ||
($(#[$meta:meta])* $vis:vis struct $name:ident($type:ty);) => { | ||
$(#[$meta])* | ||
$vis struct $name { | ||
inner: $type, | ||
links: $crate::Links<Self>, | ||
} | ||
|
||
impl $crate::GetLinks for $name { | ||
type EntryType = Self; | ||
|
||
#[inline] | ||
fn get_links(t: &Self) -> &$crate::Links<Self> { | ||
&t.links | ||
} | ||
} | ||
|
||
impl $name { | ||
#[doc = "Create a node"] | ||
pub const fn new(inner: $type) -> Self { | ||
Self { | ||
inner, | ||
links: $crate::Links::new(), | ||
} | ||
} | ||
|
||
#[inline] | ||
#[doc = "Return the referece of wrapped inner"] | ||
pub const fn inner(&self) -> &$type { | ||
&self.inner | ||
} | ||
|
||
#[inline] | ||
#[doc = "Consumes the `node`, returning the wrapped inner"] | ||
pub fn into_inner(self) -> $type { | ||
self.inner | ||
} | ||
} | ||
|
||
impl core::ops::Deref for $name { | ||
type Target = $type; | ||
|
||
#[inline] | ||
fn deref(&self) -> &Self::Target { | ||
&self.inner | ||
} | ||
} | ||
}; | ||
|
||
($(#[$meta:meta])* $vis:vis struct $name:ident<$gen:ident>($type:ty);) => { | ||
$(#[$meta])* | ||
$vis struct $name<$gen> { | ||
inner: $type, | ||
links: $crate::Links<Self>, | ||
} | ||
|
||
impl<$gen> $crate::GetLinks for $name<$gen> { | ||
type EntryType = Self; | ||
|
||
#[inline] | ||
fn get_links(t: &Self) -> &$crate::Links<Self> { | ||
&t.links | ||
} | ||
} | ||
|
||
impl<$gen> $name<$gen> { | ||
#[doc = "Create a node"] | ||
pub const fn new(inner: $type) -> Self { | ||
Self { | ||
inner, | ||
links: $crate::Links::new(), | ||
} | ||
} | ||
|
||
#[inline] | ||
#[doc = "Return the referece of wrapped inner"] | ||
pub const fn inner(&self) -> &$type { | ||
&self.inner | ||
} | ||
|
||
#[inline] | ||
#[doc = "Consumes the `node`, returning the wrapped inner"] | ||
pub fn into_inner(self) -> $type { | ||
self.inner | ||
} | ||
} | ||
|
||
impl<$gen> core::ops::Deref for $name<$gen> { | ||
type Target = $type; | ||
|
||
pub mod unsafe_list; | ||
#[inline] | ||
fn deref(&self) -> &Self::Target { | ||
&self.inner | ||
} | ||
} | ||
}; | ||
} | ||
|
||
pub use self::linked_list::{AdapterWrapped, List, Wrapper}; | ||
pub use unsafe_list::{Adapter, Cursor, Links}; | ||
/// 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>(T); | ||
/// } | ||
/// ``` | ||
/// | ||
/// # Example | ||
/// | ||
/// ```rust | ||
/// use linked_list_r4l::{def_node, List}; | ||
/// | ||
/// def_node!{ | ||
/// /// An example Node with usize | ||
/// struct ExampleNode(usize); | ||
/// /// An example Node with generic Inner type and pub(crate) | ||
/// pub(crate) struct NativeGenericNode(usize); | ||
/// /// An example Node with generic Inner type and pub vis | ||
/// pub struct GenericNode<T>(T); | ||
/// } | ||
/// | ||
/// let node1 = Box::new(ExampleNode::new(0)); | ||
/// let node2 = Box::new(ExampleNode::new(1)); | ||
/// let mut list = List::<Box<ExampleNode>>::new(); | ||
/// | ||
/// list.push_back(node1); | ||
/// list.push_back(node2); | ||
/// | ||
/// for (i,e) in list.iter().enumerate() { | ||
/// assert!(*e.inner() == i); | ||
/// } | ||
/// | ||
/// let node1 = list.pop_front().unwrap(); | ||
/// let node2 = list.pop_front().unwrap(); | ||
/// | ||
/// assert!(node1.into_inner() == 0); | ||
/// assert!(node2.into_inner() == 1); | ||
/// assert!(list.pop_front().is_none()); | ||
/// | ||
/// let node1 = Box::new(GenericNode::new(0)); | ||
/// let node2 = Box::new(GenericNode::new(1)); | ||
/// | ||
/// let mut list = List::<Box<GenericNode<usize>>>::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])* $vis:vis struct $name:ident($type:ty); $($t:tt)*) => { | ||
__def_node_internal!($(#[$meta])* $vis struct $name($type);); | ||
def_node!($($t)*); | ||
}; | ||
($(#[$meta:meta])* $vis:vis struct $name:ident<$gen:ident>($type:ty); $($t:tt)*) => { | ||
__def_node_internal!($(#[$meta])* $vis struct $name<$gen>($type);); | ||
def_node!($($t)*); | ||
}; | ||
() => () | ||
} |
Oops, something went wrong.