Skip to content

Commit

Permalink
Generate aliases with "z" stripped for stable dmabuf protocol
Browse files Browse the repository at this point in the history
  • Loading branch information
PolyMeilex committed Jan 25, 2024
1 parent fd39fd4 commit d230850
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 35 deletions.
18 changes: 18 additions & 0 deletions wayland-protocols/src/wp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,24 @@ pub mod linux_dmabuf {
[]
);
}

/// Stable version 1 (Aliased to zv1, as zv1 became stable without name change)
pub mod v1 {
#[cfg(feature = "client")]
pub mod client {
//! Client-side API of this protocol
pub use super::super::zv1::client::__interfaces;
use super::super::zv1::client::*;
wayland_scanner::__generate_aliases!("./protocols/stable/linux-dmabuf/linux-dmabuf-v1.xml");
}
#[cfg(feature = "server")]
pub mod server {
//! Server-side API of this protocol
pub use super::super::zv1::server::__interfaces;
use super::super::zv1::server::*;
wayland_scanner::__generate_aliases!("./protocols/stable/linux-dmabuf/linux-dmabuf-v1.xml");
}
}
}

#[cfg(feature = "unstable")]
Expand Down
41 changes: 41 additions & 0 deletions wayland-scanner/src/aliases_gen.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use proc_macro2::{Ident, Span, TokenStream};

use quote::quote;

use crate::{
protocol::{Interface, Protocol},
util::{description_to_doc_attr, snake_to_camel},
};

pub fn generate_aliases(protocol: &Protocol) -> TokenStream {
protocol.interfaces.iter().map(generate_aliases_for).collect()
}

fn generate_aliases_for(interface: &Interface) -> TokenStream {
let zname = &interface.name;
let name = interface.name.strip_prefix('z').unwrap_or(zname);

let zmod_name = Ident::new(zname, Span::call_site());
let zmod = quote!(super::#zmod_name);

let ziface_name = Ident::new(&snake_to_camel(zname), Span::call_site());
let iface_name = Ident::new(&snake_to_camel(name), Span::call_site());

let mod_name = Ident::new(name, Span::call_site());
let mod_doc = interface.description.as_ref().map(description_to_doc_attr);

let enums = crate::common::generate_enum_reexports_for(&zmod, interface);
let sinces =
crate::common::gen_msg_constant_reexports(&zmod, &interface.requests, &interface.events);

quote! {
#mod_doc
pub mod #mod_name {
#enums
#sinces
pub use #zmod::Event;
pub use #zmod::Request;
pub use #zmod::#ziface_name as #iface_name;
}
}
}
74 changes: 69 additions & 5 deletions wayland-scanner/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,26 @@ use quote::{format_ident, quote, ToTokens};

use crate::{protocol::*, util::*, Side};

fn enum_ident(e: &Enum) -> Ident {
Ident::new(&snake_to_camel(&e.name), Span::call_site())
}

pub(crate) fn generate_enum_reexports_for(
path: &TokenStream,
interface: &Interface,
) -> TokenStream {
interface
.enums
.iter()
.map(enum_ident)
.map(|ident| {
quote! {
pub use #path::#ident;
}
})
.collect()
}

pub(crate) fn generate_enums_for(interface: &Interface) -> TokenStream {
interface.enums.iter().map(ToTokens::into_token_stream).collect()
}
Expand All @@ -16,7 +36,7 @@ impl ToTokens for Enum {
let enum_impl;

let doc_attr = self.description.as_ref().map(description_to_doc_attr);
let ident = Ident::new(&snake_to_camel(&self.name), Span::call_site());
let ident = enum_ident(self);

if self.bitfield {
let entries = self.entries.iter().map(|entry| {
Expand Down Expand Up @@ -122,10 +142,54 @@ impl ToTokens for Enum {
}
}

fn req_since(msg: &Message) -> Ident {
format_ident!("REQ_{}_SINCE", msg.name.to_ascii_uppercase())
}

fn req_opcode(msg: &Message) -> Ident {
format_ident!("REQ_{}_OPCODE", msg.name.to_ascii_uppercase())
}

fn event_since(msg: &Message) -> Ident {
format_ident!("EVT_{}_SINCE", msg.name.to_ascii_uppercase())
}

fn event_opcode(msg: &Message) -> Ident {
format_ident!("EVT_{}_OPCODE", msg.name.to_ascii_uppercase())
}

pub(crate) fn gen_msg_constant_reexports(
path: &TokenStream,
requests: &[Message],
events: &[Message],
) -> TokenStream {
let req_constants = requests.iter().map(|msg| {
let since_cstname = req_since(msg);
let opcode_cstname = req_opcode(msg);
quote! {
pub use #path::#since_cstname;
pub use #path::#opcode_cstname;
}
});
let evt_constants = events.iter().map(|msg| {
let since_cstname = event_since(msg);
let opcode_cstname = event_opcode(msg);
quote! {
pub use #path::#since_cstname;
pub use #path::#opcode_cstname;
}
});

quote! {
#(#req_constants)*
#(#evt_constants)*
}
}

pub(crate) fn gen_msg_constants(requests: &[Message], events: &[Message]) -> TokenStream {
let req_constants = requests.iter().enumerate().map(|(opcode, msg)| {
let since_cstname = format_ident!("REQ_{}_SINCE", msg.name.to_ascii_uppercase());
let opcode_cstname = format_ident!("REQ_{}_OPCODE", msg.name.to_ascii_uppercase());
let since_cstname = req_since(msg);
let opcode_cstname = req_opcode(msg);
let since = msg.since;
let opcode = opcode as u16;
quote! {
Expand All @@ -136,8 +200,8 @@ pub(crate) fn gen_msg_constants(requests: &[Message], events: &[Message]) -> Tok
}
});
let evt_constants = events.iter().enumerate().map(|(opcode, msg)| {
let since_cstname = format_ident!("EVT_{}_SINCE", msg.name.to_ascii_uppercase());
let opcode_cstname = format_ident!("EVT_{}_OPCODE", msg.name.to_ascii_uppercase());
let since_cstname = event_since(msg);
let opcode_cstname = event_opcode(msg);
let since = msg.since;
let opcode = opcode as u16;
quote! {
Expand Down
55 changes: 25 additions & 30 deletions wayland-scanner/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,12 @@
//! }
//! ```
use std::{ffi::OsString, path::PathBuf};
use std::{
ffi::{OsStr, OsString},
path::PathBuf,
};

mod aliases_gen;
mod c_interfaces;
mod client_gen;
mod common;
Expand All @@ -48,10 +52,7 @@ mod server_gen;
mod token;
mod util;

/// Proc-macro for generating low-level interfaces associated with an XML specification
#[proc_macro]
pub fn generate_interfaces(stream: proc_macro::TokenStream) -> proc_macro::TokenStream {
let path: OsString = token::parse_lit_str_token(stream).into();
fn open_file(path: &OsStr) -> protocol::Protocol {
let path = if let Some(manifest_dir) = std::env::var_os("CARGO_MANIFEST_DIR") {
let mut buf = PathBuf::from(manifest_dir);
buf.push(path);
Expand All @@ -63,45 +64,39 @@ pub fn generate_interfaces(stream: proc_macro::TokenStream) -> proc_macro::Token
Ok(file) => file,
Err(e) => panic!("Failed to open protocol file {}: {}", path.display(), e),
};
let protocol = parse::parse(file);
parse::parse(file)
}

/// Proc-macro for generating low-level interfaces associated with an XML specification
#[proc_macro]
pub fn generate_interfaces(stream: proc_macro::TokenStream) -> proc_macro::TokenStream {
let path: OsString = token::parse_lit_str_token(stream).into();
let protocol = open_file(&path);
interfaces::generate(&protocol, true).into()
}

/// Proc-macro for generating client-side API associated with an XML specification
#[doc(hidden)]
#[proc_macro]
pub fn __generate_aliases(stream: proc_macro::TokenStream) -> proc_macro::TokenStream {
let path: OsString = token::parse_lit_str_token(stream).into();
let protocol = open_file(&path);
aliases_gen::generate_aliases(&protocol).into()
}

/// Proc-macro for generating client-side API associated with an XML specification
#[proc_macro]
pub fn generate_client_code(stream: proc_macro::TokenStream) -> proc_macro::TokenStream {
let path: OsString = token::parse_lit_str_token(stream).into();
let path = if let Some(manifest_dir) = std::env::var_os("CARGO_MANIFEST_DIR") {
let mut buf = PathBuf::from(manifest_dir);
buf.push(path);
buf
} else {
path.into()
};
let file = match std::fs::File::open(&path) {
Ok(file) => file,
Err(e) => panic!("Failed to open protocol file {}: {}", path.display(), e),
};
let protocol = parse::parse(file);
let protocol = open_file(&path);
client_gen::generate_client_objects(&protocol).into()
}

/// Proc-macro for generating server-side API associated with an XML specification
#[proc_macro]
pub fn generate_server_code(stream: proc_macro::TokenStream) -> proc_macro::TokenStream {
let path: OsString = token::parse_lit_str_token(stream).into();
let path = if let Some(manifest_dir) = std::env::var_os("CARGO_MANIFEST_DIR") {
let mut buf = PathBuf::from(manifest_dir);
buf.push(path);
buf
} else {
path.into()
};
let file = match std::fs::File::open(&path) {
Ok(file) => file,
Err(e) => panic!("Failed to open protocol file {}: {}", path.display(), e),
};
let protocol = parse::parse(file);
let protocol = open_file(&path);
server_gen::generate_server_objects(&protocol).into()
}

Expand Down

0 comments on commit d230850

Please sign in to comment.