wiggle-generate: paramaterize library on module path to runtime (#1574)

* wiggle-generate: paramaterize library on module path to runtime

This change makes no functional difference to users who only use the
wiggle crate.

Add a parameter to the `Names` constructor that determines the module
that runtime components (e.g. GuestPtr, GuestError etc) of wiggle come
from. For `wiggle` users this is just `quote!(wiggle)`, but other
libraries which consume wiggle-generate may wrap and re-export wiggle
under some other path, and not want their consumers to have to know
about the wiggle dependency, e.g. `quote!(my_crate::some_path::wiggle)`.

* wiggle-generate,macro: move more logic into macro

better for code reuse elsewhere
This commit is contained in:
Pat Hickey
2020-04-22 07:16:21 -07:00
committed by GitHub
parent 65ef26b989
commit 25cbd8b591
14 changed files with 118 additions and 93 deletions

1
Cargo.lock generated
View File

@@ -2366,6 +2366,7 @@ dependencies = [
name = "wiggle-macro" name = "wiggle-macro"
version = "0.15.0" version = "0.15.0"
dependencies = [ dependencies = [
"quote",
"syn", "syn",
"wiggle", "wiggle",
"wiggle-generate", "wiggle-generate",

View File

@@ -12,7 +12,6 @@ use syn::{
pub struct Config { pub struct Config {
pub witx: WitxConf, pub witx: WitxConf,
pub ctx: CtxConf, pub ctx: CtxConf,
pub emit_metadata: bool,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@@ -60,7 +59,6 @@ impl Config {
ctx: ctx ctx: ctx
.take() .take()
.ok_or_else(|| Error::new(err_loc, "`ctx` field required"))?, .ok_or_else(|| Error::new(err_loc, "`ctx` field required"))?,
emit_metadata: false,
}) })
} }
} }

View File

@@ -13,6 +13,7 @@ pub fn define_func(
let funcname = func.name.as_str(); let funcname = func.name.as_str();
let ident = names.func(&func.name); let ident = names.func(&func.name);
let rt = names.runtime_mod();
let ctx_type = names.ctx_type(); let ctx_type = names.ctx_type();
let coretype = func.core_type(); let coretype = func.core_type();
@@ -23,7 +24,7 @@ pub fn define_func(
}); });
let abi_args = quote!( let abi_args = quote!(
ctx: &#ctx_type, memory: &dyn wiggle::GuestMemory, ctx: &#ctx_type, memory: &dyn #rt::GuestMemory,
#(#params),* #(#params),*
); );
let abi_ret = if let Some(ret) = &coretype.ret { let abi_ret = if let Some(ret) = &coretype.ret {
@@ -64,7 +65,7 @@ pub fn define_func(
let err_typename = names.type_ref(&tref, anon_lifetime()); let err_typename = names.type_ref(&tref, anon_lifetime());
let err_method = names.guest_error_conversion_method(&tref); let err_method = names.guest_error_conversion_method(&tref);
quote! { quote! {
let e = wiggle::GuestError::InFunc { funcname: #funcname, location: #location, err: Box::new(e.into()) }; let e = #rt::GuestError::InFunc { funcname: #funcname, location: #location, err: Box::new(e.into()) };
let err: #err_typename = GuestErrorConversion::#err_method(ctx, e); // XXX replace with conversion method on trait! let err: #err_typename = GuestErrorConversion::#err_method(ctx, e); // XXX replace with conversion method on trait!
return #abi_ret::from(err); return #abi_ret::from(err);
} }
@@ -139,7 +140,7 @@ pub fn define_func(
let success = if let Some(ref err_type) = err_type { let success = if let Some(ref err_type) = err_type {
let err_typename = names.type_ref(&err_type, anon_lifetime()); let err_typename = names.type_ref(&err_type, anon_lifetime());
quote! { quote! {
let success:#err_typename = wiggle::GuestErrorType::success(); let success:#err_typename = #rt::GuestErrorType::success();
#[cfg(feature = "trace_log")] #[cfg(feature = "trace_log")]
{ {
log::trace!(" | errno={}", success); log::trace!(" | errno={}", success);
@@ -185,6 +186,7 @@ fn marshal_arg(
param: &witx::InterfaceFuncParam, param: &witx::InterfaceFuncParam,
error_handling: TokenStream, error_handling: TokenStream,
) -> TokenStream { ) -> TokenStream {
let rt = names.runtime_mod();
let tref = &param.tref; let tref = &param.tref;
let interface_typename = names.type_ref(&tref, anon_lifetime()); let interface_typename = names.type_ref(&tref, anon_lifetime());
@@ -208,7 +210,7 @@ fn marshal_arg(
let arg_name = names.func_ptr_binding(&param.name); let arg_name = names.func_ptr_binding(&param.name);
let name = names.func_param(&param.name); let name = names.func_param(&param.name);
quote! { quote! {
let #name = match wiggle::GuestPtr::<#pointee_type>::new(memory, #arg_name as u32).read() { let #name = match #rt::GuestPtr::<#pointee_type>::new(memory, #arg_name as u32).read() {
Ok(r) => r, Ok(r) => r,
Err(e) => { Err(e) => {
#error_handling #error_handling
@@ -254,7 +256,7 @@ fn marshal_arg(
let len_name = names.func_len_binding(&param.name); let len_name = names.func_len_binding(&param.name);
let name = names.func_param(&param.name); let name = names.func_param(&param.name);
quote! { quote! {
let #name = wiggle::GuestPtr::<#lifetime, str>::new(memory, (#ptr_name as u32, #len_name as u32)); let #name = #rt::GuestPtr::<#lifetime, str>::new(memory, (#ptr_name as u32, #len_name as u32));
} }
} }
}, },
@@ -262,7 +264,7 @@ fn marshal_arg(
let pointee_type = names.type_ref(pointee, anon_lifetime()); let pointee_type = names.type_ref(pointee, anon_lifetime());
let name = names.func_param(&param.name); let name = names.func_param(&param.name);
quote! { quote! {
let #name = wiggle::GuestPtr::<#pointee_type>::new(memory, #name as u32); let #name = #rt::GuestPtr::<#pointee_type>::new(memory, #name as u32);
} }
} }
witx::Type::Struct(_) => read_conversion, witx::Type::Struct(_) => read_conversion,
@@ -272,7 +274,7 @@ fn marshal_arg(
let len_name = names.func_len_binding(&param.name); let len_name = names.func_len_binding(&param.name);
let name = names.func_param(&param.name); let name = names.func_param(&param.name);
quote! { quote! {
let #name = wiggle::GuestPtr::<[#pointee_type]>::new(memory, (#ptr_name as u32, #len_name as u32)); let #name = #rt::GuestPtr::<[#pointee_type]>::new(memory, (#ptr_name as u32, #len_name as u32));
} }
} }
witx::Type::Union(_u) => read_conversion, witx::Type::Union(_u) => read_conversion,
@@ -292,6 +294,7 @@ fn marshal_result<F>(
where where
F: Fn(&str) -> TokenStream, F: Fn(&str) -> TokenStream,
{ {
let rt = names.runtime_mod();
let tref = &result.tref; let tref = &result.tref;
let write_val_to_ptr = { let write_val_to_ptr = {
@@ -300,7 +303,7 @@ where
let ptr_name = names.func_ptr_binding(&result.name); let ptr_name = names.func_ptr_binding(&result.name);
let ptr_err_handling = error_handling(&format!("{}:result_ptr_mut", result.name.as_str())); let ptr_err_handling = error_handling(&format!("{}:result_ptr_mut", result.name.as_str()));
let pre = quote! { let pre = quote! {
let #ptr_name = wiggle::GuestPtr::<#pointee_type>::new(memory, #ptr_name as u32); let #ptr_name = #rt::GuestPtr::<#pointee_type>::new(memory, #ptr_name as u32);
}; };
// trait binding returns func_param name. // trait binding returns func_param name.
let val_name = names.func_param(&result.name); let val_name = names.func_param(&result.name);

View File

@@ -16,17 +16,17 @@ pub use module_trait::define_module_trait;
pub use names::Names; pub use names::Names;
pub use types::define_datatype; pub use types::define_datatype;
pub fn generate(doc: &witx::Document, config: &Config) -> TokenStream { pub fn generate(doc: &witx::Document, names: &Names) -> TokenStream {
// TODO at some point config should grow more ability to configure name // TODO at some point config should grow more ability to configure name
// overrides. // overrides.
let names = Names::new(&config.ctx.name); let rt = names.runtime_mod();
let types = doc.typenames().map(|t| define_datatype(&names, &t)); let types = doc.typenames().map(|t| define_datatype(&names, &t));
let guest_error_methods = doc.error_types().map(|t| { let guest_error_methods = doc.error_types().map(|t| {
let typename = names.type_ref(&t, anon_lifetime()); let typename = names.type_ref(&t, anon_lifetime());
let err_method = names.guest_error_conversion_method(&t); let err_method = names.guest_error_conversion_method(&t);
quote!(fn #err_method(&self, e: wiggle::GuestError) -> #typename;) quote!(fn #err_method(&self, e: #rt::GuestError) -> #typename;)
}); });
let guest_error_conversion = quote! { let guest_error_conversion = quote! {
pub trait GuestErrorConversion { pub trait GuestErrorConversion {
@@ -53,26 +53,24 @@ pub fn generate(doc: &witx::Document, config: &Config) -> TokenStream {
) )
}); });
let metadata = if config.emit_metadata {
let doc_text = &format!("{}", doc);
quote! {
pub mod metadata {
pub const DOC_TEXT: &str = #doc_text;
pub fn document() -> wiggle::witx::Document {
wiggle::witx::parse(DOC_TEXT).unwrap()
}
}
}
} else {
quote!()
};
quote!( quote!(
pub mod types { pub mod types {
#(#types)* #(#types)*
#guest_error_conversion #guest_error_conversion
} }
#(#modules)* #(#modules)*
#metadata
) )
} }
pub fn generate_metadata(doc: &witx::Document, names: &Names) -> TokenStream {
let rt = names.runtime_mod();
let doc_text = &format!("{}", doc);
quote! {
pub mod metadata {
pub const DOC_TEXT: &str = #doc_text;
pub fn document() -> #rt::witx::Document {
#rt::witx::parse(DOC_TEXT).unwrap()
}
}
}
}

View File

@@ -7,24 +7,32 @@ use crate::lifetimes::LifetimeExt;
pub struct Names { pub struct Names {
ctx_type: Ident, ctx_type: Ident,
runtime_mod: TokenStream,
} }
impl Names { impl Names {
pub fn new(ctx_type: &Ident) -> Names { pub fn new(ctx_type: &Ident, runtime_mod: TokenStream) -> Names {
Names { Names {
ctx_type: ctx_type.clone(), ctx_type: ctx_type.clone(),
runtime_mod,
} }
} }
pub fn ctx_type(&self) -> Ident { pub fn ctx_type(&self) -> Ident {
self.ctx_type.clone() self.ctx_type.clone()
} }
pub fn runtime_mod(&self) -> TokenStream {
self.runtime_mod.clone()
}
pub fn type_(&self, id: &Id) -> TokenStream { pub fn type_(&self, id: &Id) -> TokenStream {
let ident = format_ident!("{}", id.as_str().to_camel_case()); let ident = format_ident!("{}", id.as_str().to_camel_case());
quote!(#ident) quote!(#ident)
} }
pub fn builtin_type(&self, b: BuiltinType, lifetime: TokenStream) -> TokenStream { pub fn builtin_type(&self, b: BuiltinType, lifetime: TokenStream) -> TokenStream {
match b { match b {
BuiltinType::String => quote!(wiggle::GuestPtr<#lifetime, str>), BuiltinType::String => {
let rt = self.runtime_mod();
quote!(#rt::GuestPtr<#lifetime, str>)
}
BuiltinType::U8 => quote!(u8), BuiltinType::U8 => quote!(u8),
BuiltinType::U16 => quote!(u16), BuiltinType::U16 => quote!(u16),
BuiltinType::U32 => quote!(u32), BuiltinType::U32 => quote!(u32),
@@ -61,12 +69,14 @@ impl Names {
TypeRef::Value(ty) => match &**ty { TypeRef::Value(ty) => match &**ty {
Type::Builtin(builtin) => self.builtin_type(*builtin, lifetime.clone()), Type::Builtin(builtin) => self.builtin_type(*builtin, lifetime.clone()),
Type::Pointer(pointee) | Type::ConstPointer(pointee) => { Type::Pointer(pointee) | Type::ConstPointer(pointee) => {
let rt = self.runtime_mod();
let pointee_type = self.type_ref(&pointee, lifetime.clone()); let pointee_type = self.type_ref(&pointee, lifetime.clone());
quote!(wiggle::GuestPtr<#lifetime, #pointee_type>) quote!(#rt::GuestPtr<#lifetime, #pointee_type>)
} }
Type::Array(pointee) => { Type::Array(pointee) => {
let rt = self.runtime_mod();
let pointee_type = self.type_ref(&pointee, lifetime.clone()); let pointee_type = self.type_ref(&pointee, lifetime.clone());
quote!(wiggle::GuestPtr<#lifetime, [#pointee_type]>) quote!(#rt::GuestPtr<#lifetime, [#pointee_type]>)
} }
_ => unimplemented!("anonymous type ref {:?}", tref), _ => unimplemented!("anonymous type ref {:?}", tref),
}, },

View File

@@ -6,6 +6,7 @@ use quote::quote;
pub(super) fn define_enum(names: &Names, name: &witx::Id, e: &witx::EnumDatatype) -> TokenStream { pub(super) fn define_enum(names: &Names, name: &witx::Id, e: &witx::EnumDatatype) -> TokenStream {
let ident = names.type_(&name); let ident = names.type_(&name);
let rt = names.runtime_mod();
let repr = int_repr_tokens(e.repr); let repr = int_repr_tokens(e.repr);
let abi_repr = atom_token(match e.repr { let abi_repr = atom_token(match e.repr {
@@ -46,18 +47,18 @@ pub(super) fn define_enum(names: &Names, name: &witx::Id, e: &witx::EnumDatatype
} }
impl ::std::convert::TryFrom<#repr> for #ident { impl ::std::convert::TryFrom<#repr> for #ident {
type Error = wiggle::GuestError; type Error = #rt::GuestError;
fn try_from(value: #repr) -> Result<#ident, wiggle::GuestError> { fn try_from(value: #repr) -> Result<#ident, #rt::GuestError> {
match value as usize { match value as usize {
#(#tryfrom_repr_cases),*, #(#tryfrom_repr_cases),*,
_ => Err(wiggle::GuestError::InvalidEnumValue(stringify!(#ident))), _ => Err( #rt::GuestError::InvalidEnumValue(stringify!(#ident))),
} }
} }
} }
impl ::std::convert::TryFrom<#abi_repr> for #ident { impl ::std::convert::TryFrom<#abi_repr> for #ident {
type Error = wiggle::GuestError; type Error = #rt::GuestError;
fn try_from(value: #abi_repr) -> Result<#ident, wiggle::GuestError> { fn try_from(value: #abi_repr) -> Result<#ident, #rt::GuestError> {
#ident::try_from(value as #repr) #ident::try_from(value as #repr)
} }
} }
@@ -76,7 +77,7 @@ pub(super) fn define_enum(names: &Names, name: &witx::Id, e: &witx::EnumDatatype
} }
} }
impl<'a> wiggle::GuestType<'a> for #ident { impl<'a> #rt::GuestType<'a> for #ident {
fn guest_size() -> u32 { fn guest_size() -> u32 {
#repr::guest_size() #repr::guest_size()
} }
@@ -85,23 +86,23 @@ pub(super) fn define_enum(names: &Names, name: &witx::Id, e: &witx::EnumDatatype
#repr::guest_align() #repr::guest_align()
} }
fn read(location: &wiggle::GuestPtr<#ident>) -> Result<#ident, wiggle::GuestError> { fn read(location: & #rt::GuestPtr<#ident>) -> Result<#ident, #rt::GuestError> {
use std::convert::TryFrom; use std::convert::TryFrom;
let reprval = #repr::read(&location.cast())?; let reprval = #repr::read(&location.cast())?;
let value = #ident::try_from(reprval)?; let value = #ident::try_from(reprval)?;
Ok(value) Ok(value)
} }
fn write(location: &wiggle::GuestPtr<'_, #ident>, val: Self) fn write(location: & #rt::GuestPtr<'_, #ident>, val: Self)
-> Result<(), wiggle::GuestError> -> Result<(), #rt::GuestError>
{ {
#repr::write(&location.cast(), #repr::from(val)) #repr::write(&location.cast(), #repr::from(val))
} }
} }
unsafe impl <'a> wiggle::GuestTypeTransparent<'a> for #ident { unsafe impl <'a> #rt::GuestTypeTransparent<'a> for #ident {
#[inline] #[inline]
fn validate(location: *mut #ident) -> Result<(), wiggle::GuestError> { fn validate(location: *mut #ident) -> Result<(), #rt::GuestError> {
use std::convert::TryFrom; use std::convert::TryFrom;
// Validate value in memory using #ident::try_from(reprval) // Validate value in memory using #ident::try_from(reprval)
let reprval = unsafe { (location as *mut #repr).read() }; let reprval = unsafe { (location as *mut #repr).read() };

View File

@@ -6,6 +6,7 @@ use quote::quote;
use std::convert::TryFrom; use std::convert::TryFrom;
pub(super) fn define_flags(names: &Names, name: &witx::Id, f: &witx::FlagsDatatype) -> TokenStream { pub(super) fn define_flags(names: &Names, name: &witx::Id, f: &witx::FlagsDatatype) -> TokenStream {
let rt = names.runtime_mod();
let ident = names.type_(&name); let ident = names.type_(&name);
let repr = int_repr_tokens(f.repr); let repr = int_repr_tokens(f.repr);
let abi_repr = atom_token(match f.repr { let abi_repr = atom_token(match f.repr {
@@ -116,10 +117,10 @@ pub(super) fn define_flags(names: &Names, name: &witx::Id, f: &witx::FlagsDataty
} }
impl ::std::convert::TryFrom<#repr> for #ident { impl ::std::convert::TryFrom<#repr> for #ident {
type Error = wiggle::GuestError; type Error = #rt::GuestError;
fn try_from(value: #repr) -> Result<Self, wiggle::GuestError> { fn try_from(value: #repr) -> Result<Self, #rt::GuestError> {
if #repr::from(!#ident::all()) & value != 0 { if #repr::from(!#ident::all()) & value != 0 {
Err(wiggle::GuestError::InvalidFlagValue(stringify!(#ident))) Err(#rt::GuestError::InvalidFlagValue(stringify!(#ident)))
} else { } else {
Ok(#ident(value)) Ok(#ident(value))
} }
@@ -127,8 +128,8 @@ pub(super) fn define_flags(names: &Names, name: &witx::Id, f: &witx::FlagsDataty
} }
impl ::std::convert::TryFrom<#abi_repr> for #ident { impl ::std::convert::TryFrom<#abi_repr> for #ident {
type Error = wiggle::GuestError; type Error = #rt::GuestError;
fn try_from(value: #abi_repr) -> Result<#ident, wiggle::GuestError> { fn try_from(value: #abi_repr) -> Result<#ident, #rt::GuestError> {
#ident::try_from(value as #repr) #ident::try_from(value as #repr)
} }
} }
@@ -145,7 +146,7 @@ pub(super) fn define_flags(names: &Names, name: &witx::Id, f: &witx::FlagsDataty
} }
} }
impl<'a> wiggle::GuestType<'a> for #ident { impl<'a> #rt::GuestType<'a> for #ident {
fn guest_size() -> u32 { fn guest_size() -> u32 {
#repr::guest_size() #repr::guest_size()
} }
@@ -154,21 +155,21 @@ pub(super) fn define_flags(names: &Names, name: &witx::Id, f: &witx::FlagsDataty
#repr::guest_align() #repr::guest_align()
} }
fn read(location: &wiggle::GuestPtr<#ident>) -> Result<#ident, wiggle::GuestError> { fn read(location: &#rt::GuestPtr<#ident>) -> Result<#ident, #rt::GuestError> {
use std::convert::TryFrom; use std::convert::TryFrom;
let reprval = #repr::read(&location.cast())?; let reprval = #repr::read(&location.cast())?;
let value = #ident::try_from(reprval)?; let value = #ident::try_from(reprval)?;
Ok(value) Ok(value)
} }
fn write(location: &wiggle::GuestPtr<'_, #ident>, val: Self) -> Result<(), wiggle::GuestError> { fn write(location: &#rt::GuestPtr<'_, #ident>, val: Self) -> Result<(), #rt::GuestError> {
let val: #repr = #repr::from(val); let val: #repr = #repr::from(val);
#repr::write(&location.cast(), val) #repr::write(&location.cast(), val)
} }
} }
unsafe impl <'a> wiggle::GuestTypeTransparent<'a> for #ident { unsafe impl<'a> #rt::GuestTypeTransparent<'a> for #ident {
#[inline] #[inline]
fn validate(location: *mut #ident) -> Result<(), wiggle::GuestError> { fn validate(location: *mut #ident) -> Result<(), #rt::GuestError> {
use std::convert::TryFrom; use std::convert::TryFrom;
// Validate value in memory using #ident::try_from(reprval) // Validate value in memory using #ident::try_from(reprval)
let reprval = unsafe { (location as *mut #repr).read() }; let reprval = unsafe { (location as *mut #repr).read() };

View File

@@ -9,6 +9,7 @@ pub(super) fn define_handle(
name: &witx::Id, name: &witx::Id,
h: &witx::HandleDatatype, h: &witx::HandleDatatype,
) -> TokenStream { ) -> TokenStream {
let rt = names.runtime_mod();
let ident = names.type_(name); let ident = names.type_(name);
let size = h.mem_size_align().size as u32; let size = h.mem_size_align().size as u32;
let align = h.mem_size_align().align as usize; let align = h.mem_size_align().align as usize;
@@ -52,7 +53,7 @@ pub(super) fn define_handle(
} }
} }
impl<'a> wiggle::GuestType<'a> for #ident { impl<'a> #rt::GuestType<'a> for #ident {
fn guest_size() -> u32 { fn guest_size() -> u32 {
#size #size
} }
@@ -61,18 +62,18 @@ pub(super) fn define_handle(
#align #align
} }
fn read(location: &wiggle::GuestPtr<'a, #ident>) -> Result<#ident, wiggle::GuestError> { fn read(location: &#rt::GuestPtr<'a, #ident>) -> Result<#ident, #rt::GuestError> {
Ok(#ident(u32::read(&location.cast())?)) Ok(#ident(u32::read(&location.cast())?))
} }
fn write(location: &wiggle::GuestPtr<'_, Self>, val: Self) -> Result<(), wiggle::GuestError> { fn write(location: &#rt::GuestPtr<'_, Self>, val: Self) -> Result<(), #rt::GuestError> {
u32::write(&location.cast(), val.0) u32::write(&location.cast(), val.0)
} }
} }
unsafe impl<'a> wiggle::GuestTypeTransparent<'a> for #ident { unsafe impl<'a> #rt::GuestTypeTransparent<'a> for #ident {
#[inline] #[inline]
fn validate(_location: *mut #ident) -> Result<(), wiggle::GuestError> { fn validate(_location: *mut #ident) -> Result<(), #rt::GuestError> {
// All bit patterns accepted // All bit patterns accepted
Ok(()) Ok(())
} }

View File

@@ -5,6 +5,7 @@ use proc_macro2::TokenStream;
use quote::quote; use quote::quote;
pub(super) fn define_int(names: &Names, name: &witx::Id, i: &witx::IntDatatype) -> TokenStream { pub(super) fn define_int(names: &Names, name: &witx::Id, i: &witx::IntDatatype) -> TokenStream {
let rt = names.runtime_mod();
let ident = names.type_(&name); let ident = names.type_(&name);
let repr = int_repr_tokens(i.repr); let repr = int_repr_tokens(i.repr);
let abi_repr = atom_token(match i.repr { let abi_repr = atom_token(match i.repr {
@@ -37,15 +38,15 @@ pub(super) fn define_int(names: &Names, name: &witx::Id, i: &witx::IntDatatype)
} }
impl ::std::convert::TryFrom<#repr> for #ident { impl ::std::convert::TryFrom<#repr> for #ident {
type Error = wiggle::GuestError; type Error = #rt::GuestError;
fn try_from(value: #repr) -> Result<Self, wiggle::GuestError> { fn try_from(value: #repr) -> Result<Self, #rt::GuestError> {
Ok(#ident(value)) Ok(#ident(value))
} }
} }
impl ::std::convert::TryFrom<#abi_repr> for #ident { impl ::std::convert::TryFrom<#abi_repr> for #ident {
type Error = wiggle::GuestError; type Error = #rt::GuestError;
fn try_from(value: #abi_repr) -> Result<#ident, wiggle::GuestError> { fn try_from(value: #abi_repr) -> Result<#ident, #rt::GuestError> {
#ident::try_from(value as #repr) #ident::try_from(value as #repr)
} }
} }
@@ -62,7 +63,7 @@ pub(super) fn define_int(names: &Names, name: &witx::Id, i: &witx::IntDatatype)
} }
} }
impl<'a> wiggle::GuestType<'a> for #ident { impl<'a> #rt::GuestType<'a> for #ident {
fn guest_size() -> u32 { fn guest_size() -> u32 {
#repr::guest_size() #repr::guest_size()
} }
@@ -71,19 +72,19 @@ pub(super) fn define_int(names: &Names, name: &witx::Id, i: &witx::IntDatatype)
#repr::guest_align() #repr::guest_align()
} }
fn read(location: &wiggle::GuestPtr<'a, #ident>) -> Result<#ident, wiggle::GuestError> { fn read(location: &#rt::GuestPtr<'a, #ident>) -> Result<#ident, #rt::GuestError> {
Ok(#ident(#repr::read(&location.cast())?)) Ok(#ident(#repr::read(&location.cast())?))
} }
fn write(location: &wiggle::GuestPtr<'_, #ident>, val: Self) -> Result<(), wiggle::GuestError> { fn write(location: &#rt::GuestPtr<'_, #ident>, val: Self) -> Result<(), #rt::GuestError> {
#repr::write(&location.cast(), val.0) #repr::write(&location.cast(), val.0)
} }
} }
unsafe impl<'a> wiggle::GuestTypeTransparent<'a> for #ident { unsafe impl<'a> #rt::GuestTypeTransparent<'a> for #ident {
#[inline] #[inline]
fn validate(_location: *mut #ident) -> Result<(), wiggle::GuestError> { fn validate(_location: *mut #ident) -> Result<(), #rt::GuestError> {
// All bit patterns accepted // All bit patterns accepted
Ok(()) Ok(())
} }

View File

@@ -23,10 +23,12 @@ pub fn define_datatype(names: &Names, namedtype: &witx::NamedType) -> TokenStrea
witx::Type::Handle(h) => handle::define_handle(names, &namedtype.name, &h), witx::Type::Handle(h) => handle::define_handle(names, &namedtype.name, &h),
witx::Type::Builtin(b) => define_builtin(names, &namedtype.name, *b), witx::Type::Builtin(b) => define_builtin(names, &namedtype.name, *b),
witx::Type::Pointer(p) => { witx::Type::Pointer(p) => {
define_witx_pointer(names, &namedtype.name, quote!(wiggle::GuestPtr), p) let rt = names.runtime_mod();
define_witx_pointer(names, &namedtype.name, quote!(#rt::GuestPtr), p)
} }
witx::Type::ConstPointer(p) => { witx::Type::ConstPointer(p) => {
define_witx_pointer(names, &namedtype.name, quote!(wiggle::GuestPtr), p) let rt = names.runtime_mod();
define_witx_pointer(names, &namedtype.name, quote!(#rt::GuestPtr), p)
} }
witx::Type::Array(arr) => define_witx_array(names, &namedtype.name, &arr), witx::Type::Array(arr) => define_witx_array(names, &namedtype.name, &arr),
}, },
@@ -67,8 +69,9 @@ fn define_witx_pointer(
fn define_witx_array(names: &Names, name: &witx::Id, arr_raw: &witx::TypeRef) -> TokenStream { fn define_witx_array(names: &Names, name: &witx::Id, arr_raw: &witx::TypeRef) -> TokenStream {
let ident = names.type_(name); let ident = names.type_(name);
let rt = names.runtime_mod();
let pointee_type = names.type_ref(arr_raw, quote!('a)); let pointee_type = names.type_ref(arr_raw, quote!('a));
quote!(pub type #ident<'a> = wiggle::GuestPtr<'a, [#pointee_type]>;) quote!(pub type #ident<'a> = #rt::GuestPtr<'a, [#pointee_type]>;)
} }
fn int_repr_tokens(int_repr: witx::IntRepr) -> TokenStream { fn int_repr_tokens(int_repr: witx::IntRepr) -> TokenStream {

View File

@@ -10,6 +10,7 @@ pub(super) fn define_struct(
name: &witx::Id, name: &witx::Id,
s: &witx::StructDatatype, s: &witx::StructDatatype,
) -> TokenStream { ) -> TokenStream {
let rt = names.runtime_mod();
let ident = names.type_(name); let ident = names.type_(name);
let size = s.mem_size_align().size as u32; let size = s.mem_size_align().size as u32;
let align = s.mem_size_align().align as usize; let align = s.mem_size_align().align as usize;
@@ -23,7 +24,7 @@ pub(super) fn define_struct(
witx::Type::Builtin(builtin) => names.builtin_type(*builtin, quote!('a)), witx::Type::Builtin(builtin) => names.builtin_type(*builtin, quote!('a)),
witx::Type::Pointer(pointee) | witx::Type::ConstPointer(pointee) => { witx::Type::Pointer(pointee) | witx::Type::ConstPointer(pointee) => {
let pointee_type = names.type_ref(&pointee, quote!('a)); let pointee_type = names.type_ref(&pointee, quote!('a));
quote!(wiggle::GuestPtr<'a, #pointee_type>) quote!(#rt::GuestPtr<'a, #pointee_type>)
} }
_ => unimplemented!("other anonymous struct members"), _ => unimplemented!("other anonymous struct members"),
}, },
@@ -39,20 +40,20 @@ pub(super) fn define_struct(
witx::TypeRef::Name(nt) => { witx::TypeRef::Name(nt) => {
let type_ = names.type_(&nt.name); let type_ = names.type_(&nt.name);
quote! { quote! {
let #name = <#type_ as wiggle::GuestType>::read(&#location)?; let #name = <#type_ as #rt::GuestType>::read(&#location)?;
} }
} }
witx::TypeRef::Value(ty) => match &**ty { witx::TypeRef::Value(ty) => match &**ty {
witx::Type::Builtin(builtin) => { witx::Type::Builtin(builtin) => {
let type_ = names.builtin_type(*builtin, anon_lifetime()); let type_ = names.builtin_type(*builtin, anon_lifetime());
quote! { quote! {
let #name = <#type_ as wiggle::GuestType>::read(&#location)?; let #name = <#type_ as #rt::GuestType>::read(&#location)?;
} }
} }
witx::Type::Pointer(pointee) | witx::Type::ConstPointer(pointee) => { witx::Type::Pointer(pointee) | witx::Type::ConstPointer(pointee) => {
let pointee_type = names.type_ref(&pointee, anon_lifetime()); let pointee_type = names.type_ref(&pointee, anon_lifetime());
quote! { quote! {
let #name = <wiggle::GuestPtr::<#pointee_type> as wiggle::GuestType>::read(&#location)?; let #name = <#rt::GuestPtr::<#pointee_type> as #rt::GuestType>::read(&#location)?;
} }
} }
_ => unimplemented!("other anonymous struct members"), _ => unimplemented!("other anonymous struct members"),
@@ -64,7 +65,7 @@ pub(super) fn define_struct(
let name = names.struct_member(&ml.member.name); let name = names.struct_member(&ml.member.name);
let offset = ml.offset as u32; let offset = ml.offset as u32;
quote! { quote! {
wiggle::GuestType::write( #rt::GuestType::write(
&location.cast::<u8>().add(#offset)?.cast(), &location.cast::<u8>().add(#offset)?.cast(),
val.#name, val.#name,
)?; )?;
@@ -91,9 +92,9 @@ pub(super) fn define_struct(
}); });
quote! { quote! {
unsafe impl<'a> wiggle::GuestTypeTransparent<'a> for #ident { unsafe impl<'a> #rt::GuestTypeTransparent<'a> for #ident {
#[inline] #[inline]
fn validate(location: *mut #ident) -> Result<(), wiggle::GuestError> { fn validate(location: *mut #ident) -> Result<(), #rt::GuestError> {
#(#member_validate)* #(#member_validate)*
Ok(()) Ok(())
} }
@@ -109,7 +110,7 @@ pub(super) fn define_struct(
#(#member_decls),* #(#member_decls),*
} }
impl<'a> wiggle::GuestType<'a> for #ident #struct_lifetime { impl<'a> #rt::GuestType<'a> for #ident #struct_lifetime {
fn guest_size() -> u32 { fn guest_size() -> u32 {
#size #size
} }
@@ -118,12 +119,12 @@ pub(super) fn define_struct(
#align #align
} }
fn read(location: &wiggle::GuestPtr<'a, Self>) -> Result<Self, wiggle::GuestError> { fn read(location: &#rt::GuestPtr<'a, Self>) -> Result<Self, #rt::GuestError> {
#(#member_reads)* #(#member_reads)*
Ok(#ident { #(#member_names),* }) Ok(#ident { #(#member_names),* })
} }
fn write(location: &wiggle::GuestPtr<'_, Self>, val: Self) -> Result<(), wiggle::GuestError> { fn write(location: &#rt::GuestPtr<'_, Self>, val: Self) -> Result<(), #rt::GuestError> {
#(#member_writes)* #(#member_writes)*
Ok(()) Ok(())
} }

View File

@@ -6,6 +6,7 @@ use quote::quote;
use witx::Layout; use witx::Layout;
pub(super) fn define_union(names: &Names, name: &witx::Id, u: &witx::UnionDatatype) -> TokenStream { pub(super) fn define_union(names: &Names, name: &witx::Id, u: &witx::UnionDatatype) -> TokenStream {
let rt = names.runtime_mod();
let ident = names.type_(name); let ident = names.type_(name);
let size = u.mem_size_align().size as u32; let size = u.mem_size_align().size as u32;
let align = u.mem_size_align().align as usize; let align = u.mem_size_align().align as usize;
@@ -33,7 +34,7 @@ pub(super) fn define_union(names: &Names, name: &witx::Id, u: &witx::UnionDataty
quote! { quote! {
#tagname::#variantname => { #tagname::#variantname => {
let variant_ptr = location.cast::<u8>().add(#contents_offset)?; let variant_ptr = location.cast::<u8>().add(#contents_offset)?;
let variant_val = <#varianttype as wiggle::GuestType>::read(&variant_ptr.cast())?; let variant_val = <#varianttype as #rt::GuestType>::read(&variant_ptr.cast())?;
Ok(#ident::#variantname(variant_val)) Ok(#ident::#variantname(variant_val))
} }
} }
@@ -53,7 +54,7 @@ pub(super) fn define_union(names: &Names, name: &witx::Id, u: &witx::UnionDataty
#ident::#variantname(contents) => { #ident::#variantname(contents) => {
#write_tag #write_tag
let variant_ptr = location.cast::<u8>().add(#contents_offset)?; let variant_ptr = location.cast::<u8>().add(#contents_offset)?;
<#varianttype as wiggle::GuestType>::write(&variant_ptr.cast(), contents)?; <#varianttype as #rt::GuestType>::write(&variant_ptr.cast(), contents)?;
} }
} }
} else { } else {
@@ -77,7 +78,7 @@ pub(super) fn define_union(names: &Names, name: &witx::Id, u: &witx::UnionDataty
#(#variants),* #(#variants),*
} }
impl<'a> wiggle::GuestType<'a> for #ident #enum_lifetime { impl<'a> #rt::GuestType<'a> for #ident #enum_lifetime {
fn guest_size() -> u32 { fn guest_size() -> u32 {
#size #size
} }
@@ -86,8 +87,8 @@ pub(super) fn define_union(names: &Names, name: &witx::Id, u: &witx::UnionDataty
#align #align
} }
fn read(location: &wiggle::GuestPtr<'a, Self>) fn read(location: &#rt::GuestPtr<'a, Self>)
-> Result<Self, wiggle::GuestError> -> Result<Self, #rt::GuestError>
{ {
let tag = location.cast().read()?; let tag = location.cast().read()?;
match tag { match tag {
@@ -96,8 +97,8 @@ pub(super) fn define_union(names: &Names, name: &witx::Id, u: &witx::UnionDataty
} }
fn write(location: &wiggle::GuestPtr<'_, Self>, val: Self) fn write(location: &#rt::GuestPtr<'_, Self>, val: Self)
-> Result<(), wiggle::GuestError> -> Result<(), #rt::GuestError>
{ {
match val { match val {
#(#write_variant)* #(#write_variant)*

View File

@@ -16,6 +16,7 @@ proc-macro = true
[dependencies] [dependencies]
wiggle-generate = { path = "../generate", version = "0.15.0" } wiggle-generate = { path = "../generate", version = "0.15.0" }
witx = { path = "../../wasi-common/WASI/tools/witx", version = "0.8.5" } witx = { path = "../../wasi-common/WASI/tools/witx", version = "0.8.5" }
quote = "1.0"
syn = { version = "1.0", features = ["full"] } syn = { version = "1.0", features = ["full"] }
[dev-dependencies] [dev-dependencies]

View File

@@ -1,6 +1,7 @@
extern crate proc_macro; extern crate proc_macro;
use proc_macro::TokenStream; use proc_macro::TokenStream;
use quote::quote;
use syn::parse_macro_input; use syn::parse_macro_input;
/// This macro expands to a set of `pub` Rust modules: /// This macro expands to a set of `pub` Rust modules:
@@ -94,11 +95,15 @@ pub fn from_witx(args: TokenStream) -> TokenStream {
std::env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR env var"), std::env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR env var"),
); );
#[cfg(feature = "wiggle_metadata")]
{
config.emit_metadata = true;
}
let doc = witx::load(&config.witx.paths).expect("loading witx"); let doc = witx::load(&config.witx.paths).expect("loading witx");
TokenStream::from(wiggle_generate::generate(&doc, &config)) let names = wiggle_generate::Names::new(&config.ctx.name, quote!(wiggle));
let code = wiggle_generate::generate(&doc, &names);
let metadata = if cfg!(feature = "wiggle_metadata") {
wiggle_generate::generate_metadata(&doc, &names)
} else {
quote!()
};
TokenStream::from(quote! { #code #metadata })
} }