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