Skip to content

Commit

Permalink
Bases of codegen & enums
Browse files Browse the repository at this point in the history
  • Loading branch information
elinorbgr committed Feb 25, 2018
1 parent 9416cf5 commit 61d0c22
Show file tree
Hide file tree
Showing 8 changed files with 256 additions and 29 deletions.
1 change: 1 addition & 0 deletions wayland-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ travis-ci = { repository = "smithay/wayland-rs" }
[dependencies]
wayland-commons = { version = "0.20.0", path = "../wayland-commons" }
wayland-sys = { version = "0.20.0", features = ["client"], path = "../wayland-sys", optional = true }
bitflags = "1.0"
libc = "0.2"

[build-dependencies]
Expand Down
19 changes: 18 additions & 1 deletion wayland-client/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#[macro_use]
extern crate bitflags;
extern crate libc;

extern crate wayland_commons;
Expand All @@ -6,4 +8,19 @@ extern crate wayland_commons;
extern crate wayland_sys;

mod proxy;
pub use proxy::{Proxy, NewProxy};
pub use proxy::{NewProxy, Proxy};

mod generated {
#![allow(dead_code, non_camel_case_types, unused_unsafe, unused_variables)]
#![allow(non_upper_case_globals, non_snake_case, unused_imports)]
#![allow(missing_docs)]

#[cfg(feature = "native_lib")]
mod c_interfaces {
include!(concat!(env!("OUT_DIR"), "/wayland_c_interfaces.rs"));
}
#[cfg(feature = "native_lib")]
mod c_api {
include!(concat!(env!("OUT_DIR"), "/wayland_c_api.rs"));
}
}
32 changes: 29 additions & 3 deletions wayland-scanner/src/c_code_gen.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,40 @@
use std::io::Result as IOResult;
use protocol::*;
use std::cmp;
use std::io::Write;

use common_gen::*;
use protocol::*;
use util::*;

pub(crate) fn write_protocol_client<O: Write>(protocol: Protocol, out: &mut O) -> IOResult<()> {
// TODO
write_prefix(&protocol, out)?;

for iface in &protocol.interfaces {
writeln!(out, "pub mod {} {{", iface.name)?;

write_enums(&iface.enums, out)?;

writeln!(out, "}}\n")?;
}

Ok(())
}

pub(crate) fn write_protocol_server<O: Write>(protocol: Protocol, out: &mut O) -> IOResult<()> {
// TODO
write_prefix(&protocol, out)?;

for iface in &protocol.interfaces {
// display and registry are handled specially
if iface.name == "wl_display" || iface.name == "wl_registry" {
continue;
}

writeln!(out, "pub mod {} {{", iface.name)?;

write_enums(&iface.enums, out)?;

writeln!(out, "}}\n")?;
}

Ok(())
}
23 changes: 11 additions & 12 deletions wayland-scanner/src/c_interface_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ pub(crate) fn generate_interfaces<O: Write>(protocol: Protocol, out: &mut O) ->
writeln!(out, "/*\n{}\n*/\n", text)?;
}

writeln!(out,
r#"
writeln!(
out,
r#"
use std::os::raw::{{c_char, c_void}};
use wayland_sys::common::*;"#
)?;
Expand All @@ -23,22 +24,20 @@ use wayland_sys::common::*;"#
//

let longest_nulls = protocol.interfaces.iter().fold(0, |max, interface| {
let request_longest_null = interface
.requests
.iter()
.fold(0, |max, request| if request.all_null() {
let request_longest_null = interface.requests.iter().fold(0, |max, request| {
if request.all_null() {
cmp::max(request.args.len(), max)
} else {
max
});
let events_longest_null = interface
.events
.iter()
.fold(0, |max, event| if event.all_null() {
}
});
let events_longest_null = interface.events.iter().fold(0, |max, event| {
if event.all_null() {
cmp::max(event.args.len(), max)
} else {
max
});
}
});
cmp::max(max, cmp::max(request_longest_null, events_longest_null))
});

Expand Down
173 changes: 173 additions & 0 deletions wayland-scanner/src/common_gen.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
use std::io::Result as IOResult;
use std::cmp;
use std::io::Write;

use protocol::*;
use util::*;

pub(crate) fn write_prefix<O: Write>(protocol: &Protocol, out: &mut O) -> IOResult<()> {
writeln!(
out,
r#"
//
// This file was auto-generated, do not edit directly.
//
"#
)?;
if let Some(ref text) = protocol.copyright {
writeln!(out, "/*\n{}\n*/\n", text)?;
}
Ok(())
}

pub(crate) fn write_enums<O: Write>(enums: &[Enum], out: &mut O) -> IOResult<()> {
// generate contents
for enu in enums {
if enu.bitfield {
writeln!(out, " bitflags! {{")?;
if let Some((ref short, ref long)) = enu.description {
write_doc(Some(short), long, false, out, 2)?;
}
writeln!(
out,
" pub struct {}: u32 {{",
snake_to_camel(&enu.name)
)?;
for entry in &enu.entries {
if let Some((ref short, ref long)) = entry.description {
write_doc(Some(short), long, false, out, 3)?;
} else if let Some(ref summary) = entry.summary {
writeln!(out, " /// {}", summary)?;
}
writeln!(
out,
" const {}{} = {};",
if entry.name.chars().next().unwrap().is_numeric() {
"_"
} else {
""
},
snake_to_camel(&entry.name),
entry.value
)?;
}
writeln!(out, " }}")?;
writeln!(out, " }}")?;
writeln!(out, " impl {} {{", snake_to_camel(&enu.name))?;
writeln!(
out,
" pub fn from_raw(n: u32) -> Option<{}> {{",
snake_to_camel(&enu.name)
)?;
writeln!(
out,
" Some({}::from_bits_truncate(n))",
snake_to_camel(&enu.name)
)?;
writeln!(
out,
r#"
}}
pub fn to_raw(&self) -> u32 {{
self.bits()
}}
}}
"#
)?;
} else {
// if enu.bitfield
if let Some((ref short, ref long)) = enu.description {
write_doc(Some(short), long, false, out, 1)?;
}
writeln!(
out,
r#"
#[repr(u32)]
#[derive(Copy,Clone,Debug,PartialEq)]
pub enum {} {{"#,
snake_to_camel(&enu.name)
)?;
for entry in &enu.entries {
if let Some((ref short, ref long)) = entry.description {
write_doc(Some(short), long, false, out, 2)?;
} else if let Some(ref summary) = entry.summary {
writeln!(out, " /// {}", summary)?;
}
writeln!(
out,
" {}{} = {},",
if entry.name.chars().next().unwrap().is_numeric() {
"_"
} else {
""
},
snake_to_camel(&entry.name),
entry.value
)?;
}
writeln!(out, " }}")?;

writeln!(out, " impl {} {{", snake_to_camel(&enu.name))?;
writeln!(
out,
" pub fn from_raw(n: u32) -> Option<{}> {{",
snake_to_camel(&enu.name)
)?;
writeln!(out, " match n {{")?;
for entry in &enu.entries {
writeln!(
out,
" {} => Some({}::{}{}),",
entry.value,
snake_to_camel(&enu.name),
if entry.name.chars().next().unwrap().is_numeric() {
"_"
} else {
""
},
snake_to_camel(&entry.name)
)?;
}
writeln!(
out,
r#"
_ => Option::None
}}
}}
pub fn to_raw(&self) -> u32 {{
*self as u32
}}
}}
"#
)?;
}
}
Ok(())
}

pub(crate) fn write_doc<O: Write>(
short: Option<&str>,
long: &str,
internal: bool,
out: &mut O,
indent: usize,
) -> IOResult<()> {
let p = if internal { '!' } else { '/' };
if let Some(txt) = short {
for _ in 0..indent {
write!(out, " ")?
}
writeln!(out, "//{} {}", p, txt)?;
for _ in 0..indent {
write!(out, " ")?
}
writeln!(out, "//{}", p)?;
}
for l in long.lines() {
for _ in 0..indent {
write!(out, " ")?
}
writeln!(out, "//{} {}", p, l.trim())?;
}
Ok(())
}
17 changes: 5 additions & 12 deletions wayland-scanner/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
//! use std::env::var;
//! use std::path::Path;
//!
//! use wayland_scanner::{Side, generate_code, generate_interfaces};
//! use wayland_scanner::{Side, generate_c_code, generate_c_interfaces};
//!
//! fn main() {
//! // Location of the xml file, relative to the `Cargo.toml`
Expand All @@ -40,14 +40,14 @@
//! let out_dir_str = var("OUT_DIR").unwrap();
//! let out_dir = Path::new(&out_dir_str);
//!
//! generate_code(
//! generate_c_code(
//! protocol_file,
//! out_dir.join("my_protocol_api.rs"),
//! Side::Client, // Replace by `Side::Server` for server-side code
//! );
//!
//! // interfaces are the same for client and server
//! generate_interfaces(
//! generate_c_interfaces(
//! protocol_file,
//! out_dir.join("my_protocol_interfaces.rs")
//! );
Expand Down Expand Up @@ -83,17 +83,9 @@
//! }
//!
//! pub mod client {
//! // These import are mandatory, and need to by `pub`, because
//! // submodules in the generated code will try to import them.
//! // Hopefully someday pub(restricted) and friends will
//! // allow for a cleaner way to do that
//! #[doc(hidden)] pub use wayland_client::{Proxy, Handler, EventQueueHandle, RequestResult};
//! // Replace the above line with this for server-side:
//! // #[doc(hidden)] pub use wayland_server::{Resource, Handler, EventLoopHandle, EventResult};
//! #[doc(hidden)] pub use super::interfaces;
//! // If you protocol interacts with objects from other protocols, you'll need to import
//! // their modules, like so:
//! #[doc(hidden)] pub use wayland_client::protocol::{wl_surface, wl_region};
//! pub(crate) use wayland_client::protocol::{wl_surface, wl_region};
//! include!(concat!(env!("OUT_DIR"), "/my_protocol_code.rs"));
//! }
//! }
Expand All @@ -111,6 +103,7 @@ mod util;
mod parse;
mod protocol;
mod side;
mod common_gen;
mod c_interface_gen;
mod c_code_gen;

Expand Down
1 change: 1 addition & 0 deletions wayland-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ travis-ci = { repository = "smithay/wayland-rs" }
[dependencies]
wayland-commons = { version = "0.20.0", path = "../wayland-commons" }
wayland-sys = { version = "0.20.0", features = ["server"], path = "../wayland-sys", optional = true }
bitflags = "1.0"
libc = "0.2"

[build-dependencies]
Expand Down
19 changes: 18 additions & 1 deletion wayland-server/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#[macro_use]
extern crate bitflags;
extern crate libc;

extern crate wayland_commons;
Expand All @@ -6,6 +8,21 @@ extern crate wayland_commons;
extern crate wayland_sys;

mod resource;
pub use resource::{Resource, NewResource};
pub use resource::{NewResource, Resource};

struct Client;

mod generated {
#![allow(dead_code, non_camel_case_types, unused_unsafe, unused_variables)]
#![allow(non_upper_case_globals, non_snake_case, unused_imports)]
#![allow(missing_docs)]

#[cfg(feature = "native_lib")]
mod c_interfaces {
include!(concat!(env!("OUT_DIR"), "/wayland_c_interfaces.rs"));
}
#[cfg(feature = "native_lib")]
mod c_api {
include!(concat!(env!("OUT_DIR"), "/wayland_c_api.rs"));
}
}

0 comments on commit 61d0c22

Please sign in to comment.