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"
version = "0.15.0"
dependencies = [
"quote",
"syn",
"wiggle",
"wiggle-generate",

View File

@@ -12,7 +12,6 @@ use syn::{
pub struct Config {
pub witx: WitxConf,
pub ctx: CtxConf,
pub emit_metadata: bool,
}
#[derive(Debug, Clone)]
@@ -60,7 +59,6 @@ impl Config {
ctx: ctx
.take()
.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 ident = names.func(&func.name);
let rt = names.runtime_mod();
let ctx_type = names.ctx_type();
let coretype = func.core_type();
@@ -23,7 +24,7 @@ pub fn define_func(
});
let abi_args = quote!(
ctx: &#ctx_type, memory: &dyn wiggle::GuestMemory,
ctx: &#ctx_type, memory: &dyn #rt::GuestMemory,
#(#params),*
);
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_method = names.guest_error_conversion_method(&tref);
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!
return #abi_ret::from(err);
}
@@ -139,7 +140,7 @@ pub fn define_func(
let success = if let Some(ref err_type) = err_type {
let err_typename = names.type_ref(&err_type, anon_lifetime());
quote! {
let success:#err_typename = wiggle::GuestErrorType::success();
let success:#err_typename = #rt::GuestErrorType::success();
#[cfg(feature = "trace_log")]
{
log::trace!(" | errno={}", success);
@@ -185,6 +186,7 @@ fn marshal_arg(
param: &witx::InterfaceFuncParam,
error_handling: TokenStream,
) -> TokenStream {
let rt = names.runtime_mod();
let tref = &param.tref;
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 name = names.func_param(&param.name);
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,
Err(e) => {
#error_handling
@@ -254,7 +256,7 @@ fn marshal_arg(
let len_name = names.func_len_binding(&param.name);
let name = names.func_param(&param.name);
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 name = names.func_param(&param.name);
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,
@@ -272,7 +274,7 @@ fn marshal_arg(
let len_name = names.func_len_binding(&param.name);
let name = names.func_param(&param.name);
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,
@@ -292,6 +294,7 @@ fn marshal_result<F>(
where
F: Fn(&str) -> TokenStream,
{
let rt = names.runtime_mod();
let tref = &result.tref;
let write_val_to_ptr = {
@@ -300,7 +303,7 @@ where
let ptr_name = names.func_ptr_binding(&result.name);
let ptr_err_handling = error_handling(&format!("{}:result_ptr_mut", result.name.as_str()));
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.
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 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
// overrides.
let names = Names::new(&config.ctx.name);
let rt = names.runtime_mod();
let types = doc.typenames().map(|t| define_datatype(&names, &t));
let guest_error_methods = doc.error_types().map(|t| {
let typename = names.type_ref(&t, anon_lifetime());
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! {
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!(
pub mod types {
#(#types)*
#guest_error_conversion
}
#(#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 {
ctx_type: Ident,
runtime_mod: TokenStream,
}
impl Names {
pub fn new(ctx_type: &Ident) -> Names {
pub fn new(ctx_type: &Ident, runtime_mod: TokenStream) -> Names {
Names {
ctx_type: ctx_type.clone(),
runtime_mod,
}
}
pub fn ctx_type(&self) -> Ident {
self.ctx_type.clone()
}
pub fn runtime_mod(&self) -> TokenStream {
self.runtime_mod.clone()
}
pub fn type_(&self, id: &Id) -> TokenStream {
let ident = format_ident!("{}", id.as_str().to_camel_case());
quote!(#ident)
}
pub fn builtin_type(&self, b: BuiltinType, lifetime: TokenStream) -> TokenStream {
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::U16 => quote!(u16),
BuiltinType::U32 => quote!(u32),
@@ -61,12 +69,14 @@ impl Names {
TypeRef::Value(ty) => match &**ty {
Type::Builtin(builtin) => self.builtin_type(*builtin, lifetime.clone()),
Type::Pointer(pointee) | Type::ConstPointer(pointee) => {
let rt = self.runtime_mod();
let pointee_type = self.type_ref(&pointee, lifetime.clone());
quote!(wiggle::GuestPtr<#lifetime, #pointee_type>)
quote!(#rt::GuestPtr<#lifetime, #pointee_type>)
}
Type::Array(pointee) => {
let rt = self.runtime_mod();
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),
},

View File

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

View File

@@ -6,6 +6,7 @@ use quote::quote;
use std::convert::TryFrom;
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 repr = int_repr_tokens(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 {
type Error = wiggle::GuestError;
fn try_from(value: #repr) -> Result<Self, wiggle::GuestError> {
type Error = #rt::GuestError;
fn try_from(value: #repr) -> Result<Self, #rt::GuestError> {
if #repr::from(!#ident::all()) & value != 0 {
Err(wiggle::GuestError::InvalidFlagValue(stringify!(#ident)))
Err(#rt::GuestError::InvalidFlagValue(stringify!(#ident)))
} else {
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 {
type Error = wiggle::GuestError;
fn try_from(value: #abi_repr) -> Result<#ident, wiggle::GuestError> {
type Error = #rt::GuestError;
fn try_from(value: #abi_repr) -> Result<#ident, #rt::GuestError> {
#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 {
#repr::guest_size()
}
@@ -154,21 +155,21 @@ pub(super) fn define_flags(names: &Names, name: &witx::Id, f: &witx::FlagsDataty
#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;
let reprval = #repr::read(&location.cast())?;
let value = #ident::try_from(reprval)?;
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);
#repr::write(&location.cast(), val)
}
}
unsafe impl <'a> wiggle::GuestTypeTransparent<'a> for #ident {
unsafe impl<'a> #rt::GuestTypeTransparent<'a> for #ident {
#[inline]
fn validate(location: *mut #ident) -> Result<(), wiggle::GuestError> {
fn validate(location: *mut #ident) -> Result<(), #rt::GuestError> {
use std::convert::TryFrom;
// Validate value in memory using #ident::try_from(reprval)
let reprval = unsafe { (location as *mut #repr).read() };

View File

@@ -9,6 +9,7 @@ pub(super) fn define_handle(
name: &witx::Id,
h: &witx::HandleDatatype,
) -> TokenStream {
let rt = names.runtime_mod();
let ident = names.type_(name);
let size = h.mem_size_align().size as u32;
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 {
#size
}
@@ -61,18 +62,18 @@ pub(super) fn define_handle(
#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())?))
}
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)
}
}
unsafe impl<'a> wiggle::GuestTypeTransparent<'a> for #ident {
unsafe impl<'a> #rt::GuestTypeTransparent<'a> for #ident {
#[inline]
fn validate(_location: *mut #ident) -> Result<(), wiggle::GuestError> {
fn validate(_location: *mut #ident) -> Result<(), #rt::GuestError> {
// All bit patterns accepted
Ok(())
}

View File

@@ -5,6 +5,7 @@ use proc_macro2::TokenStream;
use quote::quote;
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 repr = int_repr_tokens(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 {
type Error = wiggle::GuestError;
fn try_from(value: #repr) -> Result<Self, wiggle::GuestError> {
type Error = #rt::GuestError;
fn try_from(value: #repr) -> Result<Self, #rt::GuestError> {
Ok(#ident(value))
}
}
impl ::std::convert::TryFrom<#abi_repr> for #ident {
type Error = wiggle::GuestError;
fn try_from(value: #abi_repr) -> Result<#ident, wiggle::GuestError> {
type Error = #rt::GuestError;
fn try_from(value: #abi_repr) -> Result<#ident, #rt::GuestError> {
#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 {
#repr::guest_size()
}
@@ -71,19 +72,19 @@ pub(super) fn define_int(names: &Names, name: &witx::Id, i: &witx::IntDatatype)
#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())?))
}
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)
}
}
unsafe impl<'a> wiggle::GuestTypeTransparent<'a> for #ident {
unsafe impl<'a> #rt::GuestTypeTransparent<'a> for #ident {
#[inline]
fn validate(_location: *mut #ident) -> Result<(), wiggle::GuestError> {
fn validate(_location: *mut #ident) -> Result<(), #rt::GuestError> {
// All bit patterns accepted
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::Builtin(b) => define_builtin(names, &namedtype.name, *b),
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) => {
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),
},
@@ -67,8 +69,9 @@ fn define_witx_pointer(
fn define_witx_array(names: &Names, name: &witx::Id, arr_raw: &witx::TypeRef) -> TokenStream {
let ident = names.type_(name);
let rt = names.runtime_mod();
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 {

View File

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

View File

@@ -6,6 +6,7 @@ use quote::quote;
use witx::Layout;
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 size = u.mem_size_align().size as u32;
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! {
#tagname::#variantname => {
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))
}
}
@@ -53,7 +54,7 @@ pub(super) fn define_union(names: &Names, name: &witx::Id, u: &witx::UnionDataty
#ident::#variantname(contents) => {
#write_tag
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 {
@@ -77,7 +78,7 @@ pub(super) fn define_union(names: &Names, name: &witx::Id, u: &witx::UnionDataty
#(#variants),*
}
impl<'a> wiggle::GuestType<'a> for #ident #enum_lifetime {
impl<'a> #rt::GuestType<'a> for #ident #enum_lifetime {
fn guest_size() -> u32 {
#size
}
@@ -86,8 +87,8 @@ pub(super) fn define_union(names: &Names, name: &witx::Id, u: &witx::UnionDataty
#align
}
fn read(location: &wiggle::GuestPtr<'a, Self>)
-> Result<Self, wiggle::GuestError>
fn read(location: &#rt::GuestPtr<'a, Self>)
-> Result<Self, #rt::GuestError>
{
let tag = location.cast().read()?;
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)
-> Result<(), wiggle::GuestError>
fn write(location: &#rt::GuestPtr<'_, Self>, val: Self)
-> Result<(), #rt::GuestError>
{
match val {
#(#write_variant)*

View File

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

View File

@@ -1,6 +1,7 @@
extern crate proc_macro;
use proc_macro::TokenStream;
use quote::quote;
use syn::parse_macro_input;
/// 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"),
);
#[cfg(feature = "wiggle_metadata")]
{
config.emit_metadata = true;
}
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 })
}