Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Guoweikang/linked list #1

Merged
merged 25 commits into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
afc15de
Synchronize r4l linked_lists latest code
guoweikang Oct 14, 2024
db2898d
Update LinkedList to make it easier to use
guoweikang Oct 15, 2024
16b3073
remove unused unsafe_list source code
guoweikang Oct 15, 2024
3d826d9
add macro def_node and def_generic_node
guoweikang Oct 15, 2024
5a3f0c4
fix clippy warnning
guoweikang Oct 15, 2024
b8fb68b
fix doc warning
guoweikang Oct 15, 2024
aa5cb4c
add inner() func for node
guoweikang Oct 15, 2024
6f38819
create tag and update version
guoweikang Oct 15, 2024
e01115f
add doc for pub func
guoweikang Oct 16, 2024
d5641a7
inner not a pub filed, use inner() api access
guoweikang Oct 16, 2024
deaebf9
Add DOC and example for def_node macro
guoweikang Oct 17, 2024
5d853ff
use const fn for inner and is_empty
guoweikang Oct 18, 2024
02e5d46
macro def_node with new format
guoweikang Oct 21, 2024
58a879b
remove unsed description
guoweikang Oct 21, 2024
606187d
support pub(crate) for def_node
guoweikang Oct 21, 2024
33d763c
use const for more func
guoweikang Oct 21, 2024
c2c3542
use vis in macro
guoweikang Oct 21, 2024
d66aa7e
Add CI DOC for linked list
guoweikang Oct 22, 2024
907953b
modify crates-io package name from linked_list to linked_list_r4l
guoweikang Oct 22, 2024
0cc8710
fix cargo fmt
guoweikang Oct 22, 2024
f714731
fix unitest fail
guoweikang Oct 22, 2024
d289a96
update package version to 0.2.0
guoweikang Oct 22, 2024
3509ccf
use vis in _def_node_inernal
guoweikang Oct 22, 2024
325bf0a
rename repo to linked_list_r4l
guoweikang Oct 22, 2024
793fdcc
remove const fn for into_innner
guoweikang Oct 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions Cargo.toml
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]
64 changes: 64 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# LinkedList

[![Crates.io](https://img.shields.io/crates/v/linked_list_r4l)](https://crates.io/crates/linked_list_r4l)
[![Doc.rs](https://docs.rs/linked_list_r4l/badge.svg)](https://docs.rs/linked_list_r4l)
[![CI](https://github.com/arceos-org/linked_list_r4l/actions/workflows/ci.yml/badge.svg?branch=main)](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);

```


184 changes: 174 additions & 10 deletions src/lib.rs
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)*);
};
() => ()
}
Loading