Skip to content

Commit

Permalink
Add support for enums (#33)
Browse files Browse the repository at this point in the history
* Add support for enums

* Emit C-style enums

* Explain why enum is isize

* Run cargo fmt
  • Loading branch information
shadaj authored Jul 23, 2021
1 parent 0513b67 commit 306367c
Show file tree
Hide file tree
Showing 17 changed files with 465 additions and 81 deletions.
85 changes: 85 additions & 0 deletions core/src/ast/enums.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
use serde::{Deserialize, Serialize};

use super::utils::get_doc_lines;
use super::Method;

/// A fieldless enum declaration in an FFI module.
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct Enum {
pub name: String,
pub doc_lines: String,
/// A list of variants of the enum. (name, discriminant, doc_lines)
pub variants: Vec<(String, isize, String)>,
pub methods: Vec<Method>,
}

impl From<&syn::ItemEnum> for Enum {
/// Extract an [`Enum`] metadata value from an AST node.
fn from(strct: &syn::ItemEnum) -> Enum {
let mut last_discriminant = -1;
Enum {
name: strct.ident.to_string(),
doc_lines: get_doc_lines(&strct.attrs),
variants: strct
.variants
.iter()
.map(|v| {
let new_discriminant = v
.discriminant
.as_ref()
.map(|d| {
if let syn::Expr::Lit(syn::ExprLit {
attrs: _,
lit: syn::Lit::Int(lit_int),
}) = &d.1
{
lit_int.base10_parse::<isize>().unwrap()
} else {
panic!("Expected a discriminant to be a constant integer");
}
})
.unwrap_or_else(|| last_discriminant + 1);

last_discriminant = new_discriminant;

(
v.ident.to_string(),
new_discriminant,
get_doc_lines(&v.attrs),
)
})
.collect(),
methods: vec![],
}
}
}

#[cfg(test)]
mod tests {
use insta::{self, Settings};

use quote::quote;
use syn;

use super::Enum;

#[test]
fn simple_enum() {
let mut settings = Settings::new();
settings.set_sort_maps(true);

settings.bind(|| {
insta::assert_yaml_snapshot!(Enum::from(
&syn::parse2(quote! {
/// Some docs.
enum MyLocalEnum {
Abc,
/// Some more docs.
Def
}
})
.unwrap()
));
});
}
}
3 changes: 3 additions & 0 deletions core/src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ pub use modules::{File, Module};
mod structs;
pub use structs::{OpaqueStruct, Struct};

mod enums;
pub use enums::Enum;

mod types;
pub use types::{CustomType, ModSymbol, PrimitiveType, TypeName};

Expand Down
13 changes: 12 additions & 1 deletion core/src/ast/modules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::collections::HashMap;
use quote::ToTokens;
use syn::{ImplItem, Item, ItemMod, UseTree};

use super::{CustomType, Method, ModSymbol, OpaqueStruct, Path, Struct, TypeName};
use super::{CustomType, Enum, Method, ModSymbol, OpaqueStruct, Path, Struct, TypeName};

#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct Module {
Expand Down Expand Up @@ -99,6 +99,14 @@ impl Module {
}
}
}

Item::Enum(enm) => {
if analyze_types {
custom_types_by_name
.insert(enm.ident.to_string(), CustomType::Enum(Enum::from(enm)));
}
}

Item::Impl(ipl) => {
if analyze_types {
assert!(ipl.trait_.is_none());
Expand Down Expand Up @@ -126,6 +134,9 @@ impl Module {
CustomType::Opaque(strct) => {
strct.methods.append(&mut new_methods);
}
CustomType::Enum(enm) => {
enm.methods.append(&mut new_methods);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
source: core/src/ast/enums.rs
expression: "Enum::from(&syn::parse2(quote! {\n /// Some docs.\n enum MyLocalEnum\n {\n Abc, /// Some more docs.\n Def\n }\n }).unwrap())"

---
name: MyLocalEnum
doc_lines: Some docs.
variants:
- - Abc
- 0
- ""
- - Def
- 1
- Some more docs.
methods: []

9 changes: 7 additions & 2 deletions core/src/ast/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,17 @@ use lazy_static::lazy_static;
use std::collections::HashMap;
use std::iter::FromIterator;

use super::{Method, OpaqueStruct, Path, Struct};
use super::{Enum, Method, OpaqueStruct, Path, Struct};

/// A type declared inside a Diplomat-annotated module.
#[derive(Clone, Serialize, Deserialize, Debug)]
pub enum CustomType {
/// A non-opaque struct whose fields will be visible across the FFI boundary.
Struct(Struct),
// TODO(shadaj): Enum
/// A struct annotated with [`diplomat::opaque`] whose fields are not visible.
Opaque(OpaqueStruct),
/// A fieldless enum.
Enum(Enum),
}

impl CustomType {
Expand All @@ -25,6 +26,7 @@ impl CustomType {
match self {
CustomType::Struct(strct) => &strct.name,
CustomType::Opaque(strct) => &strct.name,
CustomType::Enum(enm) => &enm.name,
}
}

Expand All @@ -33,6 +35,7 @@ impl CustomType {
match self {
CustomType::Struct(strct) => &strct.methods,
CustomType::Opaque(strct) => &strct.methods,
CustomType::Enum(enm) => &enm.methods,
}
}

Expand All @@ -41,6 +44,7 @@ impl CustomType {
match self {
CustomType::Struct(strct) => &strct.doc_lines,
CustomType::Opaque(strct) => &strct.doc_lines,
CustomType::Enum(enm) => &enm.doc_lines,
}
}

Expand All @@ -61,6 +65,7 @@ impl CustomType {
}
}
CustomType::Opaque(_) => {}
CustomType::Enum(_) => {}
}

for method in self.methods().iter() {
Expand Down
21 changes: 19 additions & 2 deletions example/c/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,26 @@ typedef struct ICU4XFixedDecimal ICU4XFixedDecimal;

typedef struct ICU4XFixedDecimalFormat ICU4XFixedDecimalFormat;

enum ICU4XFixedDecimalGroupingStrategy {
ICU4XFixedDecimalGroupingStrategy_Auto = 0,
ICU4XFixedDecimalGroupingStrategy_Never = 1,
ICU4XFixedDecimalGroupingStrategy_Always = 2,
ICU4XFixedDecimalGroupingStrategy_Min2 = 3,
};

enum ICU4XFixedDecimalSignDisplay {
ICU4XFixedDecimalSignDisplay_Auto = 0,
ICU4XFixedDecimalSignDisplay_Never = 1,
ICU4XFixedDecimalSignDisplay_Always = 2,
ICU4XFixedDecimalSignDisplay_ExceptZero = 3,
ICU4XFixedDecimalSignDisplay_Negative = 4,
};

typedef struct ICU4XLocale ICU4XLocale;

typedef struct ICU4XFixedDecimalFormatOptions {
uint8_t grouping_strategy;
uint8_t sign_display;
ssize_t grouping_strategy;
ssize_t sign_display;
} ICU4XFixedDecimalFormatOptions;

typedef struct ICU4XFixedDecimalFormatResult {
Expand Down Expand Up @@ -45,6 +60,8 @@ void ICU4XFixedDecimalFormat_destroy(ICU4XFixedDecimalFormat* self);
ICU4XFixedDecimalFormatOptions ICU4XFixedDecimalFormatOptions_default();
void ICU4XFixedDecimalFormatOptions_destroy(ICU4XFixedDecimalFormatOptions* self);
void ICU4XFixedDecimalFormatResult_destroy(ICU4XFixedDecimalFormatResult* self);
void ICU4XFixedDecimalGroupingStrategy_destroy(ssize_t* self);
void ICU4XFixedDecimalSignDisplay_destroy(ssize_t* self);

ICU4XLocale* ICU4XLocale_new(const char* name_data, size_t name_len);
void ICU4XLocale_destroy(ICU4XLocale* self);
Expand Down
21 changes: 19 additions & 2 deletions example/cpp/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,26 @@ typedef struct ICU4XFixedDecimal ICU4XFixedDecimal;

typedef struct ICU4XFixedDecimalFormat ICU4XFixedDecimalFormat;

enum ICU4XFixedDecimalGroupingStrategy {
ICU4XFixedDecimalGroupingStrategy_Auto = 0,
ICU4XFixedDecimalGroupingStrategy_Never = 1,
ICU4XFixedDecimalGroupingStrategy_Always = 2,
ICU4XFixedDecimalGroupingStrategy_Min2 = 3,
};

enum ICU4XFixedDecimalSignDisplay {
ICU4XFixedDecimalSignDisplay_Auto = 0,
ICU4XFixedDecimalSignDisplay_Never = 1,
ICU4XFixedDecimalSignDisplay_Always = 2,
ICU4XFixedDecimalSignDisplay_ExceptZero = 3,
ICU4XFixedDecimalSignDisplay_Negative = 4,
};

typedef struct ICU4XLocale ICU4XLocale;

typedef struct ICU4XFixedDecimalFormatOptions {
uint8_t grouping_strategy;
uint8_t sign_display;
ssize_t grouping_strategy;
ssize_t sign_display;
} ICU4XFixedDecimalFormatOptions;

typedef struct ICU4XFixedDecimalFormatResult {
Expand Down Expand Up @@ -45,6 +60,8 @@ void ICU4XFixedDecimalFormat_destroy(ICU4XFixedDecimalFormat* self);
ICU4XFixedDecimalFormatOptions ICU4XFixedDecimalFormatOptions_default();
void ICU4XFixedDecimalFormatOptions_destroy(ICU4XFixedDecimalFormatOptions* self);
void ICU4XFixedDecimalFormatResult_destroy(ICU4XFixedDecimalFormatResult* self);
void ICU4XFixedDecimalGroupingStrategy_destroy(ssize_t* self);
void ICU4XFixedDecimalSignDisplay_destroy(ssize_t* self);

ICU4XLocale* ICU4XLocale_new(const char* name_data, size_t name_len);
void ICU4XLocale_destroy(ICU4XLocale* self);
Expand Down
25 changes: 21 additions & 4 deletions example/cpp/api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@ struct ICU4XFixedDecimalFormatOptions;

struct ICU4XFixedDecimalFormatResult;

enum struct ICU4XFixedDecimalGroupingStrategy : ssize_t {
Auto = 0,
Never = 1,
Always = 2,
Min2 = 3,
};

enum struct ICU4XFixedDecimalSignDisplay : ssize_t {
Auto = 0,
Never = 1,
Always = 2,
ExceptZero = 3,
Negative = 4,
};

class ICU4XLocale;

struct ICU4XDataProviderDeleter {
Expand Down Expand Up @@ -86,8 +101,8 @@ struct ICU4XFixedDecimalFormatOptionsDeleter {
};
struct ICU4XFixedDecimalFormatOptions {
public:
uint8_t grouping_strategy;
uint8_t sign_display;
ICU4XFixedDecimalGroupingStrategy grouping_strategy;
ICU4XFixedDecimalSignDisplay sign_display;
static ICU4XFixedDecimalFormatOptions default_();
};

Expand Down Expand Up @@ -124,7 +139,7 @@ std::string ICU4XFixedDecimal::to_string() {

ICU4XFixedDecimalFormatResult ICU4XFixedDecimalFormat::try_new(const ICU4XLocale& locale, const ICU4XDataProvider& provider, ICU4XFixedDecimalFormatOptions options) {
ICU4XFixedDecimalFormatOptions diplomat_wrapped_struct_options = options;
capi::ICU4XFixedDecimalFormatResult diplomat_raw_struct_out_value = capi::ICU4XFixedDecimalFormat_try_new(locale.AsFFI(), provider.AsFFI(), capi::ICU4XFixedDecimalFormatOptions{ .grouping_strategy = diplomat_wrapped_struct_options.grouping_strategy, .sign_display = diplomat_wrapped_struct_options.sign_display });
capi::ICU4XFixedDecimalFormatResult diplomat_raw_struct_out_value = capi::ICU4XFixedDecimalFormat_try_new(locale.AsFFI(), provider.AsFFI(), capi::ICU4XFixedDecimalFormatOptions{ .grouping_strategy = static_cast<ssize_t>(diplomat_wrapped_struct_options.grouping_strategy), .sign_display = static_cast<ssize_t>(diplomat_wrapped_struct_options.sign_display) });
auto diplomat_optional_raw_out_value_fdf = diplomat_raw_struct_out_value.fdf;
std::optional<ICU4XFixedDecimalFormat> diplomat_optional_out_value_fdf;
if (diplomat_optional_raw_out_value_fdf != nullptr) {
Expand All @@ -143,10 +158,12 @@ std::string ICU4XFixedDecimalFormat::format_write(const ICU4XFixedDecimal& value

ICU4XFixedDecimalFormatOptions ICU4XFixedDecimalFormatOptions::default_() {
capi::ICU4XFixedDecimalFormatOptions diplomat_raw_struct_out_value = capi::ICU4XFixedDecimalFormatOptions_default();
return ICU4XFixedDecimalFormatOptions{ .grouping_strategy = std::move(diplomat_raw_struct_out_value.grouping_strategy), .sign_display = std::move(diplomat_raw_struct_out_value.sign_display) };
return ICU4XFixedDecimalFormatOptions{ .grouping_strategy = std::move(ICU4XFixedDecimalGroupingStrategy{ diplomat_raw_struct_out_value.grouping_strategy }), .sign_display = std::move(ICU4XFixedDecimalSignDisplay{ diplomat_raw_struct_out_value.sign_display }) };
}




ICU4XLocale ICU4XLocale::new_(const std::string name) {
return ICU4XLocale(capi::ICU4XLocale_new(name.data(), name.length()));
}
Loading

0 comments on commit 306367c

Please sign in to comment.