hir::Ty - new methods to extract tokens to build up a g_param_spec_*() call

Depending on the kind of Ty (a Rust type we know how to Glib-ify), we
need to be able to create a GParamSpec with g_param_spec_int(),
g_param_spec_bool(), etc.

This commit adds these methods:

  Ty::to_gparam_spec_constructor
  Ty::to_gparam_spec_min_max_default

which are then used in properties.rs.
parent d54cc7b3
use proc_macro2::{Ident, TokenStream, TokenTree};
use hir::Property;
use hir::{Property, Ty};
use ident_ext::IdentExt;
pub fn properties_enum<'ast>(properties: &[Property<'ast>]) -> TokenStream {
......@@ -230,57 +230,18 @@ fn prop_registration<'ast>(properties: &[Property<'ast>]) -> Vec<TokenStream> {
.map(|prop| {
let name = prop.name.to_owned_string();
let para_spec;
let default;
// FIXME: Don't unwrap() here; instead, store a hir::Ty in the property instead of
// a syn::Type, i.e. something that we already checked that can be represented by
// Glib.
let ty = Ty::extract_from_type(&prop.type_).unwrap();
// FIXME: grep for (type conversions) above; that has a description of how to fix this.
let type_token_tree: TokenTree = prop.type_.into_tokens().into_iter().nth(0).unwrap();
let type_ = match type_token_tree {
TokenTree::Ident(i) => i.to_string(),
_ => String::new(),
};
match &type_[..] {
"i32" => {
para_spec = quote! { g_param_spec_int };
default = quote! { i32::MIN, i32::MAX, 0, };
}
"i64" => {
para_spec = quote! { g_param_spec_long };
default = quote! { i64::MIN, i64::MAX, 0, };
}
"u32" => {
para_spec = quote! { g_param_spec_uint };
default = quote! { std::u32::MIN, std::u32::MAX, 0, };
}
"u64" => {
para_spec = quote! { g_param_spec_ulong };
default = quote! { u64::MIN, u64::MAX, 0, };
}
"f32" => {
para_spec = quote! { g_param_spec_float };
default = quote! { f32::MIN, f32::MAX, 0, };
}
"f64" => {
para_spec = quote! { g_param_spec_double };
default = quote! { f64::MIN, f64::MAX, 0, };
}
"bool" => {
para_spec = quote! { g_param_spec_boolean };
default = quote! { false, };
}
"String" => {
para_spec = quote! { g_param_spec_pointer };
default = quote! { ptr::null_mut(), };
}
_ => {
para_spec = quote! { g_param_spec_pointer };
default = quote!{};
}
};
let (para_spec, default) = (
ty.to_gparam_spec_constructor(),
ty.to_gparam_spec_min_max_default(),
);
quote! {
properties.push(gobject_ffi::#para_spec(
properties.push(#para_spec(
// We're using here the same value for name, nick and blurb because with
// the current property declaration syntax we only have the property name.
// In the future we can provide a way to declare this or we can compose
......@@ -290,7 +251,7 @@ fn prop_registration<'ast>(properties: &[Property<'ast>]) -> Vec<TokenStream> {
CString::new(#name).unwrap().as_ptr(),
// default value
#default
#default,
gobject_ffi::G_PARAM_READWRITE
......
......@@ -403,7 +403,7 @@ fn extract_inputs<'ast>(punc: &'ast Punctuated<syn::FnArg, Token!(,)>) -> Result
}
impl<'ast> Ty<'ast> {
fn extract_from_type(t: &'ast syn::Type) -> Result<Ty<'ast>> {
pub fn extract_from_type(t: &'ast syn::Type) -> Result<Ty<'ast>> {
match *t {
syn::Type::Slice(_) => bail!("slice types not implemented yet"),
syn::Type::Array(_) => bail!("array types not implemented yet"),
......@@ -509,6 +509,65 @@ impl<'ast> Ty<'ast> {
pub fn to_gtype_path(&self) -> Path {
path_from_string(self.to_gtype_string())
}
/// Returns tokens for the name of the `g_param_spec_*()` function that can be
/// used to create a `GParamSpec` suitable for the `Ty`.
pub fn to_gparam_spec_constructor(&self) -> TokenStream {
match *self {
Ty::Unit => unreachable!("there is no g_param_spec_*() for the Unit type"),
Ty::Char(_) => quote! { gobject_ffi::g_param_spec_uint }, // <char as ToGlib>::GlibType = u32
Ty::Bool(_) => quote! { gobject_ffi::g_param_spec_boolean },
Ty::Borrowed(_) => unimplemented!(),
Ty::Integer(ref ident) => match ident.to_owned_string().as_str() {
"i8" | "u8" => quote! { gobject_ffi::g_param_spec_char },
"i16" => unimplemented!("should we promote i16 to i32?"),
"i32" => quote! { gobject_ffi::g_param_spec_int },
"i64" => quote! { gobject_ffi::g_param_spec_int64 },
"isize" => unimplemented!(),
"u16" => unimplemented!("should we promote u16 to u32?"),
"u32" => quote! { gobject_ffi::g_param_spec_uint },
"u64" => quote! { gobject_ffi::g_param_spec_uint64 },
"usize" => unimplemented!(),
_ => unreachable!(),
},
Ty::Owned(_) => unimplemented!(),
}
}
/// Returns tokens for the minimum/maximum/default values that are passed to
/// the `g_param_spec_*()` functions when constructing a `GParamSpec`.
pub fn to_gparam_spec_min_max_default(&self) -> TokenStream {
match *self {
Ty::Unit => unreachable!("there is no g_param_spec_*() for the Unit type"),
Ty::Char(_) => quote! { u32::MIN, u32::MAX, 0 }, // <char as ToGlib>::GlibType = u32
// g_param_spec_bool() takes no min/max, just a default
Ty::Bool(_) => quote! { glib_ffi::GFALSE },
Ty::Borrowed(_) => unimplemented!(),
Ty::Integer(ref ident) => match ident.to_owned_string().as_str() {
"i8" | "u8" => quote! { 0, 0xff as i8, 0 },
"i16" => unimplemented!("should we promote i16 to i32?"),
"i32" => quote! { i32::MIN, i32::MAX, 0 },
"i64" => quote! { i64::MIN, i64::MAX, 0 },
"isize" => unimplemented!(),
"u16" => unimplemented!("should we promote u16 to u32?"),
"u32" => quote! { u32::MIN, u32::MAX, 0 },
"u64" => quote! { u64::MIN, u64::MAX, 0 },
"usize" => unimplemented!(),
_ => unreachable!(),
},
Ty::Owned(_) => unimplemented!(),
}
}
}
impl<'ast> Property<'ast> {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment