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"
|
byteorder = "1.5.0"
|
||||||
bytes = "1.10.0"
|
bytes = "1.10.0"
|
||||||
nix = "0.29.0"
|
nix = "0.29.0"
|
||||||
protogen = { version = "0.1.0", path = "protogen" }
|
|
||||||
sendfd = { version = "0.4", features = [ "tokio" ] }
|
sendfd = { version = "0.4", features = [ "tokio" ] }
|
||||||
serde = "1.0.218"
|
serde = "1.0.218"
|
||||||
serde_derive = "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"
|
toml = "0.8.20"
|
||||||
tracing = "0.1.41"
|
tracing = "0.1.41"
|
||||||
tracing-subscriber = "0.3.19"
|
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"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[lib]
|
|
||||||
proc-macro = true
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
proc-macro2 = "1.0.93"
|
proc-macro2 = "1.0.93"
|
||||||
quick-xml = "0.37.2"
|
quick-xml = "0.37.2"
|
||||||
|
|
|
@ -1,17 +1,42 @@
|
||||||
use std::path::PathBuf;
|
use std::path::Path;
|
||||||
|
|
||||||
use quick_xml::events::Event;
|
use quick_xml::events::Event;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
use syn::{Ident, LitStr, parse_macro_input};
|
use syn::Ident;
|
||||||
use types::{WlArgType, WlInterface, WlMsg, WlMsgType};
|
use types::{WlArgType, WlInterface, WlMsg, WlMsgType};
|
||||||
|
|
||||||
mod types;
|
mod types;
|
||||||
|
|
||||||
#[proc_macro]
|
pub fn generate_from_dir(p: impl AsRef<Path>) -> String {
|
||||||
pub fn wayland_proto_gen(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
let (gen_code, (add_parsers_fn, add_object_types_fn)): (Vec<_>, (Vec<_>, Vec<_>)) =
|
||||||
let input: LitStr = parse_macro_input!(item);
|
std::fs::read_dir(p)
|
||||||
let p = PathBuf::from(input.value());
|
.expect("cannot open directory")
|
||||||
let file_name = p.file_stem().expect("No file name provided");
|
.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 xml_str = std::fs::read_to_string(&p).expect("Unable to read from file");
|
||||||
let mut reader = quick_xml::Reader::from_str(&xml_str);
|
let mut reader = quick_xml::Reader::from_str(&xml_str);
|
||||||
reader.config_mut().trim_text(true);
|
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
|
// 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
|
// 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 )*
|
#( #code )*
|
||||||
|
|
||||||
fn #add_parsers_fn() {
|
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() {
|
fn #add_object_types_fn() {
|
||||||
#( WL_KNOWN_OBJECT_TYPES.write().unwrap().insert(#known_interface_names, #known_interface_consts); )*
|
#( 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(
|
fn handle_interface(
|
||||||
|
|
|
@ -113,6 +113,7 @@ impl WlMsg {
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
|
#[allow(unused)]
|
||||||
pub struct #struct_name<'a> {
|
pub struct #struct_name<'a> {
|
||||||
_phantom: std::marker::PhantomData<&'a ()>,
|
_phantom: std::marker::PhantomData<&'a ()>,
|
||||||
#( pub #field_names: #field_types, )*
|
#( pub #field_names: #field_types, )*
|
||||||
|
@ -145,6 +146,7 @@ impl WlMsg {
|
||||||
WlMsgType::#msg_type
|
WlMsgType::#msg_type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
fn try_from_msg_impl(msg: &crate::codec::WlRawMsg) -> WaylandProtocolParsingOutcome<#struct_name> {
|
fn try_from_msg_impl(msg: &crate::codec::WlRawMsg) -> WaylandProtocolParsingOutcome<#struct_name> {
|
||||||
let payload = msg.payload();
|
let payload = msg.payload();
|
||||||
let mut pos = 0usize;
|
let mut pos = 0usize;
|
||||||
|
|
13
src/proto.rs
13
src/proto.rs
|
@ -7,7 +7,6 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use byteorder::ByteOrder;
|
use byteorder::ByteOrder;
|
||||||
use protogen::wayland_proto_gen;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
codec::WlRawMsg,
|
codec::WlRawMsg,
|
||||||
|
@ -218,13 +217,5 @@ pub fn lookup_known_object_type(name: &str) -> Option<WlObjectType> {
|
||||||
/// The default object ID of wl_display
|
/// The default object ID of wl_display
|
||||||
pub const WL_DISPLAY_OBJECT_ID: u32 = 1;
|
pub const WL_DISPLAY_OBJECT_ID: u32 = 1;
|
||||||
|
|
||||||
wayland_proto_gen!("proto/wayland.xml");
|
// Include code generated by build.rs
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/proto_generated.rs"));
|
||||||
/// 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();
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue