wayland: optimize parsing of fixed-size messages
This commit is contained in:
parent
b745e20f7f
commit
755bfdd661
6 changed files with 92 additions and 25 deletions
|
|
@ -6,7 +6,7 @@ use {
|
||||||
wire::parser::{Field, Lined, Message, Type, parse_messages, to_camel},
|
wire::parser::{Field, Lined, Message, Type, parse_messages, to_camel},
|
||||||
},
|
},
|
||||||
anyhow::{Context, Result},
|
anyhow::{Context, Result},
|
||||||
std::{fs::DirEntry, io::Write, os::unix::ffi::OsStrExt},
|
std::{fmt, fs::DirEntry, io::Write, os::unix::ffi::OsStrExt},
|
||||||
};
|
};
|
||||||
|
|
||||||
fn write_type<W: Write>(f: &mut W, ty: &Type) -> Result<()> {
|
fn write_type<W: Write>(f: &mut W, ty: &Type) -> Result<()> {
|
||||||
|
|
@ -110,26 +110,81 @@ fn write_message<W: Write>(f: &mut W, obj: &str, message: &Message) -> Result<()
|
||||||
" fn parse({}: &mut MsgParser<'_, 'a>) -> Result<Self, MsgParserError> {{",
|
" fn parse({}: &mut MsgParser<'_, 'a>) -> Result<Self, MsgParserError> {{",
|
||||||
parser
|
parser
|
||||||
)?;
|
)?;
|
||||||
writeln!(f, " Ok(Self {{")?;
|
if message.is_fixed_size {
|
||||||
writeln!(f, " self_id: {}Id::NONE,", obj)?;
|
writeln!(f, " let [")?;
|
||||||
for field in &message.fields {
|
for (i, field) in message.fields.iter().enumerate() {
|
||||||
let p = match &field.val.ty.val {
|
match &field.val.ty.val {
|
||||||
Type::Id(..) => "object",
|
Type::U64 => {
|
||||||
Type::U32 => "uint",
|
writeln!(f, " arg{i}_hi,")?;
|
||||||
Type::I32 => "int",
|
writeln!(f, " arg{i}_lo,")?;
|
||||||
Type::U64 => "u64",
|
}
|
||||||
Type::U64Rev => "u64_rev",
|
Type::U64Rev => {
|
||||||
Type::OptStr => "optstr",
|
writeln!(f, " arg{i}_lo,")?;
|
||||||
Type::Str => "str",
|
writeln!(f, " arg{i}_hi,")?;
|
||||||
Type::Fixed => "fixed",
|
}
|
||||||
Type::Fd => "fd",
|
Type::Fd => {}
|
||||||
Type::BStr => "bstr",
|
_ => {
|
||||||
Type::Array(_) => "binary_array",
|
writeln!(f, " arg{i},")?;
|
||||||
Type::Pod(_) => "binary",
|
}
|
||||||
};
|
}
|
||||||
writeln!(f, " {}: parser.{}()?,", field.val.name, p)?;
|
}
|
||||||
|
writeln!(f, " ] = *{parser}.data() else {{")?;
|
||||||
|
writeln!(
|
||||||
|
f,
|
||||||
|
" return Err(MsgParserError::UnexpectedMessageSize);"
|
||||||
|
)?;
|
||||||
|
writeln!(f, " }};")?;
|
||||||
|
writeln!(f, " Ok(Self {{")?;
|
||||||
|
writeln!(f, " self_id: {}Id::NONE,", obj)?;
|
||||||
|
for (i, field) in message.fields.iter().enumerate() {
|
||||||
|
writeln!(
|
||||||
|
f,
|
||||||
|
" {}: {},",
|
||||||
|
field.val.name,
|
||||||
|
fmt::from_fn(|f| {
|
||||||
|
match &field.val.ty.val {
|
||||||
|
Type::Id(_, name) => write!(f, "{name}Id(arg{i})"),
|
||||||
|
Type::U32 => write!(f, "arg{i}"),
|
||||||
|
Type::I32 => write!(f, "arg{i} as i32"),
|
||||||
|
Type::U64 | Type::U64Rev => {
|
||||||
|
write!(f, "((arg{i}_hi as u64) << 32) | (arg{i}_lo as u64)")
|
||||||
|
}
|
||||||
|
Type::OptStr => unreachable!(),
|
||||||
|
Type::Str => unreachable!(),
|
||||||
|
Type::Fixed => write!(f, "Fixed(arg{i} as i32)"),
|
||||||
|
Type::Fd => write!(f, "parser.fd()?"),
|
||||||
|
Type::BStr => unreachable!(),
|
||||||
|
Type::Array(_) => unreachable!(),
|
||||||
|
Type::Pod(_) => unreachable!(),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
writeln!(f, " }})")?;
|
||||||
|
} else {
|
||||||
|
writeln!(f, " let res = Ok(Self {{")?;
|
||||||
|
writeln!(f, " self_id: {}Id::NONE,", obj)?;
|
||||||
|
for field in &message.fields {
|
||||||
|
let p = match &field.val.ty.val {
|
||||||
|
Type::Id(..) => "object",
|
||||||
|
Type::U32 => "uint",
|
||||||
|
Type::I32 => "int",
|
||||||
|
Type::U64 => "u64",
|
||||||
|
Type::U64Rev => "u64_rev",
|
||||||
|
Type::OptStr => "optstr",
|
||||||
|
Type::Str => "str",
|
||||||
|
Type::Fixed => "fixed",
|
||||||
|
Type::Fd => "fd",
|
||||||
|
Type::BStr => "bstr",
|
||||||
|
Type::Array(_) => "binary_array",
|
||||||
|
Type::Pod(_) => "binary",
|
||||||
|
};
|
||||||
|
writeln!(f, " {}: parser.{}()?,", field.val.name, p)?;
|
||||||
|
}
|
||||||
|
writeln!(f, " }});")?;
|
||||||
|
writeln!(f, " parser.eof()?;")?;
|
||||||
|
writeln!(f, " res")?;
|
||||||
}
|
}
|
||||||
writeln!(f, " }})")?;
|
|
||||||
writeln!(f, " }}")?;
|
writeln!(f, " }}")?;
|
||||||
writeln!(f, " }}")?;
|
writeln!(f, " }}")?;
|
||||||
writeln!(
|
writeln!(
|
||||||
|
|
|
||||||
|
|
@ -235,6 +235,7 @@ pub struct Message {
|
||||||
pub fields: Vec<Lined<Field>>,
|
pub fields: Vec<Lined<Field>>,
|
||||||
pub attribs: MessageAttribs,
|
pub attribs: MessageAttribs,
|
||||||
pub has_reference_type: bool,
|
pub has_reference_type: bool,
|
||||||
|
pub is_fixed_size: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
|
@ -344,6 +345,11 @@ impl<'a> Parser<'a> {
|
||||||
Type::OptStr | Type::Str | Type::BStr | Type::Array(..) => true,
|
Type::OptStr | Type::Str | Type::BStr | Type::Array(..) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
});
|
});
|
||||||
|
let is_variable_size = fields.iter().any(|f| match &f.val.ty.val {
|
||||||
|
Type::OptStr | Type::Str | Type::BStr | Type::Array(..) | Type::Pod(..) => true,
|
||||||
|
_ => false,
|
||||||
|
});
|
||||||
|
let is_fixed_size = !is_variable_size;
|
||||||
let safe_name = match name {
|
let safe_name = match name {
|
||||||
"move" => "move_",
|
"move" => "move_",
|
||||||
"type" => "type_",
|
"type" => "type_",
|
||||||
|
|
@ -361,6 +367,7 @@ impl<'a> Parser<'a> {
|
||||||
fields,
|
fields,
|
||||||
attribs,
|
attribs,
|
||||||
has_reference_type,
|
has_reference_type,
|
||||||
|
is_fixed_size,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
|
|
@ -427,7 +427,6 @@ impl Client {
|
||||||
mut parser: MsgParser<'_, 'a>,
|
mut parser: MsgParser<'_, 'a>,
|
||||||
) -> Result<R, MsgParserError> {
|
) -> Result<R, MsgParserError> {
|
||||||
let res = R::parse(&mut parser)?;
|
let res = R::parse(&mut parser)?;
|
||||||
parser.eof()?;
|
|
||||||
log::trace!(
|
log::trace!(
|
||||||
"Client {} -> {}@{}.{:?}",
|
"Client {} -> {}@{}.{:?}",
|
||||||
self.id,
|
self.id,
|
||||||
|
|
|
||||||
|
|
@ -146,9 +146,7 @@ pub trait ParseFull<'a>: Sized {
|
||||||
|
|
||||||
impl<'a, T: RequestParser<'a>> ParseFull<'a> for T {
|
impl<'a, T: RequestParser<'a>> ParseFull<'a> for T {
|
||||||
fn parse_full(mut parser: MsgParser<'_, 'a>) -> Result<Self, TestError> {
|
fn parse_full(mut parser: MsgParser<'_, 'a>) -> Result<Self, TestError> {
|
||||||
let res = T::parse(&mut parser)?;
|
T::parse(&mut parser).map_err(Into::into)
|
||||||
parser.eof()?;
|
|
||||||
Ok(res)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@ pub enum MsgParserError {
|
||||||
TrailingData,
|
TrailingData,
|
||||||
#[error("String is not UTF-8")]
|
#[error("String is not UTF-8")]
|
||||||
NonUtf8,
|
NonUtf8,
|
||||||
|
#[error("The message has an unexpected size")]
|
||||||
|
UnexpectedMessageSize,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MsgParser<'a, 'b> {
|
pub struct MsgParser<'a, 'b> {
|
||||||
|
|
@ -35,6 +37,11 @@ impl<'a, 'b> MsgParser<'a, 'b> {
|
||||||
Self { buf, pos: 0, data }
|
Self { buf, pos: 0, data }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn data(&self) -> &[u32] {
|
||||||
|
self.data
|
||||||
|
}
|
||||||
|
|
||||||
pub fn int(&mut self) -> Result<i32, MsgParserError> {
|
pub fn int(&mut self) -> Result<i32, MsgParserError> {
|
||||||
if self.pos >= self.data.len() {
|
if self.pos >= self.data.len() {
|
||||||
return Err(MsgParserError::UnexpectedEof);
|
return Err(MsgParserError::UnexpectedEof);
|
||||||
|
|
@ -48,12 +55,14 @@ impl<'a, 'b> MsgParser<'a, 'b> {
|
||||||
self.int().map(|i| i as u32)
|
self.int().map(|i| i as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[expect(dead_code)]
|
||||||
pub fn u64(&mut self) -> Result<u64, MsgParserError> {
|
pub fn u64(&mut self) -> Result<u64, MsgParserError> {
|
||||||
let hi = self.uint()?;
|
let hi = self.uint()?;
|
||||||
let lo = self.uint()?;
|
let lo = self.uint()?;
|
||||||
Ok(((hi as u64) << 32) | lo as u64)
|
Ok(((hi as u64) << 32) | lo as u64)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[expect(dead_code)]
|
||||||
pub fn u64_rev(&mut self) -> Result<u64, MsgParserError> {
|
pub fn u64_rev(&mut self) -> Result<u64, MsgParserError> {
|
||||||
let lo = self.uint()?;
|
let lo = self.uint()?;
|
||||||
let hi = self.uint()?;
|
let hi = self.uint()?;
|
||||||
|
|
|
||||||
|
|
@ -257,7 +257,6 @@ impl UsrCon {
|
||||||
mut parser: MsgParser<'_, 'a>,
|
mut parser: MsgParser<'_, 'a>,
|
||||||
) -> Result<R, MsgParserError> {
|
) -> Result<R, MsgParserError> {
|
||||||
let res = R::parse(&mut parser)?;
|
let res = R::parse(&mut parser)?;
|
||||||
parser.eof()?;
|
|
||||||
log::trace!(
|
log::trace!(
|
||||||
"Server {} -> {}@{}.{:?}",
|
"Server {} -> {}@{}.{:?}",
|
||||||
self.server_id,
|
self.server_id,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue