Skip to content

Commit 92865de

Browse files
committed
start linked_list example, add multiple items to start_proj
1 parent af6c0ea commit 92865de

File tree

2 files changed

+111
-9
lines changed

2 files changed

+111
-9
lines changed

examples/linked_list.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
use std::{marker::PhantomData, ptr::NonNull};
2+
3+
use field_projection::compat::{HasFields, p, start_proj};
4+
5+
#[derive(HasFields)]
6+
struct ListItem<T> {
7+
next: NonNull<ListItem<T>>,
8+
prev: NonNull<ListItem<T>>,
9+
value: T,
10+
}
11+
12+
impl<T> ListItem<T> {
13+
fn new(prev: NonNull<Self>, next: NonNull<Self>, value: T) -> NonNull<Self> {
14+
NonNull::from(Box::leak(Box::new(Self { prev, next, value })))
15+
}
16+
}
17+
18+
pub struct List<T> {
19+
first: Option<NonNull<ListItem<T>>>,
20+
}
21+
22+
impl<T> List<T> {
23+
pub fn new() -> Self {
24+
Self { first: None }
25+
}
26+
27+
/*
28+
pub fn push_front(&mut self, item: T) {
29+
let new = ListItem {
30+
next: self.first.take(),
31+
prev: None,
32+
value: item,
33+
};
34+
self.first = Some(NonNull::from(Box::leak(Box::new(new))));
35+
}
36+
37+
pub fn push_back(&mut self, item: T) {}
38+
*/
39+
40+
pub fn cursor(&mut self) -> Option<Cursor<'_, T>> {
41+
self.first.map(|cur| Cursor {
42+
cur,
43+
_lt: PhantomData,
44+
})
45+
}
46+
}
47+
48+
pub struct Cursor<'a, T> {
49+
cur: NonNull<ListItem<T>>,
50+
_lt: PhantomData<&'a mut T>,
51+
}
52+
53+
impl<T> Cursor<'_, T> {
54+
pub fn insert_left(&mut self, item: T) {
55+
let cur = self.cur;
56+
let (prev, next) = (unsafe { (*cur.as_ptr()).prev }, cur);
57+
let new = ListItem::new(prev, cur, item);
58+
unsafe { (*prev.as_ptr()).next = new };
59+
unsafe { (*next.as_ptr()).prev = new };
60+
}
61+
62+
pub fn insert_right(&mut self, item: T) {
63+
start_proj!(let cur = self.cur);
64+
start_proj!(let prev = cur; let next = unsafe { p!(@cur->next).read() });
65+
let new = ListItem::new(prev, cur, item);
66+
unsafe { p!(@prev->next).write(new) };
67+
unsafe { p!(@next->prev).write(new) };
68+
self.cur = new;
69+
}
70+
71+
pub fn current(&mut self) -> &mut T {
72+
unsafe { &mut (*self.cur.as_ptr()).value }
73+
}
74+
}
75+
76+
fn main() {}

internal/src/start.rs

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
use proc_macro2::TokenStream;
22
use quote::{ToTokens, format_ident, quote};
3-
use syn::{Result, Token, parse::Parse};
3+
use syn::{Expr, Result, Token, parse::Parse, punctuated::Punctuated};
44

55
use crate::IdentOrSelf;
66

77
pub struct Input {
8+
input: Punctuated<Entry, Token![;]>,
9+
}
10+
11+
struct Entry {
12+
let_: Option<Token![let]>,
813
kind: ProjKind,
914
name: IdentOrSelf,
15+
equals: Option<Token![=]>,
16+
value: Option<Expr>,
1017
}
1118

12-
pub enum ProjKind {
19+
enum ProjKind {
1320
Shared,
1421
Mut(Token![mut]),
1522
Move(Token![move]),
@@ -39,36 +46,55 @@ impl ToTokens for ProjKind {
3946

4047
impl Parse for Input {
4148
fn parse(input: syn::parse::ParseStream) -> Result<Self> {
49+
Punctuated::parse_terminated(input).map(|input| Self { input })
50+
}
51+
}
52+
53+
impl Parse for Entry {
54+
fn parse(input: syn::parse::ParseStream) -> Result<Self> {
55+
let let_: Option<Token![let]> = input.parse()?;
56+
let has_let = let_.is_some();
4257
let res = Self {
58+
let_,
4359
kind: input.parse()?,
4460
name: input.parse()?,
61+
equals: has_let.then(|| input.parse()).transpose()?,
62+
value: has_let.then(|| input.parse()).transpose()?,
4563
};
46-
if !input.is_empty() {
47-
return Err(input.error("unexpected tokens"));
48-
}
4964
Ok(res)
5065
}
5166
}
5267

53-
pub fn expand(
54-
Input {
68+
pub fn expand(input: Input) -> TokenStream {
69+
input.input.into_iter().map(expand_one).collect()
70+
}
71+
72+
fn expand_one(
73+
Entry {
74+
let_,
5575
kind,
5676
name: IdentOrSelf(name),
57-
}: Input,
77+
equals,
78+
value,
79+
}: Entry,
5880
) -> TokenStream {
81+
let let_ = let_.unwrap_or_default();
82+
let equals = equals.unwrap_or_default();
5983
let projections = format_ident!("___projections_checker_for_{name}");
6084
let raw_ = format_ident!("___projections_raw_ptr_for_{name}");
6185
let (start, mut_, action) = match &kind {
6286
ProjKind::Move(_) => (quote!(__start_proj_move), quote!(), quote!()),
6387
ProjKind::Mut(mut_) => (quote!(__start_proj_mut), quote!(#mut_), quote!(&#mut_)),
6488
ProjKind::Shared => (quote!(__start_proj), quote!(), quote!(&)),
6589
};
90+
let before = value.map(|value| quote!(#let_ #mut_ #name = #value;));
6691
let (rest, raw_mut) = match &kind {
6792
ProjKind::Move(_) => (quote!(let #raw_ = &raw mut #raw_;), quote!(mut)),
6893
_ => (quote!(), quote!()),
6994
};
7095
quote! {
71-
let (#mut_ #projections, #raw_mut #raw_) = ::field_projection::compat::#start(#action #name);
96+
#before
97+
#let_ (#mut_ #projections, #raw_mut #raw_) #equals ::field_projection::compat::#start(#action #name);
7298
#rest
7399
}
74100
}

0 commit comments

Comments
 (0)