Skip to content

Commit

Permalink
wip: parse futures
Browse files Browse the repository at this point in the history
  • Loading branch information
vhdirk committed Jul 5, 2024
1 parent 38188f0 commit 5ae4e1f
Show file tree
Hide file tree
Showing 47 changed files with 2,426 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,6 @@ impl<'a> ApiDartGeneratorClassTrait for OptionalApiDartGenerator<'a> {}
impl<'a> ApiDartGeneratorClassTrait for PrimitiveApiDartGenerator<'a> {}
impl<'a> ApiDartGeneratorClassTrait for PrimitiveListApiDartGenerator<'a> {}
impl<'a> ApiDartGeneratorClassTrait for RecordApiDartGenerator<'a> {}
impl<'a> ApiDartGeneratorClassTrait for FutureApiDartGenerator<'a> {}
impl<'a> ApiDartGeneratorClassTrait for PinApiDartGenerator<'a> {}
impl<'a> ApiDartGeneratorClassTrait for RustAutoOpaqueImplicitApiDartGenerator<'a> {}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,20 @@ impl<'a> ApiDartGeneratorInfoTrait for BoxedApiDartGenerator<'a> {
}
}

impl<'a> ApiDartGeneratorInfoTrait for FutureApiDartGenerator<'a> {
fn dart_api_type(&self) -> String {
let inner = ApiDartGenerator::new(self.mir.output.clone(), self.context);
inner.dart_api_type()
}
}

impl<'a> ApiDartGeneratorInfoTrait for PinApiDartGenerator<'a> {
fn dart_api_type(&self) -> String {
let inner = ApiDartGenerator::new(self.mir.inner.clone(), self.context);
inner.dart_api_type()
}
}

impl<'a> ApiDartGeneratorInfoTrait for DartFnApiDartGenerator<'a> {
fn dart_api_type(&self) -> String {
format!(
Expand Down
24 changes: 24 additions & 0 deletions frb_codegen/src/library/codegen/generator/codec/sse/ty/future.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use crate::codegen::generator::codec::sse::ty::delegate::simple_delegate_encode;
use crate::codegen::generator::codec::sse::ty::*;

impl<'a> CodecSseTyTrait for FutureCodecSseTy<'a> {
fn generate_encode(&self, lang: &Lang) -> Option<String> {
self.should_generate(lang).then(|| {
simple_delegate_encode(
lang,
&self.mir.get_delegate(),
&format!("encode_{}(self)", self.mir.safe_ident()),
)
})
}

fn generate_decode(&self, _lang: &Lang) -> Option<String> {
None
}
}

impl<'a> FutureCodecSseTy<'a> {
fn should_generate(&self, lang: &Lang) -> bool {
!matches!(lang, Lang::RustLang(_))
}
}
2 changes: 2 additions & 0 deletions frb_codegen/src/library/codegen/generator/codec/sse/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ mod optional;
mod primitive;
mod primitive_list;
mod record;
mod future;
pub(crate) mod rust_auto_opaque_implicit;
pub(crate) mod rust_opaque;
mod structure;
mod trait_def;
mod pin;

use crate::codegen::generator::api_dart::internal_config::GeneratorApiDartInternalConfig;
use crate::codegen::generator::api_dart::spec_generator::base::ApiDartGeneratorContext;
Expand Down
24 changes: 24 additions & 0 deletions frb_codegen/src/library/codegen/generator/codec/sse/ty/pin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use crate::codegen::generator::codec::sse::ty::delegate::simple_delegate_encode;
use crate::codegen::generator::codec::sse::ty::*;

impl<'a> CodecSseTyTrait for PinCodecSseTy<'a> {
fn generate_encode(&self, lang: &Lang) -> Option<String> {
self.should_generate(lang).then(|| {
simple_delegate_encode(
lang,
&self.mir.get_delegate(),
&format!("encode_{}(self)", self.mir.safe_ident()),
)
})
}

fn generate_decode(&self, _lang: &Lang) -> Option<String> {
None
}
}

impl<'a> PinCodecSseTy<'a> {
fn should_generate(&self, lang: &Lang) -> bool {
!matches!(lang, Lang::RustLang(_))
}
}
2 changes: 2 additions & 0 deletions frb_codegen/src/library/codegen/generator/misc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ pub fn is_js_value(ty: &MirType) -> bool {
| MirType::Delegate(MirTypeDelegate::RustAutoOpaqueExplicit(_))
| MirType::DartOpaque(_)
| MirType::DartFn(_)
| MirType::Future(_)
| MirType::Pin(_)
| MirType::Record(_) => true,
MirType::Boxed(MirTypeBoxed { inner, .. }) => is_js_value(inner),
MirType::Delegate(inner) => is_js_value(&inner.get_delegate()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ macro_rules! codegen_generator_structs {
RustOpaque,
StructRef,
TraitDef,
Future,
Pin,
);
);
(@private $(#[$attribute:meta])* $generator_name:ident ; $($name:ident),*,) => (
Expand All @@ -36,12 +38,14 @@ macro_rules! codegen_generator_structs {
use $crate::codegen::ir::mir::ty::general_list::MirTypeGeneralList;
use $crate::codegen::ir::mir::ty::optional::MirTypeOptional;
use $crate::codegen::ir::mir::ty::primitive::MirTypePrimitive;
use $crate::codegen::ir::mir::ty::future::MirTypeFuture;
use $crate::codegen::ir::mir::ty::primitive_list::MirTypePrimitiveList;
use $crate::codegen::ir::mir::ty::record::MirTypeRecord;
use $crate::codegen::ir::mir::ty::rust_auto_opaque_implicit::MirTypeRustAutoOpaqueImplicit;
use $crate::codegen::ir::mir::ty::rust_opaque::MirTypeRustOpaque;
use $crate::codegen::ir::mir::ty::structure::MirTypeStructRef;
use $crate::codegen::ir::mir::ty::trait_def::MirTypeTraitDef;
use $crate::codegen::ir::mir::ty::pin::MirTypePin;
use $crate::codegen::ir::mir::ty::MirType;
// cargo fix wrongly removes this import
#[allow(unused_imports)]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
use crate::codegen::generator::acc::Acc;
use crate::codegen::generator::misc::is_js_value;
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::primitive::dart_native_type_of_primitive;
use crate::codegen::generator::wire::dart::spec_generator::codec::cst::encoder::ty::WireDartCodecCstGeneratorEncoderTrait;
use crate::codegen::ir::mir::ty::delegate::MirTypeDelegate;
use crate::codegen::ir::mir::ty::MirType::StructRef;
use crate::codegen::ir::mir::ty::{MirType, MirTypeTrait};

impl<'a> WireDartCodecCstGeneratorEncoderTrait for FutureWireDartCodecCstGenerator<'a> {
fn generate_encode_func_body(&self) -> Acc<Option<String>> {
let mir_safe_ident = self.mir.safe_ident();
let inner_safe_ident = self.mir.output.safe_ident();
let empty_struct = is_empty_struct(self);

Acc {
io: Some(
if self.mir.output.is_primitive()
|| matches!(
*self.mir.output,
MirType::RustOpaque(_)
| MirType::RustAutoOpaqueImplicit(_)
| MirType::Delegate(MirTypeDelegate::RustAutoOpaqueExplicit(_))
| MirType::DartOpaque(_)
)
{
format!(
"return wire.cst_new_{mir_safe_ident}(cst_encode_{inner_safe_ident}(raw));"
)
} else if self.mir.output.is_array() {
format!("return cst_encode_{inner_safe_ident}(raw);")
} else {
format!(
"final ptr = wire.cst_new_{mir_safe_ident}();
{}
return ptr;",
if empty_struct {
"".to_owned()
} else {
format!("cst_api_fill_to_wire_{inner_safe_ident}(raw, ptr.ref);")
}
)
},
),
web: Some(format!("return cst_encode_{inner_safe_ident}(raw);")),
..Default::default()
}
}

fn generate_encode_api_fill_to_wire_body(&self) -> Option<String> {
let inner_safe_ident = self.mir.output.safe_ident();

if self.mir.output.is_array() {
Some(format!("wireObj = cst_encode_{inner_safe_ident}(apiObj);"))
} else if !self.mir.output.is_primitive()
&& !matches!(
*self.mir.output,
MirType::RustOpaque(_)
| MirType::RustAutoOpaqueImplicit(_)
| MirType::Delegate(MirTypeDelegate::RustAutoOpaqueExplicit(_))
| MirType::DartOpaque(_)
)
&& !is_empty_struct(self)
{
Some(format!(
"cst_api_fill_to_wire_{inner_safe_ident}(apiObj, wireObj.ref);"
))
} else {
None
}
}

fn dart_wire_type(&self, target: Target) -> String {
match target {
Target::Web => {
if is_js_value(&self.mir.output)
|| self.mir.output.is_array()
|| self.mir.output.is_primitive()
{
WireDartCodecCstGenerator::new(self.mir.output.clone(), self.context)
.dart_wire_type(target)
} else {
// Quick hack to remove seemingly dead code without causing any trouble ;)

// frb-coverage:ignore-start
unreachable!("Codecov says this branch is never used. If you see this message, please create an issue and let's re-enable the logic here.")
// frb-coverage:ignore-end

// format!(
// "int /* *{} */",
// WireRustCodecCstGenerator::new(
// self.mir.output.clone(),
// self.context.as_wire_rust_context()
// )
// .rust_wire_type(target)
// )
}
}
Target::Io => {
if self.mir.output.is_array() {
return WireDartCodecCstGenerator::new(self.mir.output.clone(), self.context)
.dart_wire_type(Target::Io);
}
let wire_type = self
.mir
.output
.as_primitive()
.map(|prim| dart_native_type_of_primitive(prim).to_owned())
.unwrap_or_else(|| {
WireDartCodecCstGenerator::new(self.mir.output.clone(), self.context)
.dart_wire_type(target)
});
format!("ffi.Pointer<{wire_type}>")
}
}
}
}

// the function signature is not covered while the whole body is covered - looks like a bug in coverage tool
// frb-coverage:ignore-start
fn is_empty_struct(ty: &FutureWireDartCodecCstGenerator) -> bool {
// frb-coverage:ignore-end
if let StructRef(ref s) = ty.mir.output.as_ref() {
s.get(ty.context.mir_pack).fields.is_empty()
} else {
false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ mod rust_auto_opaque_implicit;
mod rust_opaque;
mod structure;
mod trait_def;
mod future;
mod pin;

use crate::codegen::generator::acc::Acc;
use crate::codegen::generator::misc::target::Target;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
use crate::codegen::generator::acc::Acc;
use crate::codegen::generator::misc::is_js_value;
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::primitive::dart_native_type_of_primitive;
use crate::codegen::generator::wire::dart::spec_generator::codec::cst::encoder::ty::WireDartCodecCstGeneratorEncoderTrait;
use crate::codegen::ir::mir::ty::delegate::MirTypeDelegate;
use crate::codegen::ir::mir::ty::MirType::StructRef;
use crate::codegen::ir::mir::ty::{MirType, MirTypeTrait};

impl<'a> WireDartCodecCstGeneratorEncoderTrait for PinWireDartCodecCstGenerator<'a> {
fn generate_encode_func_body(&self) -> Acc<Option<String>> {
let mir_safe_ident = self.mir.safe_ident();
let inner_safe_ident = self.mir.inner.safe_ident();
let empty_struct = is_empty_struct(self);

Acc {
io: Some(
if self.mir.inner.is_primitive()
|| matches!(
*self.mir.inner,
MirType::RustOpaque(_)
| MirType::RustAutoOpaqueImplicit(_)
| MirType::Delegate(MirTypeDelegate::RustAutoOpaqueExplicit(_))
| MirType::DartOpaque(_)
)
{
format!(
"return wire.cst_new_{mir_safe_ident}(cst_encode_{inner_safe_ident}(raw));"
)
} else if self.mir.inner.is_array() {
format!("return cst_encode_{inner_safe_ident}(raw);")
} else {
format!(
"final ptr = wire.cst_new_{mir_safe_ident}();
{}
return ptr;",
if empty_struct {
"".to_owned()
} else {
format!("cst_api_fill_to_wire_{inner_safe_ident}(raw, ptr.ref);")
}
)
},
),
web: Some(format!("return cst_encode_{inner_safe_ident}(raw);")),
..Default::default()
}
}

fn generate_encode_api_fill_to_wire_body(&self) -> Option<String> {
let inner_safe_ident = self.mir.inner.safe_ident();

if self.mir.inner.is_array() {
Some(format!("wireObj = cst_encode_{inner_safe_ident}(apiObj);"))
} else if !self.mir.inner.is_primitive()
&& !matches!(
*self.mir.inner,
MirType::RustOpaque(_)
| MirType::RustAutoOpaqueImplicit(_)
| MirType::Delegate(MirTypeDelegate::RustAutoOpaqueExplicit(_))
| MirType::DartOpaque(_)
)
&& !is_empty_struct(self)
{
Some(format!(
"cst_api_fill_to_wire_{inner_safe_ident}(apiObj, wireObj.ref);"
))
} else {
None
}
}

fn dart_wire_type(&self, target: Target) -> String {
match target {
Target::Web => {
if is_js_value(&self.mir.inner)
|| self.mir.inner.is_array()
|| self.mir.inner.is_primitive()
{
WireDartCodecCstGenerator::new(self.mir.inner.clone(), self.context)
.dart_wire_type(target)
} else {
// Quick hack to remove seemingly dead code without causing any trouble ;)

// frb-coverage:ignore-start
unreachable!("Codecov says this branch is never used. If you see this message, please create an issue and let's re-enable the logic here.")
// frb-coverage:ignore-end

// format!(
// "int /* *{} */",
// WireRustCodecCstGenerator::new(
// self.mir.inner.clone(),
// self.context.as_wire_rust_context()
// )
// .rust_wire_type(target)
// )
}
}
Target::Io => {
if self.mir.inner.is_array() {
return WireDartCodecCstGenerator::new(self.mir.inner.clone(), self.context)
.dart_wire_type(Target::Io);
}
let wire_type = self
.mir
.inner
.as_primitive()
.map(|prim| dart_native_type_of_primitive(prim).to_owned())
.unwrap_or_else(|| {
WireDartCodecCstGenerator::new(self.mir.inner.clone(), self.context)
.dart_wire_type(target)
});
format!("ffi.Pointer<{wire_type}>")
}
}
}
}

// the function signature is not covered while the whole body is covered - looks like a bug in coverage tool
// frb-coverage:ignore-start
fn is_empty_struct(ty: &PinWireDartCodecCstGenerator) -> bool {
// frb-coverage:ignore-end
if let StructRef(ref s) = ty.mir.inner.as_ref() {
s.get(ty.context.mir_pack).fields.is_empty()
} else {
false
}
}
Loading

0 comments on commit 5ae4e1f

Please sign in to comment.