Skip to content

Commit

Permalink
Add defaults for properties in Records (#316) r=rfk
Browse files Browse the repository at this point in the history
* Implement defaults in constructors for swift and kotlin

* Tidy literals for python

* Add tests for defaults in constructors
  • Loading branch information
jhugman authored Oct 7, 2020
1 parent c97e301 commit 29eebbd
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 6 deletions.
24 changes: 24 additions & 0 deletions examples/rondpoint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,12 @@ impl Retourneur {
fn identique_nombres(&self, value: DictionnaireNombres) -> DictionnaireNombres {
value
}
fn identique_optionneur_dictionnaire(
&self,
value: OptionneurDictionnaire,
) -> OptionneurDictionnaire {
value
}
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -257,4 +263,22 @@ impl Optionneur {
}
}

struct OptionneurDictionnaire {
i8_var: i8,
u8_var: u8,
i16_var: i16,
u16_var: u16,
i32_var: i32,
u32_var: u32,
i64_var: i64,
u64_var: u64,
float_var: f32,
double_var: f64,
boolean_var: bool,
string_var: String,
list_var: Vec<String>,
enumeration_var: Enumeration,
dictionnaire_var: Option<minusculeMAJUSCULEEnum>,
}

include!(concat!(env!("OUT_DIR"), "/rondpoint.uniffi.rs"));
19 changes: 19 additions & 0 deletions examples/rondpoint/src/rondpoint.idl
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ interface Retourneur {

DictionnaireNombresSignes identique_nombres_signes(DictionnaireNombresSignes value);
DictionnaireNombres identique_nombres(DictionnaireNombres value);
OptionneurDictionnaire identique_optionneur_dictionnaire(OptionneurDictionnaire value);
};

interface Stringifier {
Expand Down Expand Up @@ -114,4 +115,22 @@ interface Optionneur {

// Enums, which we have to treat as strings in the IDL frontend.
Enumeration sinon_enum(optional Enumeration value = "Trois");
};

dictionary OptionneurDictionnaire {
i8 i8_var = -8;
u8 u8_var = 8;
i16 i16_var = -0x10;
u16 u16_var = 0x10;
i32 i32_var = -32;
u32 u32_var = 32;
i64 i64_var = -64;
u64 u64_var = 64;
float float_var = 4.0;
double double_var = 8.0;
boolean boolean_var = true;
string string_var = "default";
sequence<string> list_var = [];
Enumeration enumeration_var = "DEUX";
minusculeMAJUSCULEEnum? dictionnaire_var = null;
};
30 changes: 29 additions & 1 deletion examples/rondpoint/tests/bindings/test_rondpoint.kts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ listOf(-1, 0, 1).map { DictionnaireNombresSignes(it.toByte(), it.toShort(), it.t
listOf(0, 1).map { DictionnaireNombres(it.toUByte(), it.toUShort(), it.toUInt(), it.toULong()) }
.affirmAllerRetour(rt::identiqueNombres)


rt.destroy()

// Test one way across the FFI.
Expand Down Expand Up @@ -202,4 +203,31 @@ listOf(0.0, 1.0).affirmAllerRetour(op::sinonF64)
// enums
Enumeration.values().toList().affirmAllerRetour(op::sinonEnum)

op.destroy()
op.destroy()

// Testing defaulting properties in record types.
val defaultes = OptionneurDictionnaire()
val explicite = OptionneurDictionnaire(
i8Var = -8,
u8Var = 8u,
i16Var = -16,
u16Var = 0x10u,
i32Var = -32,
u32Var = 32u,
i64Var = -64L,
u64Var = 64uL,
floatVar = 4.0f,
doubleVar = 8.0,
booleanVar = true,
stringVar = "default",
listVar = listOf(),
enumerationVar = Enumeration.DEUX,
dictionnaireVar = null
)
assert(defaultes == explicite)

// …and makes sure they travel across and back the FFI.
val rt2 = Retourneur()
listOf(defaultes).affirmAllerRetour(rt2::identiqueOptionneurDictionnaire)

rt2.destroy()
24 changes: 24 additions & 0 deletions examples/rondpoint/tests/bindings/test_rondpoint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -193,3 +193,27 @@ assert(op.sinonEnum() == .trois)

// enums
[.un, .deux, .trois].affirmAllerRetour(op.sinonEnum)

// Testing defaulting properties in record types.
let defaultes = OptionneurDictionnaire()
let explicite = OptionneurDictionnaire(
i8Var: Int8(-8),
u8Var: UInt8(8),
i16Var: Int16(-16),
u16Var: UInt16(0x10),
i32Var: -32,
u32Var: UInt32(32),
i64Var: Int64(-64),
u64Var: UInt64(64),
floatVar: Float(4.0),
doubleVar: Double(8.0),
booleanVar: true,
stringVar: "default",
listVar: [],
enumerationVar: .deux,
dictionnaireVar: nil
)

// …and makes sure they travel across and back the FFI.
assert(defaultes == explicite)
[defaultes].affirmAllerRetour(rt.identiqueOptionneurDictionnaire)
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
data class {{ rec.name()|class_name_kt }} (
{%- for field in rec.fields() %}
val {{ field.name()|var_name_kt }}: {{ field.type_()|type_kt }}{% if loop.last %}{% else %},{% endif %}
val {{ field.name()|var_name_kt }}: {{ field.type_()|type_kt -}}
{%- match field.default_value() %}
{%- when Some with(literal) %} = {{ literal|literal_kt }}
{%- else %}
{%- endmatch -%}
{% if !loop.last %}, {% endif %}
{%- endfor %}
) {
companion object {
Expand Down
14 changes: 11 additions & 3 deletions uniffi_bindgen/src/bindings/python/gen_python.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,17 @@ mod filters {
Type::Enum(name) => format!("{}.{}", class_name_py(name)?, enum_name_py(v)?),
_ => panic!("Unexpected type in enum literal: {:?}", type_),
},
// TODO: render with the intended radix.
Literal::Int(i, _radix, _type_) => format!("{}", i),
Literal::UInt(i, _radix, _type_) => format!("{}", i),
// https://docs.python.org/3/reference/lexical_analysis.html#integer-literals
Literal::Int(i, radix, _) => match radix {
Radix::Octal => format!("0o{:o}", i),
Radix::Decimal => format!("{}", i),
Radix::Hexadecimal => format!("{:#x}", i),
},
Literal::UInt(i, radix, _) => match radix {
Radix::Octal => format!("0o{:o}", i),
Radix::Decimal => format!("{}", i),
Radix::Hexadecimal => format!("{:#x}", i),
},
Literal::Float(string, _type_) => string.clone(),
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ public struct {{ rec.name()|class_name_swift }}: ViaFfiUsingByteBuffer, ViaFfi,
// declare one manually.
public init(
{%- for field in rec.fields() %}
{{ field.name()|var_name_swift }}: {{ field.type_()|type_swift }}{% if loop.last %}{% else %},{% endif %}
{{ field.name()|var_name_swift }}: {{ field.type_()|type_swift -}}
{%- match field.default_value() %}
{%- when Some with(literal) %} = {{ literal|literal_swift }}
{%- else %}
{%- endmatch -%}
{% if !loop.last %}, {% endif %}
{%- endfor %}
) {
{%- for field in rec.fields() %}
Expand Down
3 changes: 3 additions & 0 deletions uniffi_bindgen/src/interface/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1090,6 +1090,9 @@ impl Field {
pub fn type_(&self) -> Type {
self.type_.clone()
}
pub fn default_value(&self) -> Option<Literal> {
self.default.clone()
}
}

impl APIConverter<Field> for weedle::dictionary::DictionaryMember<'_> {
Expand Down

0 comments on commit 29eebbd

Please sign in to comment.