Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for duration primitive type in code generation #33

Merged
merged 8 commits into from
May 24, 2024
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
22 changes: 22 additions & 0 deletions fixtures/duration_type_test/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[package]
name = "duration_type_test"
version = "0.1.0"
edition = "2021"
publish = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html


[lib]
name = "duration_type_test"
crate-type = ["lib", "cdylib"]

[dependencies]
uniffi = { workspace = true }

[build-dependencies]
uniffi-dart = { path = "../../", features = ["build"] }

[dev-dependencies]
uniffi-dart = { path = "../../", features = ["bindgen-tests"] }
uniffi = { workspace = true, features = ["bindgen-tests"] }
anyhow = "1"
3 changes: 3 additions & 0 deletions fixtures/duration_type_test/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
uniffi_dart::generate_scaffolding("./src/api.udl".into()).unwrap();
}
1 change: 1 addition & 0 deletions fixtures/duration_type_test/src/api.udl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
namespace duration_type_test { };
19 changes: 19 additions & 0 deletions fixtures/duration_type_test/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use core::time::Duration;
use uniffi;

#[uniffi::export]
pub fn make_duration(seconds: u64, nanos: u32) -> Duration {
Duration::new(seconds, nanos)
}

#[uniffi::export]
pub fn get_seconds(duration: Duration) -> u64 {
duration.as_secs()
}

#[uniffi::export]
pub fn get_nanos(duration: Duration) -> u32 {
duration.subsec_nanos()
}

uniffi::include_scaffolding!("api");
35 changes: 35 additions & 0 deletions fixtures/duration_type_test/test/duration_type_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import 'package:test/test.dart';
import '../duration_type_test.dart';

void main() {
final api = Api.load();
test('rust return value seconds check', () {
final duration = api.makeDuration(5, 0);

expect(duration.inSeconds, 5);
expect(api.getSeconds(duration), 5);
expect(api.getNanos(duration), 0);
});

test('seconds data check from dart', () {
final duration = Duration(seconds: 10);
expect(api.getSeconds(duration), 10);
expect(api.getNanos(duration), 0);
});

test('check nanos/micros', () {
final duration = api.makeDuration(0, 3000);
expect(duration.inSeconds, 0);
expect(duration.inMicroseconds, 3);
expect(api.getSeconds(duration), 0);
expect(api.getNanos(duration), 3000);
});

test('check large values', () {
final duration = api.makeDuration(123456789, 3000000);
expect(duration.inSeconds, 123456789);
expect(duration.inMicroseconds, 123456789003000);
expect(api.getSeconds(duration), 123456789);
expect(api.getNanos(duration), 3000000);
});
}
6 changes: 6 additions & 0 deletions fixtures/duration_type_test/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use anyhow::Result;

#[test]
fn duration_type_test() -> Result<()> {
uniffi_dart::testing::run_test("duration_type_test", "src/api.udl", None)
}
3 changes: 3 additions & 0 deletions src/gen/oracle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ impl DartCodeOracle {
| Type::Float32
| Type::Float64 => inner,
Type::Boolean
| Type::Duration
| Type::String
| Type::Object { .. }
| Type::Enum { .. }
Expand Down Expand Up @@ -237,6 +238,7 @@ impl DartCodeOracle {
| Type::Float32
| Type::Float64 => inner,
Type::Boolean
| Type::Duration
| Type::String
| Type::Object { .. }
| Type::Enum { .. }
Expand Down Expand Up @@ -336,6 +338,7 @@ impl<T: AsType> AsCodeType for T {
Type::Float64 => Box::new(primitives::Float64CodeType),
Type::Boolean => Box::new(primitives::BooleanCodeType),
Type::String => Box::new(primitives::StringCodeType),
Type::Duration => Box::new(primitives::DurationCodeType),
Type::Object { name, .. } => Box::new(objects::ObjectCodeType::new(name)),
Type::Optional { inner_type } => Box::new(compounds::OptionalCodeType::new(
self.as_type(),
Expand Down
7 changes: 5 additions & 2 deletions src/gen/primitives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ use uniffi_bindgen::interface::{Radix, Type};
#[macro_use]
mod macros;
mod boolean;
mod duration;
mod string;
pub use boolean::BooleanCodeType;
pub use duration::DurationCodeType;
pub use string::StringCodeType;

fn render_literal(literal: &Literal) -> String {
Expand All @@ -22,7 +24,8 @@ fn render_literal(literal: &Literal) -> String {
| Type::UInt32
| Type::UInt64
| Type::Float32
| Type::Float64 => num_str,
| Type::Float64
| Type::Duration => num_str,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

neither that this is actually needed.

_ => panic!("Unexpected literal: {} is not a number", num_str),
}
}
Expand All @@ -47,7 +50,6 @@ fn render_literal(literal: &Literal) -> String {
},
),
Literal::Float(string, type_) => typed_number(type_, string.clone()),

_ => unreachable!("Literal"),
}
}
Expand Down Expand Up @@ -143,6 +145,7 @@ pub fn generate_wrapper_lowerers() -> dart::Tokens {
return res;
}


Uint8List lowerSequence<T, V>(Api api, List<T> input, Uint8List Function(Api, V) lowerer, int element_byte_size) {
int capacity = input.length * element_byte_size;
Uint8List items = Uint8List(capacity + 4); // Four bytes for the length
Expand Down
48 changes: 48 additions & 0 deletions src/gen/primitives/duration.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use crate::gen::{
quote,
render::{Renderable, TypeHelperRenderer},
};

use super::paste;
use genco::lang::dart;

impl_code_type_for_primitive!(DurationCodeType, "duration", "Duration");

impl Renderable for DurationCodeType {
fn render_type_helper(&self, _type_helper: &dyn TypeHelperRenderer) -> dart::Tokens {
quote! {
class FfiConverterDuration {
static Duration lift(Api api, RustBuffer buf) {
return FfiConverterDuration.read(api, buf.asUint8List()).value;
}

static RustBuffer lower(Api api, Duration value) {
final buf = Uint8List(12);
FfiConverterDuration.write(api, value, buf);
return toRustBuffer(api, buf);
}

static LiftRetVal<Duration> read(Api api, Uint8List buf) {
final bytes = buf.buffer.asByteData(buf.offsetInBytes, 12);
final seconds = bytes.getUint64(0);
final micros = (bytes.getUint32(8) ~/ 1000);
return LiftRetVal(Duration(seconds: seconds, microseconds: micros), 12);
}

static int allocationSize([Duration value = const Duration()]) {
return 12;
}

static int write(Api api, Duration value, Uint8List buf) {
final bytes = buf.buffer.asByteData(buf.offsetInBytes, 12);
bytes.setUint64(0, value.inSeconds);
final ms = (value.inMicroseconds - (value.inSeconds * 1000000)) * 1000;
if (ms > 0) {
bytes.setUint32(8, ms.toInt());
}
return 12;
}
}
}
}
}
4 changes: 3 additions & 1 deletion src/gen/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ pub trait Renderable {
Type::String => quote!(String),
Type::Object { name, .. } => quote!($name),
Type::Boolean => quote!(bool),
Type::Duration => quote!(Duration),
Type::Optional { inner_type } => quote!($(&self.render_type(inner_type, type_helper))?),
Type::Sequence { inner_type } => {
quote!(List<$(&self.render_type(inner_type, type_helper))>)
Expand Down Expand Up @@ -109,6 +110,7 @@ impl<T: AsType> AsRenderable for T {
Type::Float64 => Box::new(primitives::Float64CodeType),
Type::Boolean => Box::new(primitives::BooleanCodeType),
Type::String => Box::new(primitives::StringCodeType),
Type::Duration => Box::new(primitives::DurationCodeType),
Type::Object { name, .. } => Box::new(objects::ObjectCodeType::new(name)),
Type::Optional { inner_type, .. } => Box::new(compounds::OptionalCodeType::new(
self.as_type(),
Expand All @@ -122,10 +124,10 @@ impl<T: AsType> AsRenderable for T {
Type::Record { name, module_path } => {
Box::new(records::RecordCodeType::new(name, module_path))
}

_ => todo!("Renderable for Type::{:?}", self.as_type()), // Type::Bytes => Box::new(primitives::BytesCodeType),

// Type::Timestamp => Box::new(miscellany::TimestampCodeType),
// Type::Duration => Box::new(miscellany::DurationCodeType),

// Type::Object { name, .. } => Box::new(object::ObjectCodeType::new(name)),
// Type::Record(id) => Box::new(record::RecordCodeType::new(id)),
Expand Down
1 change: 1 addition & 0 deletions src/gen/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ pub fn generate_type(ty: &Type) -> dart::Tokens {
| Type::Int64
| Type::UInt16
| Type::Int32
| Type::Duration
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure this is needed at all....

| Type::UInt64 => quote!(int),
Type::Float32 | Type::Float64 => quote!(double),
Type::String => quote!(String),
Expand Down
Loading