Skip to main content

Properties (Accessors)

The pub fields of an opaque struct will be automatically translated, such that it can be used as if it is a normal field.

Example

Suppose we have the following opaque type:

pub struct MyOpaqueType {
pub name: String,
#[frb(ignore)]
pub no_accessor: String,
db: Database,
}

Then, the public field, name, will be recognized. The getters and setters will be generated:

// Auto-generated class
class MyOpaqueType {
String get name => ...;
set name(String value) => ...;
...
}

Then, we can use it as if it is a normal field:

var object = MyOpaqueType();
object.name += 'a';
print('Hi ${object.name}');

Disabling the automatic accessors

Sometimes we don't want all or any of the pub fields to have accessors automatically generated for them. For this case you can use the ignore and ignore_all attributes.

Adding the ignore attribute to a field will disable the automatic accessor from being generated for that field. Using the ignore_all attribute on a struct is equivalent to applying the ignore attribute to all of its fields.

When using ignore_all you can allow accessors from being generated only for specific fields by annotating those fields with the unignore attribute. The names are experimental and may change in the future.

Caveats

tip

There is no need to memorize anything here (or anything in doc) - the code generator will provide warnings when detecting non-best-practices.

Problem description

Because borrowed types are not (yet) supported, the current implementation clones the field when reading it. This is no problem when the field type is something like integers, Strings, or RustAutoOpaque<T>s. However, it may be confusing in some scenarios. For example,

#[frb(opaque)]
pub struct A {
pub b: B,
}

#[frb(opaque)]
pub struct B {
pub c: i32,
}

Then, usage like

var a = A(...);
a.b.c += 1;
print(a.b.c); // unchanged

may be confusing since the a.b.c is not changed. This is because each access to a.b creates a brand new B instance.

Solution 1

One solution is to just add RustAutoOpaque<...> like below. It will not affect other things, for example, the generated type will still be B.

pub struct A {
pub b: RustAutoOpaque<B>,
}

It works because RustAutoOpaque<T> is indeed an Arc, thus the cloned b will point to the very same object instead of a brand new object.

To create/read/write objects of type RustAutoOpaque<...>, please refer to this page.

Solution 2

Another way is to make the struct non-opaque (possibly by adding #[frb(non_opaque)]).

Solution 3

Yet another way is to utilize the proxy feature.

This may be the default generated code instead in the future. If this simplifies your scenario a lot, feel free to create an issue to discuss.