Skip to content

Commit f278e0f

Browse files
committed
feat: Refactored int primitives with BigInt support and bounds checking
1 parent 050fda4 commit f278e0f

File tree

5 files changed

+66
-207
lines changed

5 files changed

+66
-207
lines changed

fixtures/duration_type_test/test/duration_type_test.dart

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,32 @@ import '../duration_type_test.dart';
33

44
void main() {
55
test('rust return value seconds check', () {
6-
final duration = makeDuration(5, 0);
6+
final duration = makeDuration(BigInt.from(5), 0);
77

88
expect(duration.inSeconds, 5);
9-
expect(getSeconds(duration), 5);
9+
expect(getSeconds(duration), BigInt.from(5));
1010
expect(getNanos(duration), 0);
1111
});
1212

1313
test('seconds data check from dart', () {
1414
final duration = Duration(seconds: 10);
15-
expect(getSeconds(duration), 10);
15+
expect(getSeconds(duration), BigInt.from(10));
1616
expect(getNanos(duration), 0);
1717
});
1818

1919
test('check nanos/micros', () {
20-
final duration = makeDuration(0, 3000);
20+
final duration = makeDuration(BigInt.zero, 3000);
2121
expect(duration.inSeconds, 0);
2222
expect(duration.inMicroseconds, 3);
23-
expect(getSeconds(duration), 0);
23+
expect(getSeconds(duration), BigInt.zero);
2424
expect(getNanos(duration), 3000);
2525
});
2626

2727
test('check large values', () {
28-
final duration = makeDuration(123456789, 3000000);
28+
final duration = makeDuration(BigInt.from(123456789), 3000000);
2929
expect(duration.inSeconds, 123456789);
3030
expect(duration.inMicroseconds, 123456789003000);
31-
expect(getSeconds(duration), 123456789);
31+
expect(getSeconds(duration), BigInt.from(123456789));
3232
expect(getNanos(duration), 3000000);
3333
});
3434
}

src/gen/compounds.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ impl CodeType for MapCodeType {
222222
fn canonical_name(&self) -> String {
223223
let key = DartCodeOracle::find(self.key()).canonical_name();
224224
let val = DartCodeOracle::find(self.value()).canonical_name();
225-
format!("Map{}To{}", key, val)
225+
format!("Map{key}To{val}")
226226
}
227227
}
228228

src/gen/primitives/macros.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ macro_rules! impl_renderable_for_primitive {
6868
}
6969
}
7070
};
71+
// Variant without bounds checking (for floats, etc.)
7172
($T:ty, $class_name:literal, $canonical_name:literal, $allocation_size:literal) => {
7273
impl Renderable for $T {
7374
fn render_type_helper(&self, _type_helper: &dyn TypeHelperRenderer) -> dart::Tokens {
@@ -111,4 +112,45 @@ macro_rules! impl_renderable_for_primitive {
111112
}
112113
}
113114
};
115+
// Variant with bounds checking (for integers)
116+
($T:ty, $class_name:literal, $canonical_name:literal, $allocation_size:literal, $min_value:literal, $max_value:literal, $type_name:literal) => {
117+
impl Renderable for $T {
118+
fn render_type_helper(&self, _type_helper: &dyn TypeHelperRenderer) -> dart::Tokens {
119+
let cl_name = &self.ffi_converter_name();
120+
let type_signature = &self.type_label();
121+
let conversion_name = &$canonical_name
122+
.replace("UInt", "Uint")
123+
.replace("Double", "Float");
124+
125+
// Pre-compute the error message to avoid string interpolation conflicts
126+
let error_message = format!("\"Value out of range for {}: \" + value.toString()", $type_name);
127+
128+
quote! {
129+
class $cl_name {
130+
static $type_signature lift($type_signature value) => value;
131+
132+
static LiftRetVal<$type_signature> read(Uint8List buf) {
133+
return LiftRetVal(buf.buffer.asByteData(buf.offsetInBytes).get$conversion_name(0), $allocation_size);
134+
}
135+
136+
static $type_signature lower($type_signature value) {
137+
if (value < $min_value || value > $max_value) {
138+
throw ArgumentError($error_message);
139+
}
140+
return value;
141+
}
142+
143+
static int allocationSize([$type_signature value = 0]) {
144+
return $allocation_size;
145+
}
146+
147+
static int write($type_signature value, Uint8List buf) {
148+
buf.buffer.asByteData(buf.offsetInBytes).set$conversion_name(0, lower(value));
149+
return $allocation_size;
150+
}
151+
}
152+
}
153+
}
154+
}
155+
};
114156
}

src/gen/primitives/mod.rs

Lines changed: 15 additions & 198 deletions
Original file line numberDiff line numberDiff line change
@@ -157,201 +157,18 @@ impl Renderable for UInt64CodeType {
157157
}
158158
}
159159

160-
// Custom implementations for smaller integer types with bounds checking
161-
impl Renderable for Int8CodeType {
162-
fn render_type_helper(&self, _type_helper: &dyn TypeHelperRenderer) -> dart::Tokens {
163-
let cl_name = &self.ffi_converter_name();
164-
let type_signature = &self.type_label();
165-
166-
quote! {
167-
class $cl_name {
168-
static $type_signature lift($type_signature value) => value;
169-
170-
static LiftRetVal<$type_signature> read(Uint8List buf) {
171-
return LiftRetVal(buf.buffer.asByteData(buf.offsetInBytes).getInt8(0), 1);
172-
}
173-
174-
static $type_signature lower($type_signature value) {
175-
if (value < -128 || value > 127) {
176-
throw ArgumentError("Value out of range for i8: " + value.toString());
177-
}
178-
return value;
179-
}
180-
181-
static int allocationSize([$type_signature value = 0]) {
182-
return 1;
183-
}
184-
185-
static int write($type_signature value, Uint8List buf) {
186-
buf.buffer.asByteData(buf.offsetInBytes).setInt8(0, lower(value));
187-
return 1;
188-
}
189-
}
190-
}
191-
}
192-
}
193-
194-
impl Renderable for Int16CodeType {
195-
fn render_type_helper(&self, _type_helper: &dyn TypeHelperRenderer) -> dart::Tokens {
196-
let cl_name = &self.ffi_converter_name();
197-
let type_signature = &self.type_label();
198-
199-
quote! {
200-
class $cl_name {
201-
static $type_signature lift($type_signature value) => value;
202-
203-
static LiftRetVal<$type_signature> read(Uint8List buf) {
204-
return LiftRetVal(buf.buffer.asByteData(buf.offsetInBytes).getInt16(0), 2);
205-
}
206-
207-
static $type_signature lower($type_signature value) {
208-
if (value < -32768 || value > 32767) {
209-
throw ArgumentError("Value out of range for i16: " + value.toString());
210-
}
211-
return value;
212-
}
213-
214-
static int allocationSize([$type_signature value = 0]) {
215-
return 2;
216-
}
217-
218-
static int write($type_signature value, Uint8List buf) {
219-
buf.buffer.asByteData(buf.offsetInBytes).setInt16(0, lower(value));
220-
return 2;
221-
}
222-
}
223-
}
224-
}
225-
}
226-
227-
impl Renderable for Int32CodeType {
228-
fn render_type_helper(&self, _type_helper: &dyn TypeHelperRenderer) -> dart::Tokens {
229-
let cl_name = &self.ffi_converter_name();
230-
let type_signature = &self.type_label();
231-
232-
quote! {
233-
class $cl_name {
234-
static $type_signature lift($type_signature value) => value;
235-
236-
static LiftRetVal<$type_signature> read(Uint8List buf) {
237-
return LiftRetVal(buf.buffer.asByteData(buf.offsetInBytes).getInt32(0), 4);
238-
}
239-
240-
static $type_signature lower($type_signature value) {
241-
if (value < -2147483648 || value > 2147483647) {
242-
throw ArgumentError("Value out of range for i32: " + value.toString());
243-
}
244-
return value;
245-
}
246-
247-
static int allocationSize([$type_signature value = 0]) {
248-
return 4;
249-
}
250-
251-
static int write($type_signature value, Uint8List buf) {
252-
buf.buffer.asByteData(buf.offsetInBytes).setInt32(0, lower(value));
253-
return 4;
254-
}
255-
}
256-
}
257-
}
258-
}
259-
260-
impl Renderable for UInt8CodeType {
261-
fn render_type_helper(&self, _type_helper: &dyn TypeHelperRenderer) -> dart::Tokens {
262-
let cl_name = &self.ffi_converter_name();
263-
let type_signature = &self.type_label();
264-
265-
quote! {
266-
class $cl_name {
267-
static $type_signature lift($type_signature value) => value;
268-
269-
static LiftRetVal<$type_signature> read(Uint8List buf) {
270-
return LiftRetVal(buf.buffer.asByteData(buf.offsetInBytes).getUint8(0), 1);
271-
}
272-
273-
static $type_signature lower($type_signature value) {
274-
if (value < 0 || value > 255) {
275-
throw ArgumentError("Value out of range for u8: " + value.toString());
276-
}
277-
return value;
278-
}
279-
280-
static int allocationSize([$type_signature value = 0]) {
281-
return 1;
282-
}
283-
284-
static int write($type_signature value, Uint8List buf) {
285-
buf.buffer.asByteData(buf.offsetInBytes).setUint8(0, lower(value));
286-
return 1;
287-
}
288-
}
289-
}
290-
}
291-
}
292-
293-
impl Renderable for UInt16CodeType {
294-
fn render_type_helper(&self, _type_helper: &dyn TypeHelperRenderer) -> dart::Tokens {
295-
let cl_name = &self.ffi_converter_name();
296-
let type_signature = &self.type_label();
297-
298-
quote! {
299-
class $cl_name {
300-
static $type_signature lift($type_signature value) => value;
301-
302-
static LiftRetVal<$type_signature> read(Uint8List buf) {
303-
return LiftRetVal(buf.buffer.asByteData(buf.offsetInBytes).getUint16(0), 2);
304-
}
305-
306-
static $type_signature lower($type_signature value) {
307-
if (value < 0 || value > 65535) {
308-
throw ArgumentError("Value out of range for u16: " + value.toString());
309-
}
310-
return value;
311-
}
312-
313-
static int allocationSize([$type_signature value = 0]) {
314-
return 2;
315-
}
316-
317-
static int write($type_signature value, Uint8List buf) {
318-
buf.buffer.asByteData(buf.offsetInBytes).setUint16(0, lower(value));
319-
return 2;
320-
}
321-
}
322-
}
323-
}
324-
}
325-
326-
impl Renderable for UInt32CodeType {
327-
fn render_type_helper(&self, _type_helper: &dyn TypeHelperRenderer) -> dart::Tokens {
328-
let cl_name = &self.ffi_converter_name();
329-
let type_signature = &self.type_label();
330-
331-
quote! {
332-
class $cl_name {
333-
static $type_signature lift($type_signature value) => value;
334-
335-
static LiftRetVal<$type_signature> read(Uint8List buf) {
336-
return LiftRetVal(buf.buffer.asByteData(buf.offsetInBytes).getUint32(0), 4);
337-
}
338-
339-
static $type_signature lower($type_signature value) {
340-
if (value < 0 || value > 4294967295) {
341-
throw ArgumentError("Value out of range for u32: " + value.toString());
342-
}
343-
return value;
344-
}
345-
346-
static int allocationSize([$type_signature value = 0]) {
347-
return 4;
348-
}
349-
350-
static int write($type_signature value, Uint8List buf) {
351-
buf.buffer.asByteData(buf.offsetInBytes).setUint32(0, lower(value));
352-
return 4;
353-
}
354-
}
355-
}
356-
}
357-
}
160+
// Use the unified macro with bounds checking for integer types
161+
impl_renderable_for_primitive!(Int8CodeType, "int", "Int8", 1, -128, 127, "i8");
162+
impl_renderable_for_primitive!(Int16CodeType, "int", "Int16", 2, -32768, 32767, "i16");
163+
impl_renderable_for_primitive!(
164+
Int32CodeType,
165+
"int",
166+
"Int32",
167+
4,
168+
-2147483648,
169+
2147483647,
170+
"i32"
171+
);
172+
impl_renderable_for_primitive!(UInt8CodeType, "int", "UInt8", 1, 0, 255, "u8");
173+
impl_renderable_for_primitive!(UInt16CodeType, "int", "UInt16", 2, 0, 65535, "u16");
174+
impl_renderable_for_primitive!(UInt32CodeType, "int", "UInt32", 4, 0, 4294967295, "u32");

src/gen/render/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::{callback_interface, compounds, custom, enums, primitives, records};
22
use super::{objects, oracle::AsCodeType};
3-
use genco::{lang::dart, quote};
3+
use genco::lang::dart;
44
use uniffi_bindgen::interface::{AsType, Enum, Object, Record, Type};
55
use uniffi_bindgen::ComponentInterface;
66

0 commit comments

Comments
 (0)