Skip to content

Commit

Permalink
Guoweikang/linked list (#1)
Browse files Browse the repository at this point in the history
* 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
guoweikang authored Oct 22, 2024
1 parent 34c8db3 commit d18c1d0
Show file tree
Hide file tree
Showing 6 changed files with 976 additions and 747 deletions.
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

0 comments on commit d18c1d0

Please sign in to comment.