mirror of
https://codeberg.org/icewind/tf-log-parser.git
synced 2026-06-03 18:24:09 +02:00
some derive cleanup
This commit is contained in:
parent
14c1fbe0d9
commit
c06e09e691
5 changed files with 58 additions and 49 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -1,5 +1,5 @@
|
|||
target
|
||||
/result
|
||||
/.direnv
|
||||
result
|
||||
.direnv
|
||||
Cargo.lock
|
||||
callgrind.*
|
||||
|
|
@ -21,10 +21,12 @@ logos = "0.12"
|
|||
memchr = "2.5.0"
|
||||
ahash = "0.8.3"
|
||||
tf-log-parser-derive = { version = "0.1", path = "./derive" }
|
||||
miette = "5.5.0"
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = "0.4"
|
||||
iai = "0.1"
|
||||
miette = { version = "5.5.0", features = ["fancy"] }
|
||||
|
||||
[[bench]]
|
||||
name = "bench"
|
||||
|
|
|
|||
|
|
@ -1,19 +1,10 @@
|
|||
use crate::{Derivable, DeriveParams};
|
||||
use proc_macro2::{Ident, TokenStream};
|
||||
use crate::{err, Derivable, DeriveParams};
|
||||
use proc_macro2::{Ident, Span, TokenStream};
|
||||
use quote::{quote, quote_spanned};
|
||||
use syn::{Data, DeriveInput, Error, Field, Fields, Generics, Lifetime, Result, Type, TypePath};
|
||||
use syn::spanned::Spanned;
|
||||
use syn::{Data, DeriveInput, Field, Fields, Generics, Lifetime, Result, Type, TypePath};
|
||||
use syn_util::{contains_attribute, get_attribute_value};
|
||||
|
||||
macro_rules! bail {
|
||||
($msg:expr $(,)?) => {
|
||||
return Err(Error::new(Span::call_site(), &$msg[..]))
|
||||
};
|
||||
|
||||
( $msg:expr => $span_to_blame:expr $(,)? ) => {
|
||||
return Err(Error::new_spanned(&$span_to_blame, $msg))
|
||||
};
|
||||
}
|
||||
|
||||
pub struct Event;
|
||||
|
||||
impl Derivable for Event {
|
||||
|
|
@ -29,30 +20,10 @@ impl Derivable for Event {
|
|||
let required_fields = required_params
|
||||
.map(|param| {
|
||||
let field_name = ¶m.field_name;
|
||||
let parser = param.parser();
|
||||
let after = param.skip_after();
|
||||
|
||||
let parser = match (¶m.param_name, param.quoted) {
|
||||
(Some(param_name), true) => {
|
||||
quote_spanned!(field_name.span() => param_parse_with(#param_name, quoted(parse_field)))
|
||||
}
|
||||
(Some(param_name), false) => {
|
||||
quote_spanned!(field_name.span() => param_parse_with(#param_name, parse_field))
|
||||
}
|
||||
(None, true) => {
|
||||
quote_spanned!(field_name.span() => quoted(parse_field))
|
||||
}
|
||||
(None, false) => {
|
||||
quote_spanned!(field_name.span() => parse_field)
|
||||
}
|
||||
};
|
||||
|
||||
let skip_after = param.skip_after as usize;
|
||||
let after = if skip_after > 0 {
|
||||
quote_spanned!(field_name.span() => let input = &input[#skip_after..];)
|
||||
} else {
|
||||
quote!()
|
||||
};
|
||||
|
||||
Ok(quote_spanned!(field_name.span() =>
|
||||
Ok(quote_spanned!(param.span() =>
|
||||
#[allow(unused_variables)]
|
||||
let (input, #field_name) = #parser(input)?;
|
||||
#after
|
||||
|
|
@ -79,7 +50,7 @@ impl Derivable for Event {
|
|||
.map(|param| {
|
||||
let field_name = ¶m.field_name;
|
||||
let Some(param_name) = param.param_name.as_deref() else {
|
||||
bail!("optional fields can't be unnamed" => param.field_name)
|
||||
return err("optional fields can't be unnamed", ¶m.field_name);
|
||||
};
|
||||
|
||||
let parser = if param.quoted {
|
||||
|
|
@ -136,10 +107,10 @@ pub struct EventParams {
|
|||
impl DeriveParams for EventParams {
|
||||
fn parse(input: &DeriveInput) -> Result<EventParams> {
|
||||
let Data::Struct(data) = &input.data else {
|
||||
bail!("only supported on structs" => input)
|
||||
return err("only supported on structs", input);
|
||||
};
|
||||
let Fields::Named(fields) = &data.fields else {
|
||||
bail!("only supported with named fields" => input)
|
||||
return err("only supported with named fields", input);
|
||||
};
|
||||
let name = input.ident.clone();
|
||||
let generics = input.generics.clone();
|
||||
|
|
@ -152,7 +123,10 @@ impl DeriveParams for EventParams {
|
|||
let mut last_optional = false;
|
||||
for param in params.iter() {
|
||||
if last_optional > param.optional {
|
||||
bail!("optional fields are required to be at the end" => param.field_name)
|
||||
return err(
|
||||
"optional fields are required to be at the end",
|
||||
¶m.field_name,
|
||||
);
|
||||
}
|
||||
last_optional = param.optional;
|
||||
}
|
||||
|
|
@ -162,14 +136,13 @@ impl DeriveParams for EventParams {
|
|||
{
|
||||
Lifetime::new(&lifetime, name.span())
|
||||
} else {
|
||||
let mut lifetimes = input.generics.lifetimes();
|
||||
let mut lifetimes = input.generics.lifetimes().cloned();
|
||||
let lifetime = lifetimes
|
||||
.next()
|
||||
.cloned()
|
||||
.map(|lifetime| lifetime.lifetime)
|
||||
.unwrap_or_else(|| Lifetime::new("'_", name.span()));
|
||||
if lifetimes.next().is_some() {
|
||||
bail!("For structs with more than one lifetime, manually specifiying the lifetime is required" => name);
|
||||
return err("For structs with more than one lifetime, manually specifiying the lifetime is required", name);
|
||||
}
|
||||
lifetime
|
||||
};
|
||||
|
|
@ -185,6 +158,7 @@ impl DeriveParams for EventParams {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct EventParam {
|
||||
span: Span,
|
||||
field_name: Ident,
|
||||
param_name: Option<String>,
|
||||
optional: bool,
|
||||
|
|
@ -218,11 +192,12 @@ impl EventParam {
|
|||
get_attribute_value(&input.attrs, &["event", "skip_after"]).unwrap_or_default();
|
||||
|
||||
if optional && skip_after > 0 {
|
||||
bail!("skip_after can't be used with optional fields" => input);
|
||||
return err("skip_after can't be used with optional fields", input);
|
||||
}
|
||||
let quoted = contains_attribute(&input.attrs, &["event", "quoted"]);
|
||||
|
||||
Ok(EventParam {
|
||||
span: input.span(),
|
||||
field_name,
|
||||
param_name,
|
||||
optional,
|
||||
|
|
@ -230,4 +205,31 @@ impl EventParam {
|
|||
quoted,
|
||||
})
|
||||
}
|
||||
|
||||
fn span(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
|
||||
fn parser(&self) -> TokenStream {
|
||||
let field_parser = if self.quoted {
|
||||
quote_spanned!(self.span() => quoted(parse_field))
|
||||
} else {
|
||||
quote_spanned!(self.span() => parse_field)
|
||||
};
|
||||
|
||||
if let Some(param_name) = &self.param_name {
|
||||
quote_spanned!(self.span() => param_parse_with(#param_name, #field_parser))
|
||||
} else {
|
||||
quote_spanned!(self.span() => #field_parser)
|
||||
}
|
||||
}
|
||||
|
||||
fn skip_after(&self) -> TokenStream {
|
||||
let skip_after = self.skip_after as usize;
|
||||
if skip_after > 0 {
|
||||
quote_spanned!(self.span() => let input = &input.get(#skip_after..).ok_or(nom::Err::Incomplete(nom::Needed::Unknown))?;)
|
||||
} else {
|
||||
quote!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,9 @@ mod event;
|
|||
|
||||
use crate::event::Event;
|
||||
use proc_macro2::TokenStream;
|
||||
use std::fmt::Debug;
|
||||
use syn::{parse_macro_input, DeriveInput, Result};
|
||||
use quote::ToTokens;
|
||||
use std::fmt::{Debug, Display};
|
||||
use syn::{parse_macro_input, DeriveInput, Error, Result};
|
||||
|
||||
/// Derive the `Event` trait for a struct
|
||||
#[proc_macro_derive(Event, attributes(event))]
|
||||
|
|
@ -36,3 +37,7 @@ trait Derivable {
|
|||
trait DeriveParams: Sized + Debug {
|
||||
fn parse(input: &DeriveInput) -> Result<Self>;
|
||||
}
|
||||
|
||||
fn err<R, T: ToTokens, U: Display>(msg: U, span: T) -> Result<R> {
|
||||
return Err(Error::new_spanned(&span, msg));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ impl<'a> Iterator for LineSplit<'a> {
|
|||
None if self.start < self.input.len() => {
|
||||
let line = &self.input[self.start..];
|
||||
self.start = self.input.len();
|
||||
Some(dbg!(line.trim_end_matches("\n")))
|
||||
Some(line.trim_end_matches("\n"))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue