Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions documentation/source/messaging.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,34 @@ struct Inner {
my_field: bool,
}
```

## Ignoring fields / variants

To ignore a field or variant, annotate it with `#[serde(skip)]`. This is useful when transferring partially private data because it allows you to specify which data is exposed to Dart. See Serde's documentation on [variant](https://serde.rs/variant-attrs.html) and [field](https://serde.rs/field-attrs.html) attributes for more information on how Serde handles this attribute.

```{code-block} rust
:caption: Rust
#[derive(Serialize, RustSignal)]
struct UpdateMessage {
event: String,
struct_data: StructData,
enum_data: EnumData,
}

#[derive(Serialize, SignalPiece)]
struct StructData {
my_public_field: bool,
#[serde(skip)]
my_private_field: bool,
}

#[derive(Serialize, SignalPiece)]
enum EnumData {
Variant1(i32, #[serde(skip)] i32),
Variant2 {
my_public_field: bool,
#[serde(skip)]
my_private_field: bool,
},
}
```
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ pub enum SerdeData {
OtherTypes(Box<OtherTypes>),
UnitVariant,
NewTypeVariant(String),
TupleVariant(u32, u64),
TupleVariant(u32, #[serde(skip)] NotSerializable, u64),
StructVariant {
#[serde(skip)]
ignored: NotSerializable,
f0: UnitStruct,
f1: NewTypeStruct,
f2: TupleStruct,
Expand Down Expand Up @@ -107,3 +109,6 @@ pub enum CStyleEnum {
D,
E = 10,
}

#[derive(Default, PartialEq, Clone)]
pub struct NotSerializable;
9 changes: 5 additions & 4 deletions flutter_package/example/native/hub/src/testing/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::signals::{
CStyleEnum, ComplexSignalTestResult, List, NewTypeStruct, OtherTypes,
PrimitiveTypes, SerdeData, SimpleList, Struct, Tree, TupleStruct, UnitStruct,
UnitTestEnd, UnitTestStart,
CStyleEnum, ComplexSignalTestResult, List, NewTypeStruct, NotSerializable,
OtherTypes, PrimitiveTypes, SerdeData, SimpleList, Struct, Tree, TupleStruct,
UnitStruct, UnitTestEnd, UnitTestStart,
};
use rinf::{DartSignal, RustSignal};
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
Expand Down Expand Up @@ -163,9 +163,10 @@ fn get_complex_signals() -> Vec<SerdeData> {
"test.\u{10348}.\u{00a2}\u{0939}\u{20ac}\u{d55c}..".to_string(),
);

let v5 = SerdeData::TupleVariant(3, 6);
let v5 = SerdeData::TupleVariant(3, NotSerializable, 6);

let v6 = SerdeData::StructVariant {
ignored: NotSerializable,
f0: UnitStruct,
f1: NewTypeStruct(1),
f2: TupleStruct(2, 3),
Expand Down
41 changes: 39 additions & 2 deletions rust_crate_cli/src/tool/generate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ use std::sync::mpsc::channel;
use std::time::Duration;
use syn::spanned::Spanned;
use syn::{
Attribute, Expr, File, GenericArgument, Item, ItemEnum, ItemStruct, Lit,
PathArguments, Type, TypeArray, TypePath, TypeTuple,
Attribute, Expr, Field, File, GenericArgument, Item, ItemEnum, ItemStruct,
Lit, PathArguments, Type, TypeArray, TypePath, TypeTuple, Variant,
};

static GEN_MOD: &str = "signals";
Expand Down Expand Up @@ -225,6 +225,7 @@ fn trace_struct(traced: &mut Traced, item: &ItemStruct) {
let fields: Vec<Format> = unnamed
.unnamed
.iter()
.filter(is_kept)
.map(|field| to_type_format(&field.ty))
.collect();
if fields.is_empty() {
Expand All @@ -239,6 +240,7 @@ fn trace_struct(traced: &mut Traced, item: &ItemStruct) {
let fields = named
.named
.iter()
.filter(is_kept)
.filter_map(|field| {
field.ident.as_ref().map(|ident| Named {
name: ident.to_string(),
Expand All @@ -264,6 +266,7 @@ fn trace_enum(traced: &mut Traced, item: &ItemEnum) {
let variants: BTreeMap<u32, Named<VariantFormat>> = item
.variants
.iter()
.filter(is_kept)
.map(|variant| {
let name = variant.ident.to_string();
let variant_format = match &variant.fields {
Expand All @@ -272,6 +275,7 @@ fn trace_enum(traced: &mut Traced, item: &ItemEnum) {
let fields = unnamed
.unnamed
.iter()
.filter(is_kept)
.map(|field| to_type_format(&field.ty))
.collect::<Vec<_>>();
if fields.is_empty() {
Expand All @@ -286,6 +290,7 @@ fn trace_enum(traced: &mut Traced, item: &ItemEnum) {
let fields = named
.named
.iter()
.filter(is_kept)
.filter_map(|field| {
field.ident.as_ref().map(|ident| Named {
name: ident.to_string(),
Expand All @@ -311,6 +316,38 @@ fn trace_enum(traced: &mut Traced, item: &ItemEnum) {
traced.registry.insert(type_name, container);
}

/// Returns `false` if Serde skips `item` during serialization.
fn is_kept<T: GetAttrs>(item: &T) -> bool {
!item.get_attrs().iter().any(|attr| {
if !attr.path().is_ident("serde") {
return false;
}
let mut skip = false;
let _ = attr.parse_nested_meta(|meta| {
if meta.path.is_ident("skip") {
skip = true;
}
Ok(())
});
skip
})
}

/// Helper trait required for [`is_kept`].
trait GetAttrs {
fn get_attrs(&self) -> &Vec<Attribute>;
}
impl GetAttrs for &Field {
fn get_attrs(&self) -> &Vec<Attribute> {
&self.attrs
}
}
impl GetAttrs for &Variant {
fn get_attrs(&self) -> &Vec<Attribute> {
&self.attrs
}
}

/// Checks that the name of newly found signal is usable.
fn check_signal_name(name: &str, traced: &Traced) -> Result<(), SetupError> {
if traced.registry.contains_key(name) {
Expand Down
Loading