mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-01-12 16:45:31 +00:00
rustfmt wire_format_derive and poll_token_derive
BUG=None TEST=cargo test Change-Id: I62f00a71ed3693352de648bb8ee576335b32019f Signed-off-by: Daniel Verkamp <dverkamp@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1273688 Reviewed-by: Zach Reizner <zachr@chromium.org>
This commit is contained in:
parent
f5d565d693
commit
310b308166
3 changed files with 174 additions and 159 deletions
|
@ -8,8 +8,8 @@
|
|||
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
extern crate proc_macro2;
|
||||
extern crate proc_macro;
|
||||
extern crate proc_macro2;
|
||||
|
||||
#[macro_use]
|
||||
extern crate quote;
|
||||
|
@ -20,8 +20,8 @@ extern crate syn;
|
|||
use proc_macro::TokenStream;
|
||||
use proc_macro2::Span;
|
||||
use quote::Tokens;
|
||||
use syn::{Data, DeriveInput, Fields, Ident};
|
||||
use syn::spanned::Spanned;
|
||||
use syn::{Data, DeriveInput, Fields, Ident};
|
||||
|
||||
/// The function that derives the actual implementation.
|
||||
#[proc_macro_derive(P9WireFormat)]
|
||||
|
|
|
@ -207,7 +207,6 @@ impl ParseState {
|
|||
Tokenized::Enum => States::Ident,
|
||||
Tokenized::Visiblity => States::Start,
|
||||
_ => panic!("derives for enum types only"),
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -237,9 +236,9 @@ impl ParseState {
|
|||
self.current_state = match tok {
|
||||
Tokenized::Ident(ident) => {
|
||||
let mut variant = Some(EnumVariant {
|
||||
name: ident,
|
||||
data: None,
|
||||
});
|
||||
name: ident,
|
||||
data: None,
|
||||
});
|
||||
mem::swap(&mut variant, &mut self.current_variant);
|
||||
if let Some(variant) = variant {
|
||||
self.model.variants.push(variant);
|
||||
|
@ -247,14 +246,11 @@ impl ParseState {
|
|||
States::VariantIdent
|
||||
}
|
||||
Tokenized::IdentAndType(ident, type_) => {
|
||||
let variant_data = EnumVariantData {
|
||||
type_: type_,
|
||||
name: None,
|
||||
};
|
||||
let variant_data = EnumVariantData { type_, name: None };
|
||||
let mut variant = Some(EnumVariant {
|
||||
name: ident,
|
||||
data: Some(variant_data),
|
||||
});
|
||||
name: ident,
|
||||
data: Some(variant_data),
|
||||
});
|
||||
mem::swap(&mut variant, &mut self.current_variant);
|
||||
if let Some(variant) = variant {
|
||||
self.model.variants.push(variant);
|
||||
|
@ -278,12 +274,14 @@ impl ParseState {
|
|||
let variant = self.current_variant.as_mut().unwrap();
|
||||
self.current_state = match tok {
|
||||
Tokenized::FieldIdent(ident) => {
|
||||
assert!(variant.data.is_none(),
|
||||
"enum variant can only have one field");
|
||||
assert!(
|
||||
variant.data.is_none(),
|
||||
"enum variant can only have one field"
|
||||
);
|
||||
variant.data = Some(EnumVariantData {
|
||||
type_: "".to_owned(),
|
||||
name: Some(ident),
|
||||
});
|
||||
type_: "".to_owned(),
|
||||
name: Some(ident),
|
||||
});
|
||||
States::VariantDataType
|
||||
}
|
||||
Tokenized::CloseBrace => States::VariantIdent,
|
||||
|
@ -339,9 +337,10 @@ impl EnumModel {
|
|||
// The capture string is for everything between the variant identifier and the `=>` in
|
||||
// the match arm: the variant's data capture.
|
||||
let capture = match variant.data.as_ref() {
|
||||
Some(&EnumVariantData { name: Some(ref name), .. }) => {
|
||||
format!("{{ {}: data }}", name)
|
||||
}
|
||||
Some(&EnumVariantData {
|
||||
name: Some(ref name),
|
||||
..
|
||||
}) => format!("{{ {}: data }}", name),
|
||||
Some(&EnumVariantData { .. }) => "(data)".to_owned(),
|
||||
None => "".to_owned(),
|
||||
};
|
||||
|
@ -355,14 +354,11 @@ impl EnumModel {
|
|||
};
|
||||
|
||||
// Assembly of the match arm.
|
||||
write!(match_statement,
|
||||
"{}::{}{} => {}{},\n",
|
||||
self.name,
|
||||
variant.name,
|
||||
capture,
|
||||
index,
|
||||
modifer)
|
||||
.unwrap();
|
||||
write!(
|
||||
match_statement,
|
||||
"{}::{}{} => {}{},\n",
|
||||
self.name, variant.name, capture, index, modifer
|
||||
).unwrap();
|
||||
}
|
||||
match_statement.push_str("}");
|
||||
match_statement
|
||||
|
@ -382,24 +378,22 @@ impl EnumModel {
|
|||
// data, which includes both variant index and data bits.
|
||||
let data = match variant.data.as_ref() {
|
||||
Some(&EnumVariantData {
|
||||
name: Some(ref name),
|
||||
ref type_,
|
||||
}) => format!("{{ {}: (data >> {}) as {} }}", name, variant_bits, type_),
|
||||
name: Some(ref name),
|
||||
ref type_,
|
||||
}) => format!("{{ {}: (data >> {}) as {} }}", name, variant_bits, type_),
|
||||
Some(&EnumVariantData {
|
||||
name: None,
|
||||
ref type_,
|
||||
}) => format!("((data >> {}) as {})", variant_bits, type_),
|
||||
name: None,
|
||||
ref type_,
|
||||
}) => format!("((data >> {}) as {})", variant_bits, type_),
|
||||
None => "".to_owned(),
|
||||
};
|
||||
|
||||
// Assembly of the match arm.
|
||||
write!(match_statement,
|
||||
"{} => {}::{}{},\n",
|
||||
index,
|
||||
self.name,
|
||||
variant.name,
|
||||
data)
|
||||
.unwrap();
|
||||
write!(
|
||||
match_statement,
|
||||
"{} => {}::{}{},\n",
|
||||
index, self.name, variant.name, data
|
||||
).unwrap();
|
||||
}
|
||||
match_statement.push_str("_ => unreachable!()\n}");
|
||||
match_statement
|
||||
|
@ -419,9 +413,11 @@ fn poll_token_inner(src: &str) -> String {
|
|||
state.handle_token(tok);
|
||||
}
|
||||
|
||||
assert_eq!(state.current_state,
|
||||
States::End,
|
||||
"unexpected end after parsing source enum");
|
||||
assert_eq!(
|
||||
state.current_state,
|
||||
States::End,
|
||||
"unexpected end after parsing source enum"
|
||||
);
|
||||
|
||||
// Given our basic model of a user given enum that is suitable as a token, we generate the
|
||||
// implementation. The implementation is NOT always well formed, such as when a variant's data
|
||||
|
@ -429,7 +425,8 @@ fn poll_token_inner(src: &str) -> String {
|
|||
// would be difficult to detect every kind of error. Importantly, every implementation that we
|
||||
// generate here and goes on to compile succesfully is sound.
|
||||
let model = state.model;
|
||||
format!("impl PollToken for {} {{
|
||||
format!(
|
||||
"impl PollToken for {} {{
|
||||
fn as_raw_token(&self) -> u64 {{
|
||||
{}
|
||||
}}
|
||||
|
@ -438,9 +435,10 @@ fn poll_token_inner(src: &str) -> String {
|
|||
{}
|
||||
}}
|
||||
}}",
|
||||
model.name,
|
||||
model.generate_as_raw_token(),
|
||||
model.generate_from_raw_token())
|
||||
model.name,
|
||||
model.generate_as_raw_token(),
|
||||
model.generate_from_raw_token()
|
||||
)
|
||||
}
|
||||
|
||||
/// Implements the PollToken trait for a given `enum`.
|
||||
|
|
|
@ -21,27 +21,34 @@ mod tokenized {
|
|||
|
||||
#[test]
|
||||
fn ident() {
|
||||
assert_eq!(Tokenized::from_str("Important"),
|
||||
Ident("Important".to_owned()));
|
||||
assert_eq!(
|
||||
Tokenized::from_str("Important"),
|
||||
Ident("Important".to_owned())
|
||||
);
|
||||
assert_eq!(Tokenized::from_str("hello,"), Ident("hello".to_owned()));
|
||||
assert_eq!(Tokenized::from_str("world2"), Ident("world2".to_owned()));
|
||||
assert_eq!(Tokenized::from_str("A,"), Ident("A".to_owned()));
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn field_ident() {
|
||||
assert_eq!(Tokenized::from_str("index:"),
|
||||
FieldIdent("index".to_owned()));
|
||||
assert_eq!(
|
||||
Tokenized::from_str("index:"),
|
||||
FieldIdent("index".to_owned())
|
||||
);
|
||||
assert_eq!(Tokenized::from_str("a:"), FieldIdent("a".to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ident_and_type() {
|
||||
assert_eq!(Tokenized::from_str("a(u32)"),
|
||||
IdentAndType("a".to_owned(), "u32".to_owned()));
|
||||
assert_eq!(Tokenized::from_str("Socket(usize),"),
|
||||
IdentAndType("Socket".to_owned(), "usize".to_owned()));
|
||||
assert_eq!(
|
||||
Tokenized::from_str("a(u32)"),
|
||||
IdentAndType("a".to_owned(), "u32".to_owned())
|
||||
);
|
||||
assert_eq!(
|
||||
Tokenized::from_str("Socket(usize),"),
|
||||
IdentAndType("Socket".to_owned(), "usize".to_owned())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -63,27 +70,31 @@ mod tokenized {
|
|||
}
|
||||
|
||||
mod parse_state {
|
||||
use {Tokenized, States, ParseState, EnumModel, EnumVariant, EnumVariantData};
|
||||
use Tokenized::*;
|
||||
use {EnumModel, EnumVariant, EnumVariantData, ParseState, States, Tokenized};
|
||||
|
||||
fn parse_tokens(tokens: &[Tokenized]) -> EnumModel {
|
||||
let mut state = ParseState::new();
|
||||
for token in tokens {
|
||||
state.handle_token(token.clone());
|
||||
}
|
||||
assert_eq!(state.current_state,
|
||||
States::End,
|
||||
"unexpected end after parsing source enum");
|
||||
assert_eq!(
|
||||
state.current_state,
|
||||
States::End,
|
||||
"unexpected end after parsing source enum"
|
||||
);
|
||||
state.model
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_struct() {
|
||||
let model = parse_tokens(&[Visiblity,
|
||||
Enum,
|
||||
Ident("Blarg".to_owned()),
|
||||
OpenBrace,
|
||||
CloseBrace]);
|
||||
let model = parse_tokens(&[
|
||||
Visiblity,
|
||||
Enum,
|
||||
Ident("Blarg".to_owned()),
|
||||
OpenBrace,
|
||||
CloseBrace,
|
||||
]);
|
||||
let expected = EnumModel {
|
||||
name: "Blarg".to_string(),
|
||||
variants: Vec::new(),
|
||||
|
@ -94,94 +105,106 @@ mod parse_state {
|
|||
#[test]
|
||||
#[should_panic]
|
||||
fn invalid_token() {
|
||||
parse_tokens(&[Visiblity,
|
||||
Enum,
|
||||
Ident("Blarg".to_owned()),
|
||||
OpenBrace,
|
||||
CloseBrace,
|
||||
CloseBrace]);
|
||||
parse_tokens(&[
|
||||
Visiblity,
|
||||
Enum,
|
||||
Ident("Blarg".to_owned()),
|
||||
OpenBrace,
|
||||
CloseBrace,
|
||||
CloseBrace,
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn only_unit_variants() {
|
||||
let model = parse_tokens(&[Enum,
|
||||
Ident("Foo".to_owned()),
|
||||
OpenBrace,
|
||||
Ident("A".to_owned()),
|
||||
Ident("B".to_owned()),
|
||||
Ident("C".to_owned()),
|
||||
CloseBrace]);
|
||||
let model = parse_tokens(&[
|
||||
Enum,
|
||||
Ident("Foo".to_owned()),
|
||||
OpenBrace,
|
||||
Ident("A".to_owned()),
|
||||
Ident("B".to_owned()),
|
||||
Ident("C".to_owned()),
|
||||
CloseBrace,
|
||||
]);
|
||||
let expected = EnumModel {
|
||||
name: "Foo".to_string(),
|
||||
variants: vec![EnumVariant {
|
||||
name: "A".to_owned(),
|
||||
data: None,
|
||||
},
|
||||
EnumVariant {
|
||||
name: "B".to_owned(),
|
||||
data: None,
|
||||
},
|
||||
EnumVariant {
|
||||
name: "C".to_owned(),
|
||||
data: None,
|
||||
}],
|
||||
variants: vec![
|
||||
EnumVariant {
|
||||
name: "A".to_owned(),
|
||||
data: None,
|
||||
},
|
||||
EnumVariant {
|
||||
name: "B".to_owned(),
|
||||
data: None,
|
||||
},
|
||||
EnumVariant {
|
||||
name: "C".to_owned(),
|
||||
data: None,
|
||||
},
|
||||
],
|
||||
};
|
||||
assert_eq!(model, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unnamed_data() {
|
||||
let model = parse_tokens(&[Enum,
|
||||
Ident("Foo".to_owned()),
|
||||
OpenBrace,
|
||||
IdentAndType("A".to_owned(), "u32".to_owned()),
|
||||
Ident("B".to_owned()),
|
||||
IdentAndType("C".to_owned(), "usize".to_owned()),
|
||||
CloseBrace]);
|
||||
let model = parse_tokens(&[
|
||||
Enum,
|
||||
Ident("Foo".to_owned()),
|
||||
OpenBrace,
|
||||
IdentAndType("A".to_owned(), "u32".to_owned()),
|
||||
Ident("B".to_owned()),
|
||||
IdentAndType("C".to_owned(), "usize".to_owned()),
|
||||
CloseBrace,
|
||||
]);
|
||||
let expected = EnumModel {
|
||||
name: "Foo".to_string(),
|
||||
variants: vec![EnumVariant {
|
||||
name: "A".to_owned(),
|
||||
data: Some(EnumVariantData {
|
||||
name: None,
|
||||
type_: "u32".to_owned(),
|
||||
}),
|
||||
},
|
||||
EnumVariant {
|
||||
name: "B".to_owned(),
|
||||
data: None,
|
||||
},
|
||||
EnumVariant {
|
||||
name: "C".to_owned(),
|
||||
data: Some(EnumVariantData {
|
||||
name: None,
|
||||
type_: "usize".to_owned(),
|
||||
}),
|
||||
}],
|
||||
variants: vec![
|
||||
EnumVariant {
|
||||
name: "A".to_owned(),
|
||||
data: Some(EnumVariantData {
|
||||
name: None,
|
||||
type_: "u32".to_owned(),
|
||||
}),
|
||||
},
|
||||
EnumVariant {
|
||||
name: "B".to_owned(),
|
||||
data: None,
|
||||
},
|
||||
EnumVariant {
|
||||
name: "C".to_owned(),
|
||||
data: Some(EnumVariantData {
|
||||
name: None,
|
||||
type_: "usize".to_owned(),
|
||||
}),
|
||||
},
|
||||
],
|
||||
};
|
||||
assert_eq!(model, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn named_data() {
|
||||
let model = parse_tokens(&[Enum,
|
||||
Ident("Foo".to_owned()),
|
||||
OpenBrace,
|
||||
Ident("A".to_owned()),
|
||||
OpenBrace,
|
||||
FieldIdent("index".to_owned()),
|
||||
Ident("u16".to_owned()),
|
||||
CloseBrace,
|
||||
CloseBrace]);
|
||||
let model = parse_tokens(&[
|
||||
Enum,
|
||||
Ident("Foo".to_owned()),
|
||||
OpenBrace,
|
||||
Ident("A".to_owned()),
|
||||
OpenBrace,
|
||||
FieldIdent("index".to_owned()),
|
||||
Ident("u16".to_owned()),
|
||||
CloseBrace,
|
||||
CloseBrace,
|
||||
]);
|
||||
let expected = EnumModel {
|
||||
name: "Foo".to_string(),
|
||||
variants: vec![EnumVariant {
|
||||
name: "A".to_owned(),
|
||||
data: Some(EnumVariantData {
|
||||
name: Some("index".to_owned()),
|
||||
type_: "u16".to_owned(),
|
||||
}),
|
||||
}],
|
||||
name: "A".to_owned(),
|
||||
data: Some(EnumVariantData {
|
||||
name: Some("index".to_owned()),
|
||||
type_: "u16".to_owned(),
|
||||
}),
|
||||
}],
|
||||
};
|
||||
assert_eq!(model, expected);
|
||||
}
|
||||
|
@ -195,40 +218,34 @@ mod enum_model {
|
|||
let mut model = EnumModel {
|
||||
name: "Baz".to_string(),
|
||||
variants: vec![EnumVariant {
|
||||
name: "A".to_owned(),
|
||||
data: None,
|
||||
}],
|
||||
name: "A".to_owned(),
|
||||
data: None,
|
||||
}],
|
||||
};
|
||||
assert_eq!(model.variant_bits(), 0);
|
||||
|
||||
model.variants.append(
|
||||
&mut vec![
|
||||
EnumVariant {
|
||||
name: "B".to_owned(),
|
||||
data: None,
|
||||
},
|
||||
EnumVariant {
|
||||
name: "C".to_owned(),
|
||||
data: None,
|
||||
}
|
||||
]
|
||||
);
|
||||
model.variants.append(&mut vec![
|
||||
EnumVariant {
|
||||
name: "B".to_owned(),
|
||||
data: None,
|
||||
},
|
||||
EnumVariant {
|
||||
name: "C".to_owned(),
|
||||
data: None,
|
||||
},
|
||||
]);
|
||||
assert_eq!(model.variant_bits(), 2);
|
||||
for _ in 0..1021 {
|
||||
model
|
||||
.variants
|
||||
.push(EnumVariant {
|
||||
name: "Dynamic".to_owned(),
|
||||
data: None,
|
||||
});
|
||||
model.variants.push(EnumVariant {
|
||||
name: "Dynamic".to_owned(),
|
||||
data: None,
|
||||
});
|
||||
}
|
||||
assert_eq!(model.variant_bits(), 10);
|
||||
model
|
||||
.variants
|
||||
.push(EnumVariant {
|
||||
name: "OneMore".to_owned(),
|
||||
data: None,
|
||||
});
|
||||
model.variants.push(EnumVariant {
|
||||
name: "OneMore".to_owned(),
|
||||
data: None,
|
||||
});
|
||||
assert_eq!(model.variant_bits(), 11);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue