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
|
target
|
||||||
/result
|
result
|
||||||
/.direnv
|
.direnv
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
callgrind.*
|
callgrind.*
|
||||||
|
|
@ -21,10 +21,12 @@ logos = "0.12"
|
||||||
memchr = "2.5.0"
|
memchr = "2.5.0"
|
||||||
ahash = "0.8.3"
|
ahash = "0.8.3"
|
||||||
tf-log-parser-derive = { version = "0.1", path = "./derive" }
|
tf-log-parser-derive = { version = "0.1", path = "./derive" }
|
||||||
|
miette = "5.5.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
criterion = "0.4"
|
criterion = "0.4"
|
||||||
iai = "0.1"
|
iai = "0.1"
|
||||||
|
miette = { version = "5.5.0", features = ["fancy"] }
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
name = "bench"
|
name = "bench"
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,10 @@
|
||||||
use crate::{Derivable, DeriveParams};
|
use crate::{err, Derivable, DeriveParams};
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, Span, TokenStream};
|
||||||
use quote::{quote, quote_spanned};
|
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};
|
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;
|
pub struct Event;
|
||||||
|
|
||||||
impl Derivable for Event {
|
impl Derivable for Event {
|
||||||
|
|
@ -29,30 +20,10 @@ impl Derivable for Event {
|
||||||
let required_fields = required_params
|
let required_fields = required_params
|
||||||
.map(|param| {
|
.map(|param| {
|
||||||
let field_name = ¶m.field_name;
|
let field_name = ¶m.field_name;
|
||||||
|
let parser = param.parser();
|
||||||
|
let after = param.skip_after();
|
||||||
|
|
||||||
let parser = match (¶m.param_name, param.quoted) {
|
Ok(quote_spanned!(param.span() =>
|
||||||
(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() =>
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
let (input, #field_name) = #parser(input)?;
|
let (input, #field_name) = #parser(input)?;
|
||||||
#after
|
#after
|
||||||
|
|
@ -79,7 +50,7 @@ impl Derivable for Event {
|
||||||
.map(|param| {
|
.map(|param| {
|
||||||
let field_name = ¶m.field_name;
|
let field_name = ¶m.field_name;
|
||||||
let Some(param_name) = param.param_name.as_deref() else {
|
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 {
|
let parser = if param.quoted {
|
||||||
|
|
@ -136,10 +107,10 @@ pub struct EventParams {
|
||||||
impl DeriveParams for EventParams {
|
impl DeriveParams for EventParams {
|
||||||
fn parse(input: &DeriveInput) -> Result<EventParams> {
|
fn parse(input: &DeriveInput) -> Result<EventParams> {
|
||||||
let Data::Struct(data) = &input.data else {
|
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 {
|
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 name = input.ident.clone();
|
||||||
let generics = input.generics.clone();
|
let generics = input.generics.clone();
|
||||||
|
|
@ -152,7 +123,10 @@ impl DeriveParams for EventParams {
|
||||||
let mut last_optional = false;
|
let mut last_optional = false;
|
||||||
for param in params.iter() {
|
for param in params.iter() {
|
||||||
if last_optional > param.optional {
|
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;
|
last_optional = param.optional;
|
||||||
}
|
}
|
||||||
|
|
@ -162,14 +136,13 @@ impl DeriveParams for EventParams {
|
||||||
{
|
{
|
||||||
Lifetime::new(&lifetime, name.span())
|
Lifetime::new(&lifetime, name.span())
|
||||||
} else {
|
} else {
|
||||||
let mut lifetimes = input.generics.lifetimes();
|
let mut lifetimes = input.generics.lifetimes().cloned();
|
||||||
let lifetime = lifetimes
|
let lifetime = lifetimes
|
||||||
.next()
|
.next()
|
||||||
.cloned()
|
|
||||||
.map(|lifetime| lifetime.lifetime)
|
.map(|lifetime| lifetime.lifetime)
|
||||||
.unwrap_or_else(|| Lifetime::new("'_", name.span()));
|
.unwrap_or_else(|| Lifetime::new("'_", name.span()));
|
||||||
if lifetimes.next().is_some() {
|
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
|
lifetime
|
||||||
};
|
};
|
||||||
|
|
@ -185,6 +158,7 @@ impl DeriveParams for EventParams {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct EventParam {
|
pub struct EventParam {
|
||||||
|
span: Span,
|
||||||
field_name: Ident,
|
field_name: Ident,
|
||||||
param_name: Option<String>,
|
param_name: Option<String>,
|
||||||
optional: bool,
|
optional: bool,
|
||||||
|
|
@ -218,11 +192,12 @@ impl EventParam {
|
||||||
get_attribute_value(&input.attrs, &["event", "skip_after"]).unwrap_or_default();
|
get_attribute_value(&input.attrs, &["event", "skip_after"]).unwrap_or_default();
|
||||||
|
|
||||||
if optional && skip_after > 0 {
|
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"]);
|
let quoted = contains_attribute(&input.attrs, &["event", "quoted"]);
|
||||||
|
|
||||||
Ok(EventParam {
|
Ok(EventParam {
|
||||||
|
span: input.span(),
|
||||||
field_name,
|
field_name,
|
||||||
param_name,
|
param_name,
|
||||||
optional,
|
optional,
|
||||||
|
|
@ -230,4 +205,31 @@ impl EventParam {
|
||||||
quoted,
|
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 crate::event::Event;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use std::fmt::Debug;
|
use quote::ToTokens;
|
||||||
use syn::{parse_macro_input, DeriveInput, Result};
|
use std::fmt::{Debug, Display};
|
||||||
|
use syn::{parse_macro_input, DeriveInput, Error, Result};
|
||||||
|
|
||||||
/// Derive the `Event` trait for a struct
|
/// Derive the `Event` trait for a struct
|
||||||
#[proc_macro_derive(Event, attributes(event))]
|
#[proc_macro_derive(Event, attributes(event))]
|
||||||
|
|
@ -36,3 +37,7 @@ trait Derivable {
|
||||||
trait DeriveParams: Sized + Debug {
|
trait DeriveParams: Sized + Debug {
|
||||||
fn parse(input: &DeriveInput) -> Result<Self>;
|
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() => {
|
None if self.start < self.input.len() => {
|
||||||
let line = &self.input[self.start..];
|
let line = &self.input[self.start..];
|
||||||
self.start = self.input.len();
|
self.start = self.input.len();
|
||||||
Some(dbg!(line.trim_end_matches("\n")))
|
Some(line.trim_end_matches("\n"))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue