Skip to content

Commit

Permalink
Merge pull request #1565 from fzyzcjy/feat/1564
Browse files Browse the repository at this point in the history
Support map and set
  • Loading branch information
fzyzcjy authored Jan 3, 2024
2 parents 27bf57d + 6cd55e7 commit 2e198ec
Show file tree
Hide file tree
Showing 54 changed files with 15,215 additions and 1,571 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ keywords = ["flutter", "dart", "ffi", "code-generation", "bindings"]
categories = ["development-tools::ffi"]

[workspace.dependencies]
allo-isolate = { version = "0.1.21", features = ["anyhow"] }
allo-isolate = { version = "0.1.22", features = ["anyhow"] }
anyhow = "1.0.64"
chrono = "0.4.23"
lazy_static = "1.4.0"
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,15 @@ impl<'a> ApiDartGeneratorInfoTrait for DelegateApiDartGenerator<'a> {
// IrTypeDelegate::Uuids => "List<UuidValue>".to_owned(),
IrTypeDelegate::Backtrace => "String".to_string(),
IrTypeDelegate::AnyhowException => "AnyhowException".to_string(),
IrTypeDelegate::Map(ir) => format!(
"Map<{}, {}>",
ApiDartGenerator::new(*ir.key.clone(), self.context).dart_api_type(),
ApiDartGenerator::new(*ir.value.clone(), self.context).dart_api_type(),
),
IrTypeDelegate::Set(ir) => format!(
"Set<{}>",
ApiDartGenerator::new(*ir.inner.clone(), self.context).dart_api_type(),
),
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::codegen::generator::api_dart::spec_generator::base::ApiDartGenerator;
use crate::codegen::generator::codec::sse::lang::*;
use crate::codegen::generator::codec::sse::ty::*;
use crate::codegen::ir::ty::delegate::IrTypeDelegatePrimitiveEnum;
use crate::codegen::ir::ty::delegate::{IrTypeDelegatePrimitiveEnum, IrTypeDelegateSet};
use crate::library::codegen::generator::api_dart::spec_generator::info::ApiDartGeneratorInfoTrait;
use itertools::Itertools;

Expand All @@ -22,6 +22,12 @@ impl<'a> CodecSseTyTrait for DelegateCodecSseTy<'a> {
lang.throw_unimplemented(UNIMPLEMENTED_MESSAGE)
));
}
IrTypeDelegate::Map(_) => {
"self.entries.map((e) => (e.key, e.value)).toList()".to_owned()
}
IrTypeDelegate::Set(ir) => {
generate_set_to_list(ir, self.context.as_api_dart_context(), "self")
}
// frb-coverage:ignore-start
_ => unreachable!(),
// frb-coverage:ignore-end
Expand All @@ -34,6 +40,8 @@ impl<'a> CodecSseTyTrait for DelegateCodecSseTy<'a> {
IrTypeDelegate::PrimitiveEnum(_) => "self as _".to_owned(),
IrTypeDelegate::Backtrace => r#"format!("{:?}", self)"#.to_owned(),
IrTypeDelegate::AnyhowException => r#"format!("{:?}", self)"#.to_owned(),
IrTypeDelegate::Map(_) => "self.into_iter().collect()".to_owned(),
IrTypeDelegate::Set(_) => "self.into_iter().collect()".to_owned(),
// frb-coverage:ignore-start
_ => unreachable!(),
// frb-coverage:ignore-end
Expand Down Expand Up @@ -68,6 +76,10 @@ impl<'a> CodecSseTyTrait for DelegateCodecSseTy<'a> {
}
IrTypeDelegate::Backtrace => "inner".to_owned(),
IrTypeDelegate::AnyhowException => "AnyhowException(inner)".to_owned(),
IrTypeDelegate::Map(_) => {
"Map.fromEntries(inner.map((e) => MapEntry(e.$1, e.$2)))".to_owned()
}
IrTypeDelegate::Set(_) => "Set.from(inner)".to_owned(),
// frb-coverage:ignore-start
_ => unreachable!(),
// frb-coverage:ignore-end
Expand All @@ -86,6 +98,8 @@ impl<'a> CodecSseTyTrait for DelegateCodecSseTy<'a> {
lang.throw_unimplemented(UNIMPLEMENTED_MESSAGE)
));
}
IrTypeDelegate::Map(_) => "inner.into_iter().collect()".to_owned(),
IrTypeDelegate::Set(_) => "inner.into_iter().collect()".to_owned(),
// frb-coverage:ignore-start
_ => unreachable!(),
// frb-coverage:ignore-end
Expand Down Expand Up @@ -147,3 +161,22 @@ pub(crate) fn rust_decode_primitive_enum(

const UNIMPLEMENTED_MESSAGE: &str =
"not yet supported in serialized mode, feel free to create an issue";

pub(crate) fn generate_set_to_list(
ir: &IrTypeDelegateSet,
context: ApiDartGeneratorContext,
inner: &str,
) -> String {
let mut ans = format!("{inner}.toList()");
if let Primitive(_) = &*ir.inner {
ans = format!(
"{}.fromList({ans})",
ApiDartGenerator::new(
IrTypeDelegate::Set(ir.to_owned()).get_delegate().clone(),
context
)
.dart_api_type()
);
}
ans
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::codegen::generator::acc::Acc;
use crate::codegen::generator::codec::sse::ty::delegate::generate_set_to_list;
use crate::codegen::generator::misc::target::Target;
use crate::codegen::generator::wire::dart::spec_generator::codec::cst::base::*;
use crate::codegen::generator::wire::dart::spec_generator::codec::cst::encoder::ty::WireDartCodecCstGeneratorEncoderTrait;
Expand Down Expand Up @@ -106,6 +107,15 @@ impl<'a> WireDartCodecCstGeneratorEncoderTrait for DelegateWireDartCodecCstGener
IrTypeDelegate::Backtrace | IrTypeDelegate::AnyhowException => {
Acc::distribute(Some("throw UnimplementedError();".to_string()))
}
IrTypeDelegate::Map(_) => Acc::distribute(Some(format!(
"return cst_encode_{}(raw.entries.map((e) => (e.key, e.value)).toList());",
self.ir.get_delegate().safe_ident()
))),
IrTypeDelegate::Set(ir) => Acc::distribute(Some(format!(
"return cst_encode_{}({});",
self.ir.get_delegate().safe_ident(),
generate_set_to_list(ir, self.context.as_api_dart_context(), "raw"),
))),
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,14 @@ impl<'a> WireDartCodecDcoGeneratorDecoderTrait for DelegateWireDartCodecDcoGener
// );
// ".to_owned(),
IrTypeDelegate::AnyhowException => "return AnyhowException(raw as String);".to_owned(),
IrTypeDelegate::Map(_) => format!(
"return Map.fromEntries(dco_decode_{}(raw).map((e) => MapEntry(e.$1, e.$2)));",
self.ir.get_delegate().safe_ident(),
),
IrTypeDelegate::Set(_) => format!(
"return Set.from(dco_decode_{}(raw));",
self.ir.get_delegate().safe_ident(),
),
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use crate::codegen::generator::wire::rust::spec_generator::codec::cst::base::*;
use crate::codegen::generator::wire::rust::spec_generator::codec::cst::decoder::ty::WireRustCodecCstGeneratorDecoderTrait;
use crate::codegen::generator::wire::rust::spec_generator::output_code::WireRustOutputCode;
use crate::codegen::ir::ty::delegate::{
IrTypeDelegate, IrTypeDelegatePrimitiveEnum, IrTypeDelegateTime,
IrTypeDelegate, IrTypeDelegateArray, IrTypeDelegateMap, IrTypeDelegatePrimitiveEnum,
IrTypeDelegateSet, IrTypeDelegateTime,
};
use crate::library::codegen::ir::ty::IrTypeTrait;

Expand All @@ -17,22 +18,6 @@ impl<'a> WireRustCodecCstGeneratorDecoderTrait for DelegateWireRustCodecCstGener

fn generate_impl_decode_body(&self) -> Acc<Option<String>> {
match &self.ir {
IrTypeDelegate::Array(array) => {
let acc =
Some(
format!(
"let vec: Vec<{}> = self.cst_decode(); flutter_rust_bridge::for_generated::from_vec_to_array(vec)",
array.inner().rust_api_type()
),
);
if is_js_value(&array.inner()) {
return Acc {
io: acc,
..Default::default()
};
}
Acc::distribute(acc)
},
IrTypeDelegate::String => {
Acc {
web: Some("self".into()),
Expand Down Expand Up @@ -92,6 +77,11 @@ impl<'a> WireRustCodecCstGeneratorDecoderTrait for DelegateWireRustCodecCstGener
TargetOrCommon::Common => None,
TargetOrCommon::Io | TargetOrCommon::Web => Some("unimplemented!()".into()),
}),
IrTypeDelegate::Array(array) => {
self.generate_skip_web_if_jsvalue(generate_decode_array(array))
},
IrTypeDelegate::Map(ir) => self.generate_skip_web_if_jsvalue(generate_decode_map(ir)),
IrTypeDelegate::Set(ir) => self.generate_skip_web_if_jsvalue(generate_decode_set(ir)),
}
}

Expand All @@ -115,12 +105,11 @@ impl<'a> WireRustCodecCstGeneratorDecoderTrait for DelegateWireRustCodecCstGener
"self.unchecked_into::<flutter_rust_bridge::for_generated::js_sys::Uint8Array>().to_vec().into_boxed_slice().cst_decode()"
.into()
}
IrTypeDelegate::Array(array) => format!(
"let vec: Vec<{}> = self.cst_decode(); flutter_rust_bridge::for_generated::from_vec_to_array(vec)",
array.inner().rust_api_type()
)
.into(),
IrTypeDelegate::Backtrace | IrTypeDelegate::AnyhowException => "unimplemented!()".into(),
IrTypeDelegate::Array(array) => generate_decode_array(array)
.into(),
IrTypeDelegate::Map(ir) => generate_decode_map(ir).into(),
IrTypeDelegate::Set(ir) => generate_decode_set(ir).into(),
})
}

Expand All @@ -146,3 +135,38 @@ impl<'a> WireRustCodecCstGeneratorDecoderTrait for DelegateWireRustCodecCstGener
.rust_wire_is_pointer(target)
}
}

impl<'a> DelegateWireRustCodecCstGenerator<'a> {
fn generate_skip_web_if_jsvalue(&self, acc: String) -> Acc<Option<String>> {
if is_js_value(&self.ir.get_delegate()) {
Acc {
io: Some(acc),
..Default::default()
}
} else {
Acc::distribute(Some(acc))
}
}
}

fn generate_decode_array(array: &IrTypeDelegateArray) -> String {
format!(
"let vec: Vec<{}> = self.cst_decode(); flutter_rust_bridge::for_generated::from_vec_to_array(vec)",
array.inner().rust_api_type()
)
}

fn generate_decode_map(ir: &IrTypeDelegateMap) -> String {
format!(
"let vec: Vec<({}, {})> = self.cst_decode(); vec.into_iter().collect()",
ir.key.rust_api_type(),
ir.value.rust_api_type(),
)
}

fn generate_decode_set(ir: &IrTypeDelegateSet) -> String {
format!(
"let vec: Vec<{}> = self.cst_decode(); vec.into_iter().collect()",
ir.inner.rust_api_type()
)
}
29 changes: 28 additions & 1 deletion frb_codegen/src/library/codegen/ir/ty/delegate.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use crate::codegen::ir::namespace::Namespace;
use crate::codegen::ir::ty::enumeration::IrTypeEnumRef;
use crate::codegen::ir::ty::general_list::IrTypeGeneralList;
use crate::codegen::ir::ty::general_list::{ir_list, IrTypeGeneralList};
use crate::codegen::ir::ty::primitive::IrTypePrimitive;
use crate::codegen::ir::ty::primitive_list::IrTypePrimitiveList;
use crate::codegen::ir::ty::record::IrTypeRecord;
use crate::codegen::ir::ty::{IrContext, IrType, IrTypeTrait};

crate::ir! {
Expand All @@ -19,6 +20,8 @@ pub enum IrTypeDelegate {
// Uuids,// TODO avoid this special case?
Backtrace,
AnyhowException,
Map(IrTypeDelegateMap),
Set(IrTypeDelegateSet),
}

pub struct IrTypeDelegateArray {
Expand All @@ -45,6 +48,16 @@ pub enum IrTypeDelegateTime {
Naive,
Duration,
}

pub struct IrTypeDelegateMap {
pub key: Box<IrType>,
pub value: Box<IrType>,
pub element_delegate: IrTypeRecord,
}

pub struct IrTypeDelegateSet {
pub inner: Box<IrType>,
}
}

impl IrTypeTrait for IrTypeDelegate {
Expand Down Expand Up @@ -77,6 +90,10 @@ impl IrTypeTrait for IrTypeDelegate {
// IrTypeDelegate::Uuids => "Uuids".to_owned(),
IrTypeDelegate::Backtrace => "Backtrace".to_owned(),
IrTypeDelegate::AnyhowException => "AnyhowException".to_owned(),
IrTypeDelegate::Map(ir) => {
format!("Map_{}_{}", ir.key.safe_ident(), ir.value.safe_ident())
}
IrTypeDelegate::Set(ir) => format!("Set_{}", ir.inner.safe_ident()),
}
}

Expand Down Expand Up @@ -114,6 +131,14 @@ impl IrTypeTrait for IrTypeDelegate {
// IrTypeDelegate::Uuids => "Vec<uuid::Uuid>".to_owned(),
IrTypeDelegate::Backtrace => "backtrace::Backtrace".to_owned(),
IrTypeDelegate::AnyhowException => "anyhow::Error".to_owned(),
IrTypeDelegate::Map(ir) => format!(
"std::collections::HashMap<{}, {}>",
ir.key.rust_api_type(),
ir.value.rust_api_type()
),
IrTypeDelegate::Set(ir) => {
format!("std::collections::HashSet<{}>", ir.inner.rust_api_type())
}
}
}

Expand Down Expand Up @@ -160,6 +185,8 @@ impl IrTypeDelegate {
// }),
IrTypeDelegate::Backtrace => IrType::Delegate(IrTypeDelegate::String),
IrTypeDelegate::AnyhowException => IrType::Delegate(IrTypeDelegate::String),
IrTypeDelegate::Map(ir) => ir_list(IrType::Record(ir.element_delegate.clone())),
IrTypeDelegate::Set(ir) => ir_list(*ir.inner.to_owned()),
}
}
}
Expand Down
18 changes: 18 additions & 0 deletions frb_codegen/src/library/codegen/ir/ty/general_list.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use crate::codegen::ir::ty::primitive::IrTypePrimitive;
use crate::codegen::ir::ty::primitive_list::IrTypePrimitiveList;
use crate::codegen::ir::ty::IrType::{GeneralList, PrimitiveList};
use crate::codegen::ir::ty::{IrContext, IrType, IrTypeTrait};

crate::ir! {
Expand All @@ -23,3 +26,18 @@ impl IrTypeTrait for IrTypeGeneralList {
format!("Vec<{}>", self.inner.rust_api_type())
}
}

pub(crate) fn ir_list(inner: IrType) -> IrType {
match inner {
// Since Dart doesn't have a boolean primitive list like `Uint8List`,
// we need to convert `Vec<bool>` to a boolean general list in order to achieve the binding.
IrType::Primitive(inner) if inner != IrTypePrimitive::Bool => {
PrimitiveList(IrTypePrimitiveList {
primitive: inner.clone(),
})
}
_ => GeneralList(IrTypeGeneralList {
inner: Box::new(inner),
}),
}
}
19 changes: 18 additions & 1 deletion frb_codegen/src/library/codegen/parser/type_parser/concrete.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use crate::codegen::ir::ty::boxed::IrTypeBoxed;
use crate::codegen::ir::ty::dart_opaque::IrTypeDartOpaque;
use crate::codegen::ir::ty::delegate::{IrTypeDelegate, IrTypeDelegateTime};
use crate::codegen::ir::ty::delegate::{
IrTypeDelegate, IrTypeDelegateMap, IrTypeDelegateSet, IrTypeDelegateTime,
};
use crate::codegen::ir::ty::dynamic::IrTypeDynamic;
use crate::codegen::ir::ty::general_list::ir_list;
use crate::codegen::ir::ty::unencodable::IrTypeUnencodable;
use crate::codegen::ir::ty::IrType;
use crate::codegen::ir::ty::IrType::{Boxed, DartOpaque, Delegate, Dynamic, Unencodable};
Expand Down Expand Up @@ -42,6 +45,20 @@ impl<'a, 'b, 'c> TypeParserWithContext<'a, 'b, 'c> {
inner: Box::new(inner.clone()),
}),

("Vec", Some(Generic([element]))) => ir_list(element.to_owned()),

("HashMap", Some(Generic([key, value]))) => Delegate(IrTypeDelegate::Map(IrTypeDelegateMap {
key: Box::new(key.clone()),
value: Box::new(value.clone()),
element_delegate: self.create_ir_record(vec![
key.clone(),
value.clone(),
]),
})),
("HashSet", Some(Generic([inner]))) => Delegate(IrTypeDelegate::Set(IrTypeDelegateSet {
inner: Box::new(inner.clone()),
})),

_ => return Ok(None),
}))
}
Expand Down
1 change: 0 additions & 1 deletion frb_codegen/src/library/codegen/parser/type_parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ pub(crate) mod structure;
pub(crate) mod tuple;
pub(crate) mod ty;
pub(crate) mod unencodable;
pub(crate) mod vec;

use crate::codegen::ir::namespace::Namespace;
use crate::codegen::ir::pack::{IrEnumPool, IrStructPool};
Expand Down
Loading

0 comments on commit 2e198ec

Please sign in to comment.