Unverified Commit f0ef4282 authored by Mark Hammond's avatar Mark Hammond Committed by GitHub
Browse files

Allow UDL to define Enums with objects (#2412)

proc-macros already support this, as verified by new tests.

Fixes #1372
parent b46ab54c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -49,6 +49,8 @@ or use UDL with types from more than one crate.

- External errors work for Swift and Python. Kotlin does not work - see #2392.

- Proc-macros now allow Enums to hold objects (#1372)

### What's changed?

- Switching jinja template engine from askama to rinja.
+6 −0
Original line number Diff line number Diff line
@@ -93,6 +93,12 @@ interface MaybeSimpleDict {
    Nah();
};

[Enum]
interface MaybeObject {
    Obj(Patch p);
    Nah();
};

// Note that UDL *can not* express flat enums (ie, those with variants that carry data which
// should be ignored for the ffi), only flat errors?
//enum SimpleFlatEnum {
+17 −0
Original line number Diff line number Diff line
@@ -265,6 +265,23 @@ fn get_maybe_simple_dict(index: i8) -> MaybeSimpleDict {
    }
}

#[derive(Debug)]
enum MaybeObject {
    Obj { p: Arc<Patch> },
    Nah,
}

#[uniffi::export]
fn get_maybe_object(index: i8) -> MaybeObject {
    match index {
        0 => MaybeObject::Obj {
            p: Arc::new(Patch { color: Color::Red }),
        },
        1 => MaybeObject::Nah,
        _ => unreachable!("invalid index: {index}"),
    }
}

// UDL can not describe this as a "flat" enum, but we'll keep it here to help demonstrate that!
#[derive(Debug, Clone)]
pub enum SimpleFlatEnum {
+8 −0
Original line number Diff line number Diff line
@@ -195,6 +195,14 @@ class TestCoverall(unittest.TestCase):
        e = get_simple_flat_macro_enum(0)
        self.assertTrue(isinstance(e, SimpleFlatMacroEnum.FIRST))

        self.assertTrue(get_maybe_simple_dict(0).is_YEAH())
        self.assertEqual(get_maybe_simple_dict(0).d.text, "")
        self.assertTrue(get_maybe_simple_dict(1).is_NAH())

        self.assertTrue(get_maybe_object(0).is_OBJ())
        self.assertEqual(get_maybe_object(0).p.get_color(), Color.RED)
        self.assertTrue(get_maybe_object(1).is_NAH())

    def test_self_by_arc(self):
        coveralls = Coveralls("test_self_by_arc")
        # One reference is held by the handlemap, and one by the `Arc<Self>` method receiver.
+45 −11
Original line number Diff line number Diff line
@@ -2,6 +2,8 @@
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::sync::Arc;

pub enum Animal {
    Dog,
    Cat,
@@ -39,29 +41,61 @@ pub enum AnimalSignedInt {
    Wombat,  // 1
}

#[derive(uniffi::Record)]
#[derive(Default, PartialEq, Eq, Clone, uniffi::Record)]
pub struct AnimalRecord {
    value: u8,
    name: String,
}

impl AnimalRecord {
    fn new(name: &str) -> Self {
        Self {
            name: name.to_string(),
        }
    }
}

#[derive(uniffi::Object)]
#[derive(Default, PartialEq, Eq, uniffi::Object)]
#[uniffi::export(Eq)]
pub struct AnimalObject {
    pub value: AnimalRecord,
}

use std::sync::Arc;
// Adding an enum with a Associated Type that is a exported Arc<Object> with a exported Record field.
// This is done to check for compilation errors.
impl AnimalObject {
    fn new(name: &str) -> Self {
        Self {
            value: AnimalRecord::new(name),
        }
    }
}

#[uniffi::export]
impl AnimalObject {
    fn get_record(&self) -> AnimalRecord {
        self.value.clone()
    }
}

// An enum with non-primitive types
#[derive(uniffi::Enum)]
pub(crate) enum AnimalAssociatedType {
pub(crate) enum AnimalEnum {
    None,
    Dog(Arc<AnimalObject>),
    Cat,
    Cat(AnimalRecord),
}

#[uniffi::export]
fn get_animal_enum(animal: Animal) -> AnimalEnum {
    match animal {
        Animal::Dog => AnimalEnum::Dog(Arc::new(AnimalObject::new("dog"))),
        Animal::Cat => AnimalEnum::Cat(AnimalRecord::new("cat")),
    }
}

#[derive(uniffi::Enum)]
pub(crate) enum AnimalNamedAssociatedType {
    Dog { value: Arc<AnimalObject> },
    Cat,
pub(crate) enum AnimalNamedEnum {
    None,
    Dog { object: Arc<AnimalObject> },
    Cat { record: AnimalRecord },
}

#[uniffi::export]
Loading