Skip to content

Commit f721ea3

Browse files
committed
WIP multiple prefix
1 parent a629f73 commit f721ea3

File tree

6 files changed

+113
-25
lines changed

6 files changed

+113
-25
lines changed

protocol-derive/src/codegen/mod.rs

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
pub mod enums;
22

33
use crate::attr;
4-
use proc_macro2::TokenStream;
4+
use proc_macro2::{TokenStream, Ident};
55
use syn;
6+
use syn::Field;
67

78
pub fn read_fields(fields: &syn::Fields)
89
-> TokenStream {
@@ -31,10 +32,11 @@ fn read_named_fields(fields_named: &syn::FieldsNamed)
3132
-> TokenStream {
3233
let field_initializers: Vec<_> = fields_named.named.iter().map(|field| {
3334
let field_name = &field.ident;
35+
println!("READING NAMED FIELD {:?}", field_name);
3436
let field_ty = &field.ty;
35-
// This field may store the length prefix of another field.
37+
// This field may store the length prefix of one or more other field.
3638
let update_hints = update_hints_after_read(field, &fields_named.named);
37-
let update_hints_fixed = update_hints__fixed_after_read(field, &fields_named.named);
39+
let update_hints_fixed = update_hint_fixed_length(field, &fields_named.named);
3840

3941
quote! {
4042
#field_name : {
@@ -55,9 +57,12 @@ fn update_hints_after_read<'a>(field: &'a syn::Field,
5557
-> TokenStream {
5658
if let Some((length_prefix_of, kind, prefix_subfield_names)) = length_prefix_of(field, fields.clone()) {
5759
let kind = kind.path_expr();
58-
60+
let field_name = &field.ident.clone().map(|i| i.to_string());
61+
let debug = (field_name, &length_prefix_of, &kind, &prefix_subfield_names);
62+
println!("About to set hints for {:?}, of_index : {:?}, subfield names {:?}", field_name, &length_prefix_of, &prefix_subfield_names);
5963
quote! {
6064
if let Ok(parcel) = res.as_ref() {
65+
println!(" setting {:?} fields hint {:?}, {:?}, {:?}",#field_name, #length_prefix_of, (parcel #(.#prefix_subfield_names)* ).clone() as usize, #kind);
6166
__hints.set_field_length(#length_prefix_of,
6267
(parcel #(.#prefix_subfield_names)* ).clone() as usize,
6368
#kind);
@@ -68,9 +73,9 @@ fn update_hints_after_read<'a>(field: &'a syn::Field,
6873
}
6974
}
7075

71-
fn update_hints__fixed_after_read<'a>(field: &'a syn::Field,
72-
fields: impl IntoIterator<Item=&'a syn::Field> + Clone)
73-
-> TokenStream {
76+
fn update_hint_fixed_length<'a>(field: &'a syn::Field,
77+
fields: impl IntoIterator<Item=&'a syn::Field> + Clone)
78+
-> TokenStream {
7479

7580
if let Some(attr::Protocol::FixedLength(length)) = attr::protocol(&field.attrs) {
7681
let position = fields.clone().into_iter().position(|f| f == field).unwrap();
@@ -89,8 +94,10 @@ fn update_hints_after_write<'a>(field: &'a syn::Field,
8994
if let Some((length_prefix_of, kind, prefix_subfield_names)) = length_prefix_of(field, fields.clone()) {
9095
let field_name = &field.ident;
9196
let kind = kind.path_expr();
92-
97+
let debug = (&field.ident.clone().map(|i| i.to_string()), &length_prefix_of, &kind, &prefix_subfield_names);
98+
println!("About setting hints for {:?}", debug);
9399
quote! {
100+
println!(" WRITE setting {:?} fields hint {:?}, {:?}",self.#field_name #(.#prefix_subfield_names)*, #length_prefix_of, #kind);
94101
if let Ok(()) = res {
95102
__hints.set_field_length(#length_prefix_of,
96103
(self.#field_name #(.#prefix_subfield_names)* ).clone() as usize,
@@ -110,10 +117,10 @@ fn update_hints_after_write<'a>(field: &'a syn::Field,
110117
/// Returns the field index of the field whose length is specified.
111118
fn length_prefix_of<'a>(field: &'a syn::Field,
112119
fields: impl IntoIterator<Item=&'a syn::Field> + Clone)
113-
-> Option<(usize, attr::LengthPrefixKind, Vec<syn::Ident>)> {
120+
-> Option<Vec<(usize, attr::LengthPrefixKind, Vec<syn::Ident>)>> {
114121
let potential_prefix = field.ident.as_ref();
115122

116-
let prefix_of = fields.clone().into_iter().find(|potential_prefix_of| {
123+
let prefixes_of: Vec<&Ident> = fields.clone().into_iter().filter(|potential_prefix_of| {
117124
match attr::protocol(&potential_prefix_of.attrs) {
118125
Some(attr::Protocol::LengthPrefix { ref prefix_field_name, .. }) => {
119126
if !fields.clone().into_iter().any(|f| f.ident.as_ref() == Some(prefix_field_name)) {
@@ -124,19 +131,23 @@ fn length_prefix_of<'a>(field: &'a syn::Field,
124131
},
125132
_ => false,
126133
}
127-
});
134+
}).collect();
128135

129-
if let Some(prefix_of) = prefix_of {
130-
let prefix_of_index = fields.clone().into_iter().position(|f| f == prefix_of).unwrap();
131-
match attr::protocol(&prefix_of.attrs).unwrap() {
132-
attr::Protocol::LengthPrefix { kind, prefix_subfield_names, .. } => {
133-
Some((prefix_of_index, kind.clone(), prefix_subfield_names))
134-
},
135-
_ => unreachable!(),
136-
}
137-
} else {
138-
None
139-
}
136+
137+
prefixes_of.iter()
138+
.map(|prefix_of| {
139+
if let Some(prefix_of) = prefix_of {
140+
let prefix_of_index = fields.clone().into_iter().position(|f| f == prefix_of).unwrap();
141+
match attr::protocol(&prefix_of.attrs).unwrap() {
142+
attr::Protocol::LengthPrefix { kind, prefix_subfield_names, .. } => {
143+
Some((prefix_of_index, kind.clone(), prefix_subfield_names))
144+
},
145+
_ => unreachable!(),
146+
}
147+
} else {
148+
None
149+
}
150+
}).flatten().collect()
140151
}
141152

142153
fn write_named_fields(fields_named: &syn::FieldsNamed)
@@ -145,8 +156,9 @@ fn write_named_fields(fields_named: &syn::FieldsNamed)
145156
let field_name = &field.ident;
146157
// This field may store the length prefix of another field.
147158
let update_hints = update_hints_after_write(field, &fields_named.named);
148-
let update_hints_fixed = update_hints__fixed_after_read(field, &fields_named.named);
159+
let update_hints_fixed = update_hint_fixed_length(field, &fields_named.named);
149160

161+
println!("WRITE Hints after ");
150162
quote! {
151163
{
152164
#update_hints_fixed

protocol-derive/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,9 @@ fn build_generics(ast: &syn::DeriveInput) -> (Vec<proc_macro2::TokenStream>, Vec
7373
fn impl_parcel_for_struct(ast: &syn::DeriveInput,
7474
strukt: &syn::DataStruct) -> proc_macro2::TokenStream {
7575
let strukt_name = &ast.ident;
76+
println!("Reading struct fields {:?}", &strukt.fields);
7677
let read_fields = codegen::read_fields(&strukt.fields);
78+
println!("{}", read_fields);
7779
let write_fields = codegen::write_fields(&strukt.fields);
7880

7981
impl_trait_for(ast, quote!(protocol::Parcel), quote! {
@@ -84,6 +86,7 @@ fn impl_parcel_for_struct(ast: &syn::DeriveInput,
8486
__settings: &protocol::Settings,
8587
_: &mut protocol::hint::Hints)
8688
-> Result<Self, protocol::Error> {
89+
println!("reading fields with default Hints");
8790
// Each type gets its own hints.
8891
let mut __hints = protocol::hint::Hints::default();
8992
__hints.begin_fields();

protocol/src/hint.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@ impl Hints {
4141
/// Gets the length of the field currently being
4242
/// read, if known.
4343
pub fn current_field_length(&self) -> Option<FieldLength> {
44-
self.current_field_index.and_then(|index| self.known_field_lengths.get(&index)).cloned()
44+
println!("Getting current field length");
45+
let maybe_length = self.current_field_index.and_then(|index| self.known_field_lengths.get(&index)).cloned();
46+
println!("Got {:?}", maybe_length);
47+
maybe_length
4548
}
4649
}
4750

@@ -53,12 +56,14 @@ mod protocol_derive_helpers {
5356
// Sets hints indicating a new set of fields are beginning.
5457
#[doc(hidden)]
5558
pub fn begin_fields(&mut self) {
59+
println!("Starting from field 0");
5660
self.current_field_index = Some(0);
5761
}
5862

5963
// Updates the hints to indicate a field was just read.
6064
#[doc(hidden)]
6165
pub fn next_field(&mut self) {
66+
println!("Current field +1");
6267
*self.current_field_index.as_mut()
6368
.expect("cannot increment next field when not in a struct")+= 1;
6469
}
@@ -69,6 +74,7 @@ mod protocol_derive_helpers {
6974
field_index: FieldIndex,
7075
length: usize,
7176
kind: LengthPrefixKind) {
77+
println!("Set field length {:?}", (field_index, length, kind));
7278
self.known_field_lengths.insert(field_index, FieldLength { kind, length });
7379
}
7480
}

protocol/src/types/vec.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ mod std_vec {
4949
fn read_field(read: &mut dyn Read,
5050
settings: &Settings,
5151
hints: &mut hint::Hints) -> Result<Self, Error> {
52+
println!("Vec hints {:?}", hints);
5253
util::read_list(read, settings, hints)
5354
}
5455

protocol/src/util.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ pub fn read_list<T>(read: &mut dyn Read,
5353
hints: &mut hint::Hints)
5454
-> Result<Vec<T>, Error>
5555
where T: Parcel {
56+
println!("read predixed list with hints -> {:?}", hints);
5657
self::read_list_ext::<SizeType, T>(read, settings, hints)
5758
}
5859

@@ -74,6 +75,7 @@ pub fn read_list_ext<S,T>(read: &mut dyn Read,
7475
-> Result<Vec<T>, Error>
7576
where S: Integer,
7677
T: Parcel {
78+
println!("About to read list ext with prefix and hint {:?}", hints);
7779
match hints.current_field_length() {
7880
Some(length) => {
7981
match length.kind {
@@ -102,6 +104,7 @@ pub fn read_list_ext<S,T>(read: &mut dyn Read,
102104
Ok(items)
103105
},
104106
hint::LengthPrefixKind::Elements => {
107+
println!("Reading \"Element Kind\" with length : {:?}", length.length);
105108
read_items(length.length, read, settings).map(|i| i.collect())
106109
},
107110
}

tests/src/length_prefix.rs

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,33 @@ pub struct WithElementsLength {
2929
pub data: Vec<u32>,
3030
}
3131

32+
#[derive(Protocol, Debug, PartialEq, Eq)]
33+
pub struct WithTwoPrefix {
34+
pub count: u32,
35+
pub count_2: u32,
36+
pub foo: bool,
37+
#[protocol(length_prefix(elements(count)))]
38+
pub data: Vec<u32>,
39+
#[protocol(length_prefix(elements(count_2)))]
40+
pub data_2: Vec<u32>,
41+
}
42+
43+
#[derive(Protocol, Debug, PartialEq, Eq)]
44+
pub struct WithElementsLengthUsedTwice {
45+
pub count: u32,
46+
pub foo: bool,
47+
#[protocol(length_prefix(elements(count)))]
48+
pub data_1: Vec<u32>,
49+
#[protocol(length_prefix(elements(count)))]
50+
pub data_2: Vec<u32>,
51+
}
52+
3253
#[derive(Protocol, Debug, PartialEq, Eq)]
3354
pub struct WithFixedLength {
3455
#[protocol(fixed_length(3))]
3556
pub data: Vec<u32>,
3657
}
3758

38-
3959
#[test]
4060
fn can_read_length_prefix_5_bytes_string() {
4161
assert_eq!(Foo {
@@ -70,6 +90,49 @@ fn can_read_length_prefix_3_elements() {
7090
&Settings::default()).unwrap());
7191
}
7292

93+
#[test]
94+
fn can_read_twice_the_same_prefix_length() {
95+
assert_eq!(WithElementsLengthUsedTwice {
96+
count: 3,
97+
foo: true,
98+
data_1: vec![1, 2, 3],
99+
data_2: vec![4, 5, 6],
100+
}, WithElementsLengthUsedTwice::from_raw_bytes(
101+
&[0, 0, 0, 3, // disjoint length prefix
102+
1, // boolean true
103+
0, 0, 0, 1, // 1
104+
0, 0, 0, 2, // 2
105+
0, 0, 0, 3, // 3
106+
0, 0, 0, 1, // 4
107+
0, 0, 0, 2, // 5
108+
0, 0, 0, 3 // 6
109+
],
110+
&Settings::default()).unwrap());
111+
}
112+
113+
#[test]
114+
fn can_read_two_prefix_length() {
115+
assert_eq!(WithTwoPrefix {
116+
count: 3,
117+
count_2: 3,
118+
foo: true,
119+
data: vec![1, 2, 3],
120+
data_2: vec![4, 5, 6],
121+
}, WithTwoPrefix::from_raw_bytes(
122+
&[
123+
0, 0, 0, 3, // disjoint length prefix
124+
0, 0, 0, 3, // disjoint length prefix
125+
1, // boolean true
126+
0, 0, 0, 1, // 1
127+
0, 0, 0, 2, // 2
128+
0, 0, 0, 3, // 3
129+
0, 0, 0, 4, // 4
130+
0, 0, 0, 5, // 5
131+
0, 0, 0, 6 // 6
132+
],
133+
&Settings::default()).unwrap());
134+
}
135+
73136
#[test]
74137
fn can_read_fixed_length_prefix() {
75138

0 commit comments

Comments
 (0)