Compare commits
2 commits
4daa5f7cdf
...
97f8a6ed23
Author | SHA1 | Date | |
---|---|---|---|
97f8a6ed23 | |||
0f6c58d8b3 |
6 changed files with 66 additions and 27 deletions
|
@ -12,7 +12,6 @@ members = ["protogen"]
|
|||
byteorder = "1.5.0"
|
||||
bytes = "1.10.0"
|
||||
nix = "0.29.0"
|
||||
protogen = { version = "0.1.0", path = "protogen" }
|
||||
sendfd = { version = "0.4", features = [ "tokio" ] }
|
||||
serde = "1.0.218"
|
||||
serde_derive = "1.0.218"
|
||||
|
@ -20,3 +19,6 @@ tokio = { version = "1.43.0", features = [ "fs", "net", "rt", "rt-multi-thread",
|
|||
toml = "0.8.20"
|
||||
tracing = "0.1.41"
|
||||
tracing-subscriber = "0.3.19"
|
||||
|
||||
[build-dependencies]
|
||||
protogen = { version = "0.1.0", path = "protogen" }
|
||||
|
|
19
build.rs
Normal file
19
build.rs
Normal file
|
@ -0,0 +1,19 @@
|
|||
use std::{env, path::Path};
|
||||
|
||||
fn main() {
|
||||
let out_dir = env::var_os("OUT_DIR").unwrap();
|
||||
let out_file = Path::new(&out_dir).join("proto_generated.rs");
|
||||
|
||||
std::fs::write(&out_file, protogen::generate_from_dir("proto"))
|
||||
.expect("unable to write to file");
|
||||
|
||||
// If rustfmt is present, run rustfmt so that the generated file is somewhat human-readable
|
||||
std::process::Command::new("rustfmt")
|
||||
.arg(out_file.to_str().expect("utf8 error"))
|
||||
.output()
|
||||
.ok();
|
||||
|
||||
println!("cargo::rerun-if-changed=build.rs");
|
||||
println!("cargo::rerun-if-changed=proto");
|
||||
println!("cargo::rerun-if-changed=protogen");
|
||||
}
|
|
@ -3,9 +3,6 @@ name = "protogen"
|
|||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = "1.0.93"
|
||||
quick-xml = "0.37.2"
|
||||
|
|
|
@ -1,17 +1,42 @@
|
|||
use std::path::PathBuf;
|
||||
use std::path::Path;
|
||||
|
||||
use quick_xml::events::Event;
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{Ident, LitStr, parse_macro_input};
|
||||
use syn::Ident;
|
||||
use types::{WlArgType, WlInterface, WlMsg, WlMsgType};
|
||||
|
||||
mod types;
|
||||
|
||||
#[proc_macro]
|
||||
pub fn wayland_proto_gen(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let input: LitStr = parse_macro_input!(item);
|
||||
let p = PathBuf::from(input.value());
|
||||
let file_name = p.file_stem().expect("No file name provided");
|
||||
pub fn generate_from_dir(p: impl AsRef<Path>) -> String {
|
||||
let (gen_code, (add_parsers_fn, add_object_types_fn)): (Vec<_>, (Vec<_>, Vec<_>)) =
|
||||
std::fs::read_dir(p)
|
||||
.expect("cannot open directory")
|
||||
.filter_map(|f| f.ok())
|
||||
.filter(|f| {
|
||||
f.file_name()
|
||||
.to_str()
|
||||
.expect("utf8 encoding error")
|
||||
.ends_with(".xml")
|
||||
})
|
||||
.map(|f| generate_from_xml_file(f.path()))
|
||||
.unzip();
|
||||
|
||||
quote! {
|
||||
#( #gen_code )*
|
||||
|
||||
pub fn wl_init_parsers() {
|
||||
#( #add_parsers_fn(); )*
|
||||
}
|
||||
|
||||
pub fn wl_init_known_types() {
|
||||
#( #add_object_types_fn(); )*
|
||||
}
|
||||
}
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn generate_from_xml_file(p: impl AsRef<Path>) -> (proc_macro2::TokenStream, (Ident, Ident)) {
|
||||
let file_name = p.as_ref().file_stem().expect("No file name provided");
|
||||
let xml_str = std::fs::read_to_string(&p).expect("Unable to read from file");
|
||||
let mut reader = quick_xml::Reader::from_str(&xml_str);
|
||||
reader.config_mut().trim_text(true);
|
||||
|
@ -63,13 +88,15 @@ pub fn wayland_proto_gen(item: proc_macro::TokenStream) -> proc_macro::TokenStre
|
|||
}
|
||||
}
|
||||
|
||||
let file_name_snake = file_name.to_str().unwrap().replace("-", "_");
|
||||
|
||||
// A function to add all event/request parsers to WL_EVENT_PARSERS and WL_REQUEST_PARSERS
|
||||
let add_parsers_fn = format_ident!("wl_init_parsers_{}", file_name.to_str().unwrap());
|
||||
let add_parsers_fn = format_ident!("wl_init_parsers_{}", file_name_snake);
|
||||
|
||||
// A function to add all known interfaces to the WL_KNOWN_OBJECT_TYPES map from name -> Rust type
|
||||
let add_object_types_fn = format_ident!("wl_init_known_types_{}", file_name.to_str().unwrap());
|
||||
let add_object_types_fn = format_ident!("wl_init_known_types_{}", file_name_snake);
|
||||
|
||||
quote! {
|
||||
let ret_code = quote! {
|
||||
#( #code )*
|
||||
|
||||
fn #add_parsers_fn() {
|
||||
|
@ -80,8 +107,9 @@ pub fn wayland_proto_gen(item: proc_macro::TokenStream) -> proc_macro::TokenStre
|
|||
fn #add_object_types_fn() {
|
||||
#( WL_KNOWN_OBJECT_TYPES.write().unwrap().insert(#known_interface_names, #known_interface_consts); )*
|
||||
}
|
||||
}
|
||||
.into()
|
||||
};
|
||||
|
||||
(ret_code, (add_parsers_fn, add_object_types_fn))
|
||||
}
|
||||
|
||||
fn handle_interface(
|
||||
|
|
|
@ -113,6 +113,7 @@ impl WlMsg {
|
|||
.collect();
|
||||
|
||||
quote! {
|
||||
#[allow(unused)]
|
||||
pub struct #struct_name<'a> {
|
||||
_phantom: std::marker::PhantomData<&'a ()>,
|
||||
#( pub #field_names: #field_types, )*
|
||||
|
@ -145,6 +146,7 @@ impl WlMsg {
|
|||
WlMsgType::#msg_type
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
fn try_from_msg_impl(msg: &crate::codec::WlRawMsg) -> WaylandProtocolParsingOutcome<#struct_name> {
|
||||
let payload = msg.payload();
|
||||
let mut pos = 0usize;
|
||||
|
|
13
src/proto.rs
13
src/proto.rs
|
@ -7,7 +7,6 @@ use std::{
|
|||
};
|
||||
|
||||
use byteorder::ByteOrder;
|
||||
use protogen::wayland_proto_gen;
|
||||
|
||||
use crate::{
|
||||
codec::WlRawMsg,
|
||||
|
@ -218,13 +217,5 @@ pub fn lookup_known_object_type(name: &str) -> Option<WlObjectType> {
|
|||
/// The default object ID of wl_display
|
||||
pub const WL_DISPLAY_OBJECT_ID: u32 = 1;
|
||||
|
||||
wayland_proto_gen!("proto/wayland.xml");
|
||||
|
||||
/// Install all available Wayland protocol parsers for use by [decode_event] and [decode_request].
|
||||
pub fn wl_init_parsers() {
|
||||
wl_init_parsers_wayland();
|
||||
}
|
||||
|
||||
pub fn wl_init_known_types() {
|
||||
wl_init_known_types_wayland();
|
||||
}
|
||||
// Include code generated by build.rs
|
||||
include!(concat!(env!("OUT_DIR"), "/proto_generated.rs"));
|
||||
|
|
Loading…
Add table
Reference in a new issue