diff --git a/example/dart/lib/ICU4XDataProvider.g.dart b/example/dart/lib/ICU4XDataProvider.g.dart index c719a51c5..86e151e64 100644 --- a/example/dart/lib/ICU4XDataProvider.g.dart +++ b/example/dart/lib/ICU4XDataProvider.g.dart @@ -8,26 +8,25 @@ part of 'lib.g.dart'; /// An ICU4X data provider, capable of loading ICU4X data keys from some source. /// /// See the [Rust documentation for `icu_provider`](https://docs.rs/icu_provider/latest/icu_provider/index.html) for more information. -class ICU4XDataProvider implements ffi.Finalizable { +final class ICU4XDataProvider implements ffi.Finalizable { final ffi.Pointer _underlying; ICU4XDataProvider._(this._underlying) { _finalizer.attach(this, _underlying.cast()); } - static final _finalizer = - ffi.NativeFinalizer(_capi('ICU4XDataProvider_destroy')); + static final _finalizer = ffi.NativeFinalizer(_capi('ICU4XDataProvider_destroy')); /// See the [Rust documentation for `get_static_provider`](https://docs.rs/icu_testdata/latest/icu_testdata/fn.get_static_provider.html) for more information. factory ICU4XDataProvider.static_() { final result = _ICU4XDataProvider_new_static(); return ICU4XDataProvider._(result); } + // ignore: non_constant_identifier_names static final _ICU4XDataProvider_new_static = - _capi Function()>>( - 'ICU4XDataProvider_new_static') - .asFunction Function()>(isLeaf: true); + _capi Function()>>('ICU4XDataProvider_new_static') + .asFunction Function()>(isLeaf: true); /// This exists as a regression test for https://github.com/rust-diplomat/diplomat/issues/155 /// @@ -41,7 +40,6 @@ class ICU4XDataProvider implements ffi.Finalizable { // ignore: non_constant_identifier_names static final _ICU4XDataProvider_returns_result = - _capi>( - 'ICU4XDataProvider_returns_result') - .asFunction<_ResultVoidVoid Function()>(isLeaf: true); + _capi>('ICU4XDataProvider_returns_result') + .asFunction<_ResultVoidVoid Function()>(isLeaf: true); } diff --git a/example/dart/lib/ICU4XFixedDecimal.g.dart b/example/dart/lib/ICU4XFixedDecimal.g.dart index 736d08bae..80eff5dd6 100644 --- a/example/dart/lib/ICU4XFixedDecimal.g.dart +++ b/example/dart/lib/ICU4XFixedDecimal.g.dart @@ -6,26 +6,25 @@ part of 'lib.g.dart'; /// See the [Rust documentation for `FixedDecimal`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html) for more information. -class ICU4XFixedDecimal implements ffi.Finalizable { +final class ICU4XFixedDecimal implements ffi.Finalizable { final ffi.Pointer _underlying; ICU4XFixedDecimal._(this._underlying) { _finalizer.attach(this, _underlying.cast()); } - static final _finalizer = - ffi.NativeFinalizer(_capi('ICU4XFixedDecimal_destroy')); + static final _finalizer = ffi.NativeFinalizer(_capi('ICU4XFixedDecimal_destroy')); /// Construct an [`ICU4XFixedDecimal`] from an integer. factory ICU4XFixedDecimal(int v) { final result = _ICU4XFixedDecimal_new(v); return ICU4XFixedDecimal._(result); } + // ignore: non_constant_identifier_names static final _ICU4XFixedDecimal_new = - _capi Function(ffi.Int32)>>( - 'ICU4XFixedDecimal_new') - .asFunction Function(int)>(isLeaf: true); + _capi Function(ffi.Int32)>>('ICU4XFixedDecimal_new') + .asFunction Function(int)>(isLeaf: true); /// Multiply the [`ICU4XFixedDecimal`] by a given power of ten. /// @@ -35,10 +34,8 @@ class ICU4XFixedDecimal implements ffi.Finalizable { } // ignore: non_constant_identifier_names - static final _ICU4XFixedDecimal_multiply_pow10 = _capi< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer, - ffi.Int16)>>('ICU4XFixedDecimal_multiply_pow10') + static final _ICU4XFixedDecimal_multiply_pow10 = + _capi, ffi.Int16)>>('ICU4XFixedDecimal_multiply_pow10') .asFunction, int)>(isLeaf: true); /// Format the [`ICU4XFixedDecimal`] as a string. @@ -49,8 +46,7 @@ class ICU4XFixedDecimal implements ffi.Finalizable { @override String toString() { final writeable = _Writeable(); - final result = - _ICU4XFixedDecimal_to_string(_underlying, writeable._underlying); + final result = _ICU4XFixedDecimal_to_string(_underlying, writeable._underlying); if (!result.isOk) { throw VoidError(); } @@ -58,11 +54,7 @@ class ICU4XFixedDecimal implements ffi.Finalizable { } // ignore: non_constant_identifier_names - static final _ICU4XFixedDecimal_to_string = _capi< - ffi.NativeFunction< - _ResultVoidVoid Function(ffi.Pointer, - ffi.Pointer)>>('ICU4XFixedDecimal_to_string') - .asFunction< - _ResultVoidVoid Function( - ffi.Pointer, ffi.Pointer)>(isLeaf: true); + static final _ICU4XFixedDecimal_to_string = + _capi, ffi.Pointer)>>('ICU4XFixedDecimal_to_string') + .asFunction<_ResultVoidVoid Function(ffi.Pointer, ffi.Pointer)>(isLeaf: true); } diff --git a/example/dart/lib/ICU4XFixedDecimalFormatter.g.dart b/example/dart/lib/ICU4XFixedDecimalFormatter.g.dart index 57d299070..5d14d84ef 100644 --- a/example/dart/lib/ICU4XFixedDecimalFormatter.g.dart +++ b/example/dart/lib/ICU4XFixedDecimalFormatter.g.dart @@ -8,61 +8,44 @@ part of 'lib.g.dart'; /// An ICU4X Fixed Decimal Format object, capable of formatting a [`ICU4XFixedDecimal`] as a string. /// /// See the [Rust documentation for `FixedDecimalFormatter`](https://docs.rs/icu/latest/icu/decimal/struct.FixedDecimalFormatter.html) for more information. -class ICU4XFixedDecimalFormatter implements ffi.Finalizable { +final class ICU4XFixedDecimalFormatter implements ffi.Finalizable { final ffi.Pointer _underlying; ICU4XFixedDecimalFormatter._(this._underlying) { _finalizer.attach(this, _underlying.cast()); } - static final _finalizer = - ffi.NativeFinalizer(_capi('ICU4XFixedDecimalFormatter_destroy')); + static final _finalizer = ffi.NativeFinalizer(_capi('ICU4XFixedDecimalFormatter_destroy')); /// Creates a new [`ICU4XFixedDecimalFormatter`] from locale data. /// /// See the [Rust documentation for `try_new`](https://docs.rs/icu/latest/icu/decimal/struct.FixedDecimalFormatter.html#method.try_new) for more information. /// /// Throws [VoidError] on failure. - factory ICU4XFixedDecimalFormatter.tryNew(ICU4XLocale locale, - ICU4XDataProvider provider, ICU4XFixedDecimalFormatterOptions options) { - final result = _ICU4XFixedDecimalFormatter_try_new( - locale._underlying, provider._underlying, options._underlying); + factory ICU4XFixedDecimalFormatter.tryNew(ICU4XLocale locale, ICU4XDataProvider provider, ICU4XFixedDecimalFormatterOptions options) { + final result = _ICU4XFixedDecimalFormatter_try_new(locale._underlying, provider._underlying, options._underlying); if (!result.isOk) { throw VoidError(); } return ICU4XFixedDecimalFormatter._(result.union.ok); } + // ignore: non_constant_identifier_names - static final _ICU4XFixedDecimalFormatter_try_new = _capi< - ffi.NativeFunction< - _ResultOpaqueVoid Function( - ffi.Pointer, - ffi.Pointer, - _ICU4XFixedDecimalFormatterOptionsFfi)>>( - 'ICU4XFixedDecimalFormatter_try_new') - .asFunction< - _ResultOpaqueVoid Function( - ffi.Pointer, - ffi.Pointer, - _ICU4XFixedDecimalFormatterOptionsFfi)>(isLeaf: true); + static final _ICU4XFixedDecimalFormatter_try_new = + _capi, ffi.Pointer, _ICU4XFixedDecimalFormatterOptionsFfi)>>('ICU4XFixedDecimalFormatter_try_new') + .asFunction<_ResultOpaqueVoid Function(ffi.Pointer, ffi.Pointer, _ICU4XFixedDecimalFormatterOptionsFfi)>(isLeaf: true); /// Formats a [`ICU4XFixedDecimal`] to a string. /// /// See the [Rust documentation for `format`](https://docs.rs/icu/latest/icu/decimal/struct.FixedDecimalFormatter.html#method.format) for more information. String formatWrite(ICU4XFixedDecimal value) { final writeable = _Writeable(); - _ICU4XFixedDecimalFormatter_format_write( - _underlying, value._underlying, writeable._underlying); + _ICU4XFixedDecimalFormatter_format_write(_underlying, value._underlying, writeable._underlying); return writeable.finalize(); } // ignore: non_constant_identifier_names - static final _ICU4XFixedDecimalFormatter_format_write = _capi< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer, - ffi.Pointer, ffi.Pointer)>>( - 'ICU4XFixedDecimalFormatter_format_write') - .asFunction< - void Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer)>(isLeaf: true); + static final _ICU4XFixedDecimalFormatter_format_write = + _capi, ffi.Pointer, ffi.Pointer)>>('ICU4XFixedDecimalFormatter_format_write') + .asFunction, ffi.Pointer, ffi.Pointer)>(isLeaf: true); } diff --git a/example/dart/lib/ICU4XFixedDecimalFormatterOptions.g.dart b/example/dart/lib/ICU4XFixedDecimalFormatterOptions.g.dart index f779b0228..7bf6d88d4 100644 --- a/example/dart/lib/ICU4XFixedDecimalFormatterOptions.g.dart +++ b/example/dart/lib/ICU4XFixedDecimalFormatterOptions.g.dart @@ -5,14 +5,14 @@ part of 'lib.g.dart'; -class _ICU4XFixedDecimalFormatterOptionsFfi extends ffi.Struct { +final class _ICU4XFixedDecimalFormatterOptionsFfi extends ffi.Struct { @ffi.Int32() external int groupingStrategy; @ffi.Bool() external bool someOtherConfig; } -class ICU4XFixedDecimalFormatterOptions { +final class ICU4XFixedDecimalFormatterOptions { final _ICU4XFixedDecimalFormatterOptionsFfi _underlying; // ignore: unused_element @@ -25,8 +25,7 @@ class ICU4XFixedDecimalFormatterOptions { return result; } - ICU4XFixedDecimalGroupingStrategy get groupingStrategy => - ICU4XFixedDecimalGroupingStrategy.values[_underlying.groupingStrategy]; + ICU4XFixedDecimalGroupingStrategy get groupingStrategy => ICU4XFixedDecimalGroupingStrategy.values[_underlying.groupingStrategy]; set groupingStrategy(ICU4XFixedDecimalGroupingStrategy groupingStrategy) { _underlying.groupingStrategy = groupingStrategy.index; } @@ -40,13 +39,11 @@ class ICU4XFixedDecimalFormatterOptions { final result = _ICU4XFixedDecimalFormatterOptions_default(); return ICU4XFixedDecimalFormatterOptions._(result); } + // ignore: non_constant_identifier_names - static final _ICU4XFixedDecimalFormatterOptions_default = _capi< - ffi.NativeFunction< - _ICU4XFixedDecimalFormatterOptionsFfi - Function()>>('ICU4XFixedDecimalFormatterOptions_default') - .asFunction<_ICU4XFixedDecimalFormatterOptionsFfi Function()>( - isLeaf: true); + static final _ICU4XFixedDecimalFormatterOptions_default = + _capi>('ICU4XFixedDecimalFormatterOptions_default') + .asFunction<_ICU4XFixedDecimalFormatterOptionsFfi Function()>(isLeaf: true); @override bool operator ==(Object other) => diff --git a/example/dart/lib/ICU4XLocale.g.dart b/example/dart/lib/ICU4XLocale.g.dart index 14883629b..5bf4eb15e 100644 --- a/example/dart/lib/ICU4XLocale.g.dart +++ b/example/dart/lib/ICU4XLocale.g.dart @@ -8,7 +8,7 @@ part of 'lib.g.dart'; /// An ICU4X Locale, capable of representing strings like `"en-US"`. /// /// See the [Rust documentation for `Locale`](https://docs.rs/icu/latest/icu/locid/struct.Locale.html) for more information. -class ICU4XLocale implements ffi.Finalizable { +final class ICU4XLocale implements ffi.Finalizable { final ffi.Pointer _underlying; ICU4XLocale._(this._underlying) { @@ -21,36 +21,27 @@ class ICU4XLocale implements ffi.Finalizable { factory ICU4XLocale(String name) { final alloc = ffi2.Arena(); final nameSlice = _SliceFfi2Utf8._fromDart(name, alloc); - final result = _ICU4XLocale_new(nameSlice._bytes, nameSlice._length); alloc.releaseAll(); return ICU4XLocale._(result); } + // ignore: non_constant_identifier_names - static final _ICU4XLocale_new = _capi< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, ffi.Size)>>('ICU4XLocale_new') - .asFunction< - ffi.Pointer Function( - ffi.Pointer, int)>(isLeaf: true); + static final _ICU4XLocale_new = + _capi Function(ffi.Pointer, ffi.Size)>>('ICU4XLocale_new') + .asFunction Function(ffi.Pointer, int)>(isLeaf: true); /// Construct an [`ICU4XLocale`] from a locale identifier represented as bytes. factory ICU4XLocale.fromBytes(Uint8List bytes) { final alloc = ffi2.Arena(); final bytesSlice = _SliceFfiUint8._fromDart(bytes, alloc); - - final result = - _ICU4XLocale_new_from_bytes(bytesSlice._bytes, bytesSlice._length); + final result = _ICU4XLocale_new_from_bytes(bytesSlice._bytes, bytesSlice._length); alloc.releaseAll(); return ICU4XLocale._(result); } + // ignore: non_constant_identifier_names - static final _ICU4XLocale_new_from_bytes = _capi< - ffi.NativeFunction< - ffi.Pointer Function(ffi.Pointer, - ffi.Size)>>('ICU4XLocale_new_from_bytes') - .asFunction< - ffi.Pointer Function( - ffi.Pointer, int)>(isLeaf: true); + static final _ICU4XLocale_new_from_bytes = + _capi Function(ffi.Pointer, ffi.Size)>>('ICU4XLocale_new_from_bytes') + .asFunction Function(ffi.Pointer, int)>(isLeaf: true); } diff --git a/example/dart/lib/lib.g.dart b/example/dart/lib/lib.g.dart index 91d7891b3..e838640d1 100644 --- a/example/dart/lib/lib.g.dart +++ b/example/dart/lib/lib.g.dart @@ -19,23 +19,25 @@ void init(String path) => _capi = ffi.DynamicLibrary.open(path).lookup; final _callocFree = Finalizer(ffi2.calloc.free); -class _ResultOpaqueVoidUnion extends ffi.Union { +final class _ResultOpaqueVoidUnion extends ffi.Union { external ffi.Pointer ok; } -class _ResultOpaqueVoid extends ffi.Struct { +final class _ResultOpaqueVoid extends ffi.Struct { external _ResultOpaqueVoidUnion union; @ffi.Bool() external bool isOk; } -class _ResultVoidVoid extends ffi.Struct { +final class _ResultVoidVoid extends ffi.Struct { + + @ffi.Bool() external bool isOk; } -class _SliceFfi2Utf8 extends ffi.Struct { +final class _SliceFfi2Utf8 extends ffi.Struct { external ffi.Pointer _bytes; @ffi.Size() @@ -51,13 +53,11 @@ class _SliceFfi2Utf8 extends ffi.Struct { slice._length = units.length; slice._bytes = allocator(slice._length).cast(); slice._bytes.cast().asTypedList(slice._length).setAll(0, units); - return slice; } // ignore: unused_element - String get _asDart => - Utf8Decoder().convert(_bytes.cast().asTypedList(_length)); + String get _asDart => Utf8Decoder().convert(_bytes.cast().asTypedList(_length)); // This is expensive @override @@ -79,7 +79,7 @@ class _SliceFfi2Utf8 extends ffi.Struct { int get hashCode => _length.hashCode; } -class _SliceFfiUint8 extends ffi.Struct { +final class _SliceFfiUint8 extends ffi.Struct { external ffi.Pointer _bytes; @ffi.Size() @@ -94,7 +94,6 @@ class _SliceFfiUint8 extends ffi.Struct { slice._length = value.length; slice._bytes = allocator(slice._length); slice._bytes.asTypedList(slice._length).setAll(0, value); - return slice; } @@ -124,34 +123,27 @@ class _SliceFfiUint8 extends ffi.Struct { /// An unspecified error value class VoidError {} -class _Writeable { +final class _Writeable { final ffi.Pointer _underlying; _Writeable() : _underlying = _create(0); static final _create = - _capi Function(ffi.Size)>>( - 'diplomat_buffer_writeable_create') - .asFunction Function(int)>(); + _capi Function(ffi.Size)>>('diplomat_buffer_writeable_create') + .asFunction Function(int)>(); String finalize() { - final string = - _getBytes(_underlying).toDartString(length: _len(_underlying)); + final string = _getBytes(_underlying).toDartString(length: _len(_underlying)); _destroy(_underlying); return string; } + static final _len = + _capi)>>('diplomat_buffer_writeable_len') + .asFunction)>(isLeaf: true); - static final _len = - _capi)>>( - 'diplomat_buffer_writeable_len') - .asFunction)>(isLeaf: true); - static final _getBytes = _capi< - ffi.NativeFunction< - ffi.Pointer Function(ffi.Pointer)>>( - 'diplomat_buffer_writeable_get_bytes') - .asFunction Function(ffi.Pointer)>( - isLeaf: true); + static final _getBytes = + _capi Function(ffi.Pointer)>>('diplomat_buffer_writeable_get_bytes') + .asFunction Function(ffi.Pointer)>(isLeaf: true); static final _destroy = - _capi)>>( - 'diplomat_buffer_writeable_destroy') - .asFunction)>(isLeaf: true); + _capi)>>('diplomat_buffer_writeable_destroy') + .asFunction)>(isLeaf: true); } diff --git a/feature_tests/dart/lib/AttrEnum.g.dart b/feature_tests/dart/lib/AttrEnum.g.dart index 245e4abf5..39b352c04 100644 --- a/feature_tests/dart/lib/AttrEnum.g.dart +++ b/feature_tests/dart/lib/AttrEnum.g.dart @@ -7,6 +7,8 @@ part of 'lib.g.dart'; enum AttrEnum { a, + b, + c; } diff --git a/feature_tests/dart/lib/AttrOpaque1.g.dart b/feature_tests/dart/lib/AttrOpaque1.g.dart index 9413ed240..5866eaee9 100644 --- a/feature_tests/dart/lib/AttrOpaque1.g.dart +++ b/feature_tests/dart/lib/AttrOpaque1.g.dart @@ -5,7 +5,7 @@ part of 'lib.g.dart'; -class AttrOpaque1 implements ffi.Finalizable { +final class AttrOpaque1 implements ffi.Finalizable { final ffi.Pointer _underlying; AttrOpaque1._(this._underlying) { @@ -20,9 +20,8 @@ class AttrOpaque1 implements ffi.Finalizable { // ignore: non_constant_identifier_names static final _AttrOpaque1_method = - _capi)>>( - 'AttrOpaque1_method') - .asFunction)>(isLeaf: true); + _capi)>>('AttrOpaque1_method') + .asFunction)>(isLeaf: true); void methodDisabledcpp() { _AttrOpaque1_method_disabledcpp(_underlying); @@ -30,7 +29,6 @@ class AttrOpaque1 implements ffi.Finalizable { // ignore: non_constant_identifier_names static final _AttrOpaque1_method_disabledcpp = - _capi)>>( - 'AttrOpaque1_method_disabledcpp') - .asFunction)>(isLeaf: true); + _capi)>>('AttrOpaque1_method_disabledcpp') + .asFunction)>(isLeaf: true); } diff --git a/feature_tests/dart/lib/AttrOpaque2.g.dart b/feature_tests/dart/lib/AttrOpaque2.g.dart index b36045bf3..61a362d85 100644 --- a/feature_tests/dart/lib/AttrOpaque2.g.dart +++ b/feature_tests/dart/lib/AttrOpaque2.g.dart @@ -5,7 +5,7 @@ part of 'lib.g.dart'; -class AttrOpaque2 implements ffi.Finalizable { +final class AttrOpaque2 implements ffi.Finalizable { final ffi.Pointer _underlying; AttrOpaque2._(this._underlying) { diff --git a/feature_tests/dart/lib/Bar.g.dart b/feature_tests/dart/lib/Bar.g.dart index ab0a9cdf4..198b44763 100644 --- a/feature_tests/dart/lib/Bar.g.dart +++ b/feature_tests/dart/lib/Bar.g.dart @@ -5,7 +5,7 @@ part of 'lib.g.dart'; -class Bar implements ffi.Finalizable { +final class Bar implements ffi.Finalizable { final ffi.Pointer _underlying; Bar._(this._underlying) { diff --git a/feature_tests/dart/lib/BorrowedFields.g.dart b/feature_tests/dart/lib/BorrowedFields.g.dart index e50b5f96c..c3928c3ba 100644 --- a/feature_tests/dart/lib/BorrowedFields.g.dart +++ b/feature_tests/dart/lib/BorrowedFields.g.dart @@ -5,12 +5,12 @@ part of 'lib.g.dart'; -class _BorrowedFieldsFfi extends ffi.Struct { +final class _BorrowedFieldsFfi extends ffi.Struct { external _SliceFfiUint16 a; external _SliceFfi2Utf8 b; } -class BorrowedFields { +final class BorrowedFields { final _BorrowedFieldsFfi _underlying; // ignore: unused_element diff --git a/feature_tests/dart/lib/BorrowedFieldsReturning.g.dart b/feature_tests/dart/lib/BorrowedFieldsReturning.g.dart index b158b04bf..e9a3b9a11 100644 --- a/feature_tests/dart/lib/BorrowedFieldsReturning.g.dart +++ b/feature_tests/dart/lib/BorrowedFieldsReturning.g.dart @@ -5,11 +5,11 @@ part of 'lib.g.dart'; -class _BorrowedFieldsReturningFfi extends ffi.Struct { +final class _BorrowedFieldsReturningFfi extends ffi.Struct { external _SliceFfiUint8 bytes; } -class BorrowedFieldsReturning { +final class BorrowedFieldsReturning { final _BorrowedFieldsReturningFfi _underlying; // ignore: unused_element diff --git a/feature_tests/dart/lib/ContiguousEnum.g.dart b/feature_tests/dart/lib/ContiguousEnum.g.dart index 385f7e966..d1aabc54c 100644 --- a/feature_tests/dart/lib/ContiguousEnum.g.dart +++ b/feature_tests/dart/lib/ContiguousEnum.g.dart @@ -7,7 +7,10 @@ part of 'lib.g.dart'; enum ContiguousEnum { c, + d, + e, + f; } diff --git a/feature_tests/dart/lib/ErrorEnum.g.dart b/feature_tests/dart/lib/ErrorEnum.g.dart index 17be3a38d..f3b0e27fb 100644 --- a/feature_tests/dart/lib/ErrorEnum.g.dart +++ b/feature_tests/dart/lib/ErrorEnum.g.dart @@ -7,5 +7,6 @@ part of 'lib.g.dart'; enum ErrorEnum { foo, + bar; } diff --git a/feature_tests/dart/lib/ErrorStruct.g.dart b/feature_tests/dart/lib/ErrorStruct.g.dart index 8fbbca964..cd02ce17d 100644 --- a/feature_tests/dart/lib/ErrorStruct.g.dart +++ b/feature_tests/dart/lib/ErrorStruct.g.dart @@ -5,14 +5,14 @@ part of 'lib.g.dart'; -class _ErrorStructFfi extends ffi.Struct { +final class _ErrorStructFfi extends ffi.Struct { @ffi.Int32() external int i; @ffi.Int32() external int j; } -class ErrorStruct { +final class ErrorStruct { final _ErrorStructFfi _underlying; // ignore: unused_element diff --git a/feature_tests/dart/lib/Float64Vec.g.dart b/feature_tests/dart/lib/Float64Vec.g.dart index fbe3f1580..0f52e0033 100644 --- a/feature_tests/dart/lib/Float64Vec.g.dart +++ b/feature_tests/dart/lib/Float64Vec.g.dart @@ -5,7 +5,7 @@ part of 'lib.g.dart'; -class Float64Vec implements ffi.Finalizable { +final class Float64Vec implements ffi.Finalizable { final ffi.Pointer _underlying; Float64Vec._(this._underlying) { @@ -17,52 +17,37 @@ class Float64Vec implements ffi.Finalizable { factory Float64Vec(Float64List v) { final alloc = ffi2.Arena(); final vSlice = _SliceFfiDouble._fromDart(v, alloc); - final result = _Float64Vec_new(vSlice._bytes, vSlice._length); alloc.releaseAll(); return Float64Vec._(result); } + // ignore: non_constant_identifier_names - static final _Float64Vec_new = _capi< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, ffi.Size)>>('Float64Vec_new') - .asFunction< - ffi.Pointer Function( - ffi.Pointer, int)>(isLeaf: true); + static final _Float64Vec_new = + _capi Function(ffi.Pointer, ffi.Size)>>('Float64Vec_new') + .asFunction Function(ffi.Pointer, int)>(isLeaf: true); void fillSlice(Float64List v) { final alloc = ffi2.Arena(); final vSlice = _SliceFfiDouble._fromDart(v, alloc); - _Float64Vec_fill_slice(_underlying, vSlice._bytes, vSlice._length); alloc.releaseAll(); } // ignore: non_constant_identifier_names - static final _Float64Vec_fill_slice = _capi< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer, - ffi.Pointer, ffi.Size)>>('Float64Vec_fill_slice') - .asFunction< - void Function(ffi.Pointer, ffi.Pointer, - int)>(isLeaf: true); + static final _Float64Vec_fill_slice = + _capi, ffi.Pointer, ffi.Size)>>('Float64Vec_fill_slice') + .asFunction, ffi.Pointer, int)>(isLeaf: true); void setValue(Float64List newSlice) { final alloc = ffi2.Arena(); final newSliceSlice = _SliceFfiDouble._fromDart(newSlice, alloc); - - _Float64Vec_set_value( - _underlying, newSliceSlice._bytes, newSliceSlice._length); + _Float64Vec_set_value(_underlying, newSliceSlice._bytes, newSliceSlice._length); alloc.releaseAll(); } // ignore: non_constant_identifier_names - static final _Float64Vec_set_value = _capi< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer, - ffi.Pointer, ffi.Size)>>('Float64Vec_set_value') - .asFunction< - void Function(ffi.Pointer, ffi.Pointer, - int)>(isLeaf: true); + static final _Float64Vec_set_value = + _capi, ffi.Pointer, ffi.Size)>>('Float64Vec_set_value') + .asFunction, ffi.Pointer, int)>(isLeaf: true); } diff --git a/feature_tests/dart/lib/Foo.g.dart b/feature_tests/dart/lib/Foo.g.dart index 5a0a64f4f..ab44942c9 100644 --- a/feature_tests/dart/lib/Foo.g.dart +++ b/feature_tests/dart/lib/Foo.g.dart @@ -5,7 +5,7 @@ part of 'lib.g.dart'; -class Foo implements ffi.Finalizable { +final class Foo implements ffi.Finalizable { final ffi.Pointer _underlying; Foo._(this._underlying) { @@ -17,19 +17,15 @@ class Foo implements ffi.Finalizable { factory Foo(String x) { final alloc = ffi2.Arena(); final xSlice = _SliceFfi2Utf8._fromDart(x, alloc); - final result = _Foo_new(xSlice._bytes, xSlice._length); alloc.releaseAll(); return Foo._(result); } + // ignore: non_constant_identifier_names - static final _Foo_new = _capi< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, ffi.Size)>>('Foo_new') - .asFunction< - ffi.Pointer Function( - ffi.Pointer, int)>(isLeaf: true); + static final _Foo_new = + _capi Function(ffi.Pointer, ffi.Size)>>('Foo_new') + .asFunction Function(ffi.Pointer, int)>(isLeaf: true); Bar get getBar { final result = _Foo_get_bar(_underlying); @@ -37,29 +33,22 @@ class Foo implements ffi.Finalizable { } // ignore: non_constant_identifier_names - static final _Foo_get_bar = _capi< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer)>>('Foo_get_bar') - .asFunction Function(ffi.Pointer)>( - isLeaf: true); + static final _Foo_get_bar = + _capi Function(ffi.Pointer)>>('Foo_get_bar') + .asFunction Function(ffi.Pointer)>(isLeaf: true); factory Foo.static_(String x) { final alloc = ffi2.Arena(); final xSlice = _SliceFfi2Utf8._fromDart(x, alloc); - final result = _Foo_new_static(xSlice._bytes, xSlice._length); alloc.releaseAll(); return Foo._(result); } + // ignore: non_constant_identifier_names - static final _Foo_new_static = _capi< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, ffi.Size)>>('Foo_new_static') - .asFunction< - ffi.Pointer Function( - ffi.Pointer, int)>(isLeaf: true); + static final _Foo_new_static = + _capi Function(ffi.Pointer, ffi.Size)>>('Foo_new_static') + .asFunction Function(ffi.Pointer, int)>(isLeaf: true); BorrowedFieldsReturning get asReturning { final result = _Foo_as_returning(_underlying); @@ -67,23 +56,17 @@ class Foo implements ffi.Finalizable { } // ignore: non_constant_identifier_names - static final _Foo_as_returning = _capi< - ffi.NativeFunction< - _BorrowedFieldsReturningFfi Function( - ffi.Pointer)>>('Foo_as_returning') - .asFunction< - _BorrowedFieldsReturningFfi Function( - ffi.Pointer)>(isLeaf: true); + static final _Foo_as_returning = + _capi)>>('Foo_as_returning') + .asFunction<_BorrowedFieldsReturningFfi Function(ffi.Pointer)>(isLeaf: true); factory Foo.extractFromFields(BorrowedFields fields) { final result = _Foo_extract_from_fields(fields._underlying); return Foo._(result); } + // ignore: non_constant_identifier_names - static final _Foo_extract_from_fields = _capi< - ffi.NativeFunction< - ffi.Pointer Function( - _BorrowedFieldsFfi)>>('Foo_extract_from_fields') - .asFunction Function(_BorrowedFieldsFfi)>( - isLeaf: true); + static final _Foo_extract_from_fields = + _capi Function(_BorrowedFieldsFfi)>>('Foo_extract_from_fields') + .asFunction Function(_BorrowedFieldsFfi)>(isLeaf: true); } diff --git a/feature_tests/dart/lib/ImportedStruct.g.dart b/feature_tests/dart/lib/ImportedStruct.g.dart index 92106acc1..e68c48a9f 100644 --- a/feature_tests/dart/lib/ImportedStruct.g.dart +++ b/feature_tests/dart/lib/ImportedStruct.g.dart @@ -5,14 +5,14 @@ part of 'lib.g.dart'; -class _ImportedStructFfi extends ffi.Struct { +final class _ImportedStructFfi extends ffi.Struct { @ffi.Int32() external int foo; @ffi.Uint8() external int count; } -class ImportedStruct { +final class ImportedStruct { final _ImportedStructFfi _underlying; // ignore: unused_element diff --git a/feature_tests/dart/lib/MyEnum.g.dart b/feature_tests/dart/lib/MyEnum.g.dart index c6235f8c3..479b68950 100644 --- a/feature_tests/dart/lib/MyEnum.g.dart +++ b/feature_tests/dart/lib/MyEnum.g.dart @@ -7,10 +7,15 @@ part of 'lib.g.dart'; enum MyEnum { a, + b, + c, + d, + e, + f; int get _underlying { @@ -37,7 +42,6 @@ enum MyEnum { // ignore: non_constant_identifier_names static final _MyEnum_into_value = - _capi>( - 'MyEnum_into_value') - .asFunction(isLeaf: true); + _capi>('MyEnum_into_value') + .asFunction(isLeaf: true); } diff --git a/feature_tests/dart/lib/MyString.g.dart b/feature_tests/dart/lib/MyString.g.dart index f50b561a1..5a02a5093 100644 --- a/feature_tests/dart/lib/MyString.g.dart +++ b/feature_tests/dart/lib/MyString.g.dart @@ -5,7 +5,7 @@ part of 'lib.g.dart'; -class MyString implements ffi.Finalizable { +final class MyString implements ffi.Finalizable { final ffi.Pointer _underlying; MyString._(this._underlying) { @@ -17,36 +17,27 @@ class MyString implements ffi.Finalizable { factory MyString(String v) { final alloc = ffi2.Arena(); final vSlice = _SliceFfi2Utf8._fromDart(v, alloc); - final result = _MyString_new(vSlice._bytes, vSlice._length); alloc.releaseAll(); return MyString._(result); } + // ignore: non_constant_identifier_names - static final _MyString_new = _capi< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, ffi.Size)>>('MyString_new') - .asFunction< - ffi.Pointer Function( - ffi.Pointer, int)>(isLeaf: true); + static final _MyString_new = + _capi Function(ffi.Pointer, ffi.Size)>>('MyString_new') + .asFunction Function(ffi.Pointer, int)>(isLeaf: true); void setStr(String newStr) { final alloc = ffi2.Arena(); final newStrSlice = _SliceFfi2Utf8._fromDart(newStr, alloc); - _MyString_set_str(_underlying, newStrSlice._bytes, newStrSlice._length); alloc.releaseAll(); } // ignore: non_constant_identifier_names - static final _MyString_set_str = _capi< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer, ffi.Pointer, - ffi.Size)>>('MyString_set_str') - .asFunction< - void Function(ffi.Pointer, ffi.Pointer, - int)>(isLeaf: true); + static final _MyString_set_str = + _capi, ffi.Pointer, ffi.Size)>>('MyString_set_str') + .asFunction, ffi.Pointer, int)>(isLeaf: true); String get getStr { final writeable = _Writeable(); @@ -55,11 +46,7 @@ class MyString implements ffi.Finalizable { } // ignore: non_constant_identifier_names - static final _MyString_get_str = _capi< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer, - ffi.Pointer)>>('MyString_get_str') - .asFunction< - void Function( - ffi.Pointer, ffi.Pointer)>(isLeaf: true); + static final _MyString_get_str = + _capi, ffi.Pointer)>>('MyString_get_str') + .asFunction, ffi.Pointer)>(isLeaf: true); } diff --git a/feature_tests/dart/lib/MyStruct.g.dart b/feature_tests/dart/lib/MyStruct.g.dart index 1f8ea2c02..975bfd221 100644 --- a/feature_tests/dart/lib/MyStruct.g.dart +++ b/feature_tests/dart/lib/MyStruct.g.dart @@ -5,7 +5,7 @@ part of 'lib.g.dart'; -class _MyStructFfi extends ffi.Struct { +final class _MyStructFfi extends ffi.Struct { @ffi.Uint8() external int a; @ffi.Bool() @@ -22,7 +22,7 @@ class _MyStructFfi extends ffi.Struct { external int g; } -class MyStruct { +final class MyStruct { final _MyStructFfi _underlying; // ignore: unused_element @@ -65,8 +65,7 @@ class MyStruct { _underlying.f = f; } - MyEnum get g => - MyEnum.values.firstWhere((v) => v._underlying == _underlying.g); + MyEnum get g => MyEnum.values.firstWhere((v) => v._underlying == _underlying.g); set g(MyEnum g) { _underlying.g = g._underlying; } @@ -75,10 +74,11 @@ class MyStruct { final result = _MyStruct_new(); return MyStruct._(result); } + // ignore: non_constant_identifier_names static final _MyStruct_new = - _capi>('MyStruct_new') - .asFunction<_MyStructFfi Function()>(isLeaf: true); + _capi>('MyStruct_new') + .asFunction<_MyStructFfi Function()>(isLeaf: true); int intoA() { final result = _MyStruct_into_a(_underlying); @@ -87,9 +87,8 @@ class MyStruct { // ignore: non_constant_identifier_names static final _MyStruct_into_a = - _capi>( - 'MyStruct_into_a') - .asFunction(isLeaf: true); + _capi>('MyStruct_into_a') + .asFunction(isLeaf: true); @override bool operator ==(Object other) => diff --git a/feature_tests/dart/lib/One.g.dart b/feature_tests/dart/lib/One.g.dart index c3d07f97b..8e8c2e364 100644 --- a/feature_tests/dart/lib/One.g.dart +++ b/feature_tests/dart/lib/One.g.dart @@ -5,7 +5,7 @@ part of 'lib.g.dart'; -class One implements ffi.Finalizable { +final class One implements ffi.Finalizable { final ffi.Pointer _underlying; One._(this._underlying) { @@ -18,200 +18,109 @@ class One implements ffi.Finalizable { final result = _One_transitivity(hold._underlying, nohold._underlying); return One._(result); } + // ignore: non_constant_identifier_names - static final _One_transitivity = _capi< - ffi.NativeFunction< - ffi.Pointer Function(ffi.Pointer, - ffi.Pointer)>>('One_transitivity') - .asFunction< - ffi.Pointer Function( - ffi.Pointer, ffi.Pointer)>(isLeaf: true); + static final _One_transitivity = + _capi Function(ffi.Pointer, ffi.Pointer)>>('One_transitivity') + .asFunction Function(ffi.Pointer, ffi.Pointer)>(isLeaf: true); factory One.cycle(Two hold, One nohold) { final result = _One_cycle(hold._underlying, nohold._underlying); return One._(result); } + // ignore: non_constant_identifier_names - static final _One_cycle = _capi< - ffi.NativeFunction< - ffi.Pointer Function(ffi.Pointer, - ffi.Pointer)>>('One_cycle') - .asFunction< - ffi.Pointer Function( - ffi.Pointer, ffi.Pointer)>(isLeaf: true); + static final _One_cycle = + _capi Function(ffi.Pointer, ffi.Pointer)>>('One_cycle') + .asFunction Function(ffi.Pointer, ffi.Pointer)>(isLeaf: true); factory One.manyDependents(One a, One b, Two c, Two d, Two nohold) { - final result = _One_many_dependents(a._underlying, b._underlying, - c._underlying, d._underlying, nohold._underlying); + final result = _One_many_dependents(a._underlying, b._underlying, c._underlying, d._underlying, nohold._underlying); return One._(result); } + // ignore: non_constant_identifier_names - static final _One_many_dependents = _capi< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer)>>('One_many_dependents') - .asFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer)>(isLeaf: true); + static final _One_many_dependents = + _capi Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('One_many_dependents') + .asFunction Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>(isLeaf: true); factory One.returnOutlivesParam(Two hold, One nohold) { - final result = - _One_return_outlives_param(hold._underlying, nohold._underlying); + final result = _One_return_outlives_param(hold._underlying, nohold._underlying); return One._(result); } + // ignore: non_constant_identifier_names - static final _One_return_outlives_param = _capi< - ffi.NativeFunction< - ffi.Pointer Function(ffi.Pointer, - ffi.Pointer)>>('One_return_outlives_param') - .asFunction< - ffi.Pointer Function( - ffi.Pointer, ffi.Pointer)>(isLeaf: true); + static final _One_return_outlives_param = + _capi Function(ffi.Pointer, ffi.Pointer)>>('One_return_outlives_param') + .asFunction Function(ffi.Pointer, ffi.Pointer)>(isLeaf: true); factory One.diamondTop(One top, One left, One right, One bottom) { - final result = _One_diamond_top(top._underlying, left._underlying, - right._underlying, bottom._underlying); + final result = _One_diamond_top(top._underlying, left._underlying, right._underlying, bottom._underlying); return One._(result); } + // ignore: non_constant_identifier_names - static final _One_diamond_top = _capi< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer)>>('One_diamond_top') - .asFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer)>(isLeaf: true); + static final _One_diamond_top = + _capi Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('One_diamond_top') + .asFunction Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>(isLeaf: true); factory One.diamondLeft(One top, One left, One right, One bottom) { - final result = _One_diamond_left(top._underlying, left._underlying, - right._underlying, bottom._underlying); + final result = _One_diamond_left(top._underlying, left._underlying, right._underlying, bottom._underlying); return One._(result); } + // ignore: non_constant_identifier_names - static final _One_diamond_left = _capi< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer)>>('One_diamond_left') - .asFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer)>(isLeaf: true); + static final _One_diamond_left = + _capi Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('One_diamond_left') + .asFunction Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>(isLeaf: true); factory One.diamondRight(One top, One left, One right, One bottom) { - final result = _One_diamond_right(top._underlying, left._underlying, - right._underlying, bottom._underlying); + final result = _One_diamond_right(top._underlying, left._underlying, right._underlying, bottom._underlying); return One._(result); } + // ignore: non_constant_identifier_names - static final _One_diamond_right = _capi< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer)>>('One_diamond_right') - .asFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer)>(isLeaf: true); + static final _One_diamond_right = + _capi Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('One_diamond_right') + .asFunction Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>(isLeaf: true); factory One.diamondBottom(One top, One left, One right, One bottom) { - final result = _One_diamond_bottom(top._underlying, left._underlying, - right._underlying, bottom._underlying); + final result = _One_diamond_bottom(top._underlying, left._underlying, right._underlying, bottom._underlying); return One._(result); } + // ignore: non_constant_identifier_names - static final _One_diamond_bottom = _capi< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer)>>('One_diamond_bottom') - .asFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer)>(isLeaf: true); + static final _One_diamond_bottom = + _capi Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('One_diamond_bottom') + .asFunction Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>(isLeaf: true); factory One.diamondAndNestedTypes(One a, One b, One c, One d, One nohold) { - final result = _One_diamond_and_nested_types(a._underlying, b._underlying, - c._underlying, d._underlying, nohold._underlying); + final result = _One_diamond_and_nested_types(a._underlying, b._underlying, c._underlying, d._underlying, nohold._underlying); return One._(result); } + // ignore: non_constant_identifier_names - static final _One_diamond_and_nested_types = _capi< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer)>>('One_diamond_and_nested_types') - .asFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer)>(isLeaf: true); + static final _One_diamond_and_nested_types = + _capi Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('One_diamond_and_nested_types') + .asFunction Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>(isLeaf: true); factory One.implicitBounds(One explicitHold, One implicitHold, One nohold) { - final result = _One_implicit_bounds( - explicitHold._underlying, implicitHold._underlying, nohold._underlying); + final result = _One_implicit_bounds(explicitHold._underlying, implicitHold._underlying, nohold._underlying); return One._(result); } + // ignore: non_constant_identifier_names - static final _One_implicit_bounds = _capi< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer)>>('One_implicit_bounds') - .asFunction< - ffi.Pointer Function(ffi.Pointer, - ffi.Pointer, ffi.Pointer)>(isLeaf: true); - - factory One.implicitBoundsDeep( - One explicit, One implicit1, One implicit2, One nohold) { - final result = _One_implicit_bounds_deep(explicit._underlying, - implicit1._underlying, implicit2._underlying, nohold._underlying); + static final _One_implicit_bounds = + _capi Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('One_implicit_bounds') + .asFunction Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(isLeaf: true); + + factory One.implicitBoundsDeep(One explicit, One implicit1, One implicit2, One nohold) { + final result = _One_implicit_bounds_deep(explicit._underlying, implicit1._underlying, implicit2._underlying, nohold._underlying); return One._(result); } + // ignore: non_constant_identifier_names - static final _One_implicit_bounds_deep = _capi< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer)>>('One_implicit_bounds_deep') - .asFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer)>(isLeaf: true); + static final _One_implicit_bounds_deep = + _capi Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('One_implicit_bounds_deep') + .asFunction Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>(isLeaf: true); } diff --git a/feature_tests/dart/lib/Opaque.g.dart b/feature_tests/dart/lib/Opaque.g.dart index 4e2038cc1..d7168906d 100644 --- a/feature_tests/dart/lib/Opaque.g.dart +++ b/feature_tests/dart/lib/Opaque.g.dart @@ -5,7 +5,7 @@ part of 'lib.g.dart'; -class Opaque implements ffi.Finalizable { +final class Opaque implements ffi.Finalizable { final ffi.Pointer _underlying; Opaque._(this._underlying) { @@ -18,11 +18,11 @@ class Opaque implements ffi.Finalizable { final result = _Opaque_new(); return Opaque._(result); } + // ignore: non_constant_identifier_names static final _Opaque_new = - _capi Function()>>( - 'Opaque_new') - .asFunction Function()>(isLeaf: true); + _capi Function()>>('Opaque_new') + .asFunction Function()>(isLeaf: true); /// See the [Rust documentation for `something`](https://docs.rs/Something/latest/struct.Something.html#method.something) for more information. /// @@ -34,19 +34,11 @@ class Opaque implements ffi.Finalizable { } // ignore: non_constant_identifier_names - static final _Opaque_assert_struct = _capi< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer, - _MyStructFfi)>>('Opaque_assert_struct') - .asFunction, _MyStructFfi)>( - isLeaf: true); - - static final int returnsUsize = - _capi>('Opaque_returns_usize') - .asFunction(isLeaf: true)(); - - static final ImportedStruct returnsImported = - _capi>( - 'Opaque_returns_imported') - .asFunction<_ImportedStructFfi Function()>(isLeaf: true)(); + static final _Opaque_assert_struct = + _capi, _MyStructFfi)>>('Opaque_assert_struct') + .asFunction, _MyStructFfi)>(isLeaf: true); + + static final int returnsUsize = _capi>('Opaque_returns_usize').asFunction(isLeaf: true)(); + + static final ImportedStruct returnsImported = _capi>('Opaque_returns_imported').asFunction<_ImportedStructFfi Function()>(isLeaf: true)(); } diff --git a/feature_tests/dart/lib/OptionOpaque.g.dart b/feature_tests/dart/lib/OptionOpaque.g.dart index c543bfe81..f69d2b090 100644 --- a/feature_tests/dart/lib/OptionOpaque.g.dart +++ b/feature_tests/dart/lib/OptionOpaque.g.dart @@ -5,57 +5,47 @@ part of 'lib.g.dart'; +final class OptionOpaque implements ffi.Finalizable { + final ffi.Pointer _underlying; -class OptionOpaque implements ffi.Finalizable { - - final ffi.Pointer _underlying; - - OptionOpaque._(this._underlying) { - _finalizer.attach(this, _underlying.cast()); - } + OptionOpaque._(this._underlying) { + _finalizer.attach(this, _underlying.cast()); + } - static final _finalizer = ffi.NativeFinalizer(_capi('OptionOpaque_destroy')); + static final _finalizer = ffi.NativeFinalizer(_capi('OptionOpaque_destroy')); - -static OptionOpaque? new_(int i) { - - final result = _OptionOpaque_new(i); - return result.address == 0 ? null : OptionOpaque._(result); + static OptionOpaque? new_(int i) { + final result = _OptionOpaque_new(i); + return result.address == 0 ? null : OptionOpaque._(result); } - // ignore: non_constant_identifier_names - static final _OptionOpaque_new= _capi Function(ffi.Int32)>>('OptionOpaque_new') - .asFunction Function(int)>(isLeaf: true); + // ignore: non_constant_identifier_names + static final _OptionOpaque_new = + _capi Function(ffi.Int32)>>('OptionOpaque_new') + .asFunction Function(int)>(isLeaf: true); - -static final OptionOpaque? none = _capi Function()>>('OptionOpaque_new_none').asFunction Function()>(isLeaf: true)(); + static final OptionOpaque? none = _capi Function()>>('OptionOpaque_new_none').asFunction Function()>(isLeaf: true)(); - -static final OptionStruct struct = _capi>('OptionOpaque_new_struct').asFunction<_OptionStructFfi Function()>(isLeaf: true)(); + static final OptionStruct struct = _capi>('OptionOpaque_new_struct').asFunction<_OptionStructFfi Function()>(isLeaf: true)(); - -static final OptionStruct structNones = _capi>('OptionOpaque_new_struct_nones').asFunction<_OptionStructFfi Function()>(isLeaf: true)(); + static final OptionStruct structNones = _capi>('OptionOpaque_new_struct_nones').asFunction<_OptionStructFfi Function()>(isLeaf: true)(); - -void assertInteger(int i) { - - _OptionOpaque_assert_integer(_underlying,i); + void assertInteger(int i) { + _OptionOpaque_assert_integer(_underlying, i); } - // ignore: non_constant_identifier_names - static final _OptionOpaque_assert_integer= _capi, ffi.Int32)>>('OptionOpaque_assert_integer') - .asFunction, int)>(isLeaf: true); - - -static bool optionOpaqueArgument(OptionOpaque? arg) { - - final result = _OptionOpaque_option_opaque_argument(arg == null ? ffi.Pointer.fromAddress(0) ? arg._underlying); - return result; - } // ignore: non_constant_identifier_names - static final _OptionOpaque_option_opaque_argument= _capi)>>('OptionOpaque_option_opaque_argument') - .asFunction)>(isLeaf: true); - + static final _OptionOpaque_assert_integer = + _capi, ffi.Int32)>>('OptionOpaque_assert_integer') + .asFunction, int)>(isLeaf: true); - } + static bool optionOpaqueArgument(OptionOpaque? arg) { + final result = _OptionOpaque_option_opaque_argument(arg == null ? ffi.Pointer.fromAddress(0) ? arg._underlying); + return result; + } + // ignore: non_constant_identifier_names + static final _OptionOpaque_option_opaque_argument = + _capi)>>('OptionOpaque_option_opaque_argument') + .asFunction)>(isLeaf: true); +} diff --git a/feature_tests/dart/lib/OptionOpaqueChar.g.dart b/feature_tests/dart/lib/OptionOpaqueChar.g.dart index a6989f4f6..d097777f8 100644 --- a/feature_tests/dart/lib/OptionOpaqueChar.g.dart +++ b/feature_tests/dart/lib/OptionOpaqueChar.g.dart @@ -5,24 +5,21 @@ part of 'lib.g.dart'; -class OptionOpaqueChar implements ffi.Finalizable { +final class OptionOpaqueChar implements ffi.Finalizable { final ffi.Pointer _underlying; OptionOpaqueChar._(this._underlying) { _finalizer.attach(this, _underlying.cast()); } - static final _finalizer = - ffi.NativeFinalizer(_capi('OptionOpaqueChar_destroy')); + static final _finalizer = ffi.NativeFinalizer(_capi('OptionOpaqueChar_destroy')); void assertChar(int ch) { _OptionOpaqueChar_assert_char(_underlying, ch); } // ignore: non_constant_identifier_names - static final _OptionOpaqueChar_assert_char = _capi< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer, - ffi.Uint32)>>('OptionOpaqueChar_assert_char') + static final _OptionOpaqueChar_assert_char = + _capi, ffi.Uint32)>>('OptionOpaqueChar_assert_char') .asFunction, int)>(isLeaf: true); } diff --git a/feature_tests/dart/lib/OptionStruct.g.dart b/feature_tests/dart/lib/OptionStruct.g.dart index c2cbf62d6..416f4e70b 100644 --- a/feature_tests/dart/lib/OptionStruct.g.dart +++ b/feature_tests/dart/lib/OptionStruct.g.dart @@ -5,55 +5,60 @@ part of 'lib.g.dart'; - -class _OptionStructFfi extends ffi.Struct { - external ffi.Pointer a; - external ffi.Pointer b; - @ffi.Uint32() - external int c; - external ffi.Pointer d; +final class _OptionStructFfi extends ffi.Struct { + external ffi.Pointer a; + external ffi.Pointer b; + @ffi.Uint32() + external int c; + external ffi.Pointer d; } -class OptionStruct { - final _OptionStructFfi _underlying; - - // ignore: unused_element - OptionStruct._(this._underlying); - - factory OptionStruct() { - final pointer = ffi2.calloc<_OptionStructFfi>(); - final result = OptionStruct._(pointer.ref); - _callocFree.attach(result, pointer.cast()); - return result; - } - - OptionOpaque? get a => _underlying.a.address == 0 ? null : OptionOpaque._(_underlying.a); - set a(OptionOpaque? a) { - _underlying.a = a == null ? ffi.Pointer.fromAddress(0) ? a._underlying; - } -OptionOpaqueChar? get b => _underlying.b.address == 0 ? null : OptionOpaqueChar._(_underlying.b); - set b(OptionOpaqueChar? b) { - _underlying.b = b == null ? ffi.Pointer.fromAddress(0) ? b._underlying; - } -int get c => _underlying.c; - set c(int c) { - _underlying.c = c; - } -OptionOpaque? get d => _underlying.d.address == 0 ? null : OptionOpaque._(_underlying.d); - set d(OptionOpaque? d) { - _underlying.d = d == null ? ffi.Pointer.fromAddress(0) ? d._underlying; - } - - - @override - bool operator ==(Object other) => - other is OptionStruct - && other._underlying.a == _underlying.a - && other._underlying.b == _underlying.b - && other._underlying.c == _underlying.c - && other._underlying.d == _underlying.d; - - @override - int get hashCode => Object.hashAll([_underlying.a,_underlying.b,_underlying.c,_underlying.d,]); -} +final class OptionStruct { + final _OptionStructFfi _underlying; + + // ignore: unused_element + OptionStruct._(this._underlying); + + factory OptionStruct() { + final pointer = ffi2.calloc<_OptionStructFfi>(); + final result = OptionStruct._(pointer.ref); + _callocFree.attach(result, pointer.cast()); + return result; + } + + OptionOpaque? get a => _underlying.a.address == 0 ? null : OptionOpaque._(_underlying.a); + set a(OptionOpaque? a) { + _underlying.a = a == null ? ffi.Pointer.fromAddress(0) ? a._underlying; + } + OptionOpaqueChar? get b => _underlying.b.address == 0 ? null : OptionOpaqueChar._(_underlying.b); + set b(OptionOpaqueChar? b) { + _underlying.b = b == null ? ffi.Pointer.fromAddress(0) ? b._underlying; + } + + int get c => _underlying.c; + set c(int c) { + _underlying.c = c; + } + + OptionOpaque? get d => _underlying.d.address == 0 ? null : OptionOpaque._(_underlying.d); + set d(OptionOpaque? d) { + _underlying.d = d == null ? ffi.Pointer.fromAddress(0) ? d._underlying; + } + + @override + bool operator ==(Object other) => + other is OptionStruct && + other._underlying.a == _underlying.a && + other._underlying.b == _underlying.b && + other._underlying.c == _underlying.c && + other._underlying.d == _underlying.d; + + @override + int get hashCode => Object.hashAll([ + _underlying.a, + _underlying.b, + _underlying.c, + _underlying.d, + ]); +} diff --git a/feature_tests/dart/lib/RefList.g.dart b/feature_tests/dart/lib/RefList.g.dart index d6e699adb..f1f07e3b6 100644 --- a/feature_tests/dart/lib/RefList.g.dart +++ b/feature_tests/dart/lib/RefList.g.dart @@ -5,7 +5,7 @@ part of 'lib.g.dart'; -class RefList implements ffi.Finalizable { +final class RefList implements ffi.Finalizable { final ffi.Pointer _underlying; RefList._(this._underlying) { @@ -18,11 +18,9 @@ class RefList implements ffi.Finalizable { final result = _RefList_node(data._underlying); return RefList._(result); } + // ignore: non_constant_identifier_names - static final _RefList_node = _capi< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer)>>('RefList_node') - .asFunction Function(ffi.Pointer)>( - isLeaf: true); + static final _RefList_node = + _capi Function(ffi.Pointer)>>('RefList_node') + .asFunction Function(ffi.Pointer)>(isLeaf: true); } diff --git a/feature_tests/dart/lib/RefListParameter.g.dart b/feature_tests/dart/lib/RefListParameter.g.dart index ea2c61018..fb4114182 100644 --- a/feature_tests/dart/lib/RefListParameter.g.dart +++ b/feature_tests/dart/lib/RefListParameter.g.dart @@ -5,13 +5,12 @@ part of 'lib.g.dart'; -class RefListParameter implements ffi.Finalizable { +final class RefListParameter implements ffi.Finalizable { final ffi.Pointer _underlying; RefListParameter._(this._underlying) { _finalizer.attach(this, _underlying.cast()); } - static final _finalizer = - ffi.NativeFinalizer(_capi('RefListParameter_destroy')); + static final _finalizer = ffi.NativeFinalizer(_capi('RefListParameter_destroy')); } diff --git a/feature_tests/dart/lib/ResultOpaque.g.dart b/feature_tests/dart/lib/ResultOpaque.g.dart index 0db9a898e..001b72127 100644 --- a/feature_tests/dart/lib/ResultOpaque.g.dart +++ b/feature_tests/dart/lib/ResultOpaque.g.dart @@ -5,7 +5,7 @@ part of 'lib.g.dart'; -class ResultOpaque implements ffi.Finalizable { +final class ResultOpaque implements ffi.Finalizable { final ffi.Pointer _underlying; ResultOpaque._(this._underlying) { @@ -14,7 +14,7 @@ class ResultOpaque implements ffi.Finalizable { static final _finalizer = ffi.NativeFinalizer(_capi('ResultOpaque_destroy')); - /// + /// /// /// Throws [ErrorEnum] on failure. factory ResultOpaque(int i) { @@ -24,13 +24,13 @@ class ResultOpaque implements ffi.Finalizable { } return ResultOpaque._(result.union.ok); } + // ignore: non_constant_identifier_names static final _ResultOpaque_new = - _capi>( - 'ResultOpaque_new') - .asFunction<_ResultOpaqueInt32 Function(int)>(isLeaf: true); + _capi>('ResultOpaque_new') + .asFunction<_ResultOpaqueInt32 Function(int)>(isLeaf: true); - /// + /// /// /// Throws [ErrorEnum] on failure. factory ResultOpaque.failingFoo() { @@ -40,13 +40,13 @@ class ResultOpaque implements ffi.Finalizable { } return ResultOpaque._(result.union.ok); } + // ignore: non_constant_identifier_names static final _ResultOpaque_new_failing_foo = - _capi>( - 'ResultOpaque_new_failing_foo') - .asFunction<_ResultOpaqueInt32 Function()>(isLeaf: true); + _capi>('ResultOpaque_new_failing_foo') + .asFunction<_ResultOpaqueInt32 Function()>(isLeaf: true); - /// + /// /// /// Throws [ErrorEnum] on failure. factory ResultOpaque.failingBar() { @@ -56,13 +56,13 @@ class ResultOpaque implements ffi.Finalizable { } return ResultOpaque._(result.union.ok); } + // ignore: non_constant_identifier_names static final _ResultOpaque_new_failing_bar = - _capi>( - 'ResultOpaque_new_failing_bar') - .asFunction<_ResultOpaqueInt32 Function()>(isLeaf: true); + _capi>('ResultOpaque_new_failing_bar') + .asFunction<_ResultOpaqueInt32 Function()>(isLeaf: true); - /// + /// /// /// Throws [VoidError] on failure. factory ResultOpaque.failingUnit() { @@ -72,13 +72,13 @@ class ResultOpaque implements ffi.Finalizable { } return ResultOpaque._(result.union.ok); } + // ignore: non_constant_identifier_names static final _ResultOpaque_new_failing_unit = - _capi>( - 'ResultOpaque_new_failing_unit') - .asFunction<_ResultOpaqueVoid Function()>(isLeaf: true); + _capi>('ResultOpaque_new_failing_unit') + .asFunction<_ResultOpaqueVoid Function()>(isLeaf: true); - /// + /// /// /// Throws [ErrorStruct] on failure. factory ResultOpaque.failingStruct(int i) { @@ -88,14 +88,13 @@ class ResultOpaque implements ffi.Finalizable { } return ResultOpaque._(result.union.ok); } + // ignore: non_constant_identifier_names - static final _ResultOpaque_new_failing_struct = _capi< - ffi - .NativeFunction<_ResultOpaqueErrorStructFfi Function(ffi.Int32)>>( - 'ResultOpaque_new_failing_struct') + static final _ResultOpaque_new_failing_struct = + _capi>('ResultOpaque_new_failing_struct') .asFunction<_ResultOpaqueErrorStructFfi Function(int)>(isLeaf: true); - /// + /// /// /// Throws [ResultOpaque] on failure. static void newInErr(int i) { @@ -107,11 +106,10 @@ class ResultOpaque implements ffi.Finalizable { // ignore: non_constant_identifier_names static final _ResultOpaque_new_in_err = - _capi>( - 'ResultOpaque_new_in_err') - .asFunction<_ResultVoidOpaque Function(int)>(isLeaf: true); + _capi>('ResultOpaque_new_in_err') + .asFunction<_ResultVoidOpaque Function(int)>(isLeaf: true); - /// + /// /// /// Throws [VoidError] on failure. static int newInt(int i) { @@ -124,11 +122,10 @@ class ResultOpaque implements ffi.Finalizable { // ignore: non_constant_identifier_names static final _ResultOpaque_new_int = - _capi>( - 'ResultOpaque_new_int') - .asFunction<_ResultInt32Void Function(int)>(isLeaf: true); + _capi>('ResultOpaque_new_int') + .asFunction<_ResultInt32Void Function(int)>(isLeaf: true); - /// + /// /// /// Throws [ResultOpaque] on failure. static ErrorEnum newInEnumErr(int i) { @@ -141,18 +138,15 @@ class ResultOpaque implements ffi.Finalizable { // ignore: non_constant_identifier_names static final _ResultOpaque_new_in_enum_err = - _capi>( - 'ResultOpaque_new_in_enum_err') - .asFunction<_ResultInt32Opaque Function(int)>(isLeaf: true); + _capi>('ResultOpaque_new_in_enum_err') + .asFunction<_ResultInt32Opaque Function(int)>(isLeaf: true); void assertInteger(int i) { _ResultOpaque_assert_integer(_underlying, i); } // ignore: non_constant_identifier_names - static final _ResultOpaque_assert_integer = _capi< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer, - ffi.Int32)>>('ResultOpaque_assert_integer') + static final _ResultOpaque_assert_integer = + _capi, ffi.Int32)>>('ResultOpaque_assert_integer') .asFunction, int)>(isLeaf: true); } diff --git a/feature_tests/dart/lib/Two.g.dart b/feature_tests/dart/lib/Two.g.dart index 10b69fc73..635ed3c60 100644 --- a/feature_tests/dart/lib/Two.g.dart +++ b/feature_tests/dart/lib/Two.g.dart @@ -5,7 +5,7 @@ part of 'lib.g.dart'; -class Two implements ffi.Finalizable { +final class Two implements ffi.Finalizable { final ffi.Pointer _underlying; Two._(this._underlying) { diff --git a/feature_tests/dart/lib/UnimportedEnum.g.dart b/feature_tests/dart/lib/UnimportedEnum.g.dart index 3c9c55229..51d38a0b8 100644 --- a/feature_tests/dart/lib/UnimportedEnum.g.dart +++ b/feature_tests/dart/lib/UnimportedEnum.g.dart @@ -7,6 +7,8 @@ part of 'lib.g.dart'; enum UnimportedEnum { a, + b, + c; } diff --git a/feature_tests/dart/lib/lib.g.dart b/feature_tests/dart/lib/lib.g.dart index d7f3e69fe..b2174046b 100644 --- a/feature_tests/dart/lib/lib.g.dart +++ b/feature_tests/dart/lib/lib.g.dart @@ -38,82 +38,82 @@ void init(String path) => _capi = ffi.DynamicLibrary.open(path).lookup; final _callocFree = Finalizer(ffi2.calloc.free); -class _ResultInt32OpaqueUnion extends ffi.Union { +final class _ResultInt32OpaqueUnion extends ffi.Union { @ffi.Int32() external int ok; external ffi.Pointer err; } -class _ResultInt32Opaque extends ffi.Struct { +final class _ResultInt32Opaque extends ffi.Struct { external _ResultInt32OpaqueUnion union; @ffi.Bool() external bool isOk; } -class _ResultInt32VoidUnion extends ffi.Union { +final class _ResultInt32VoidUnion extends ffi.Union { @ffi.Int32() external int ok; } -class _ResultInt32Void extends ffi.Struct { +final class _ResultInt32Void extends ffi.Struct { external _ResultInt32VoidUnion union; @ffi.Bool() external bool isOk; } -class _ResultOpaqueErrorStructFfiUnion extends ffi.Union { +final class _ResultOpaqueErrorStructFfiUnion extends ffi.Union { external ffi.Pointer ok; external _ErrorStructFfi err; } -class _ResultOpaqueErrorStructFfi extends ffi.Struct { +final class _ResultOpaqueErrorStructFfi extends ffi.Struct { external _ResultOpaqueErrorStructFfiUnion union; @ffi.Bool() external bool isOk; } -class _ResultOpaqueInt32Union extends ffi.Union { +final class _ResultOpaqueInt32Union extends ffi.Union { external ffi.Pointer ok; @ffi.Int32() external int err; } -class _ResultOpaqueInt32 extends ffi.Struct { +final class _ResultOpaqueInt32 extends ffi.Struct { external _ResultOpaqueInt32Union union; @ffi.Bool() external bool isOk; } -class _ResultOpaqueVoidUnion extends ffi.Union { +final class _ResultOpaqueVoidUnion extends ffi.Union { external ffi.Pointer ok; } -class _ResultOpaqueVoid extends ffi.Struct { +final class _ResultOpaqueVoid extends ffi.Struct { external _ResultOpaqueVoidUnion union; @ffi.Bool() external bool isOk; } -class _ResultVoidOpaqueUnion extends ffi.Union { +final class _ResultVoidOpaqueUnion extends ffi.Union { external ffi.Pointer err; } -class _ResultVoidOpaque extends ffi.Struct { +final class _ResultVoidOpaque extends ffi.Struct { external _ResultVoidOpaqueUnion union; @ffi.Bool() external bool isOk; } -class _SliceFfi2Utf8 extends ffi.Struct { +final class _SliceFfi2Utf8 extends ffi.Struct { external ffi.Pointer _bytes; @ffi.Size() @@ -129,13 +129,11 @@ class _SliceFfi2Utf8 extends ffi.Struct { slice._length = units.length; slice._bytes = allocator(slice._length).cast(); slice._bytes.cast().asTypedList(slice._length).setAll(0, units); - return slice; } // ignore: unused_element - String get _asDart => - Utf8Decoder().convert(_bytes.cast().asTypedList(_length)); + String get _asDart => Utf8Decoder().convert(_bytes.cast().asTypedList(_length)); // This is expensive @override @@ -157,7 +155,7 @@ class _SliceFfi2Utf8 extends ffi.Struct { int get hashCode => _length.hashCode; } -class _SliceFfiDouble extends ffi.Struct { +final class _SliceFfiDouble extends ffi.Struct { external ffi.Pointer _bytes; @ffi.Size() @@ -172,7 +170,6 @@ class _SliceFfiDouble extends ffi.Struct { slice._length = value.length; slice._bytes = allocator(slice._length); slice._bytes.asTypedList(slice._length).setAll(0, value); - return slice; } @@ -199,7 +196,7 @@ class _SliceFfiDouble extends ffi.Struct { int get hashCode => _length.hashCode; } -class _SliceFfiUint16 extends ffi.Struct { +final class _SliceFfiUint16 extends ffi.Struct { external ffi.Pointer _bytes; @ffi.Size() @@ -214,7 +211,6 @@ class _SliceFfiUint16 extends ffi.Struct { slice._length = value.length; slice._bytes = allocator(slice._length); slice._bytes.asTypedList(slice._length).setAll(0, value); - return slice; } @@ -241,7 +237,7 @@ class _SliceFfiUint16 extends ffi.Struct { int get hashCode => _length.hashCode; } -class _SliceFfiUint8 extends ffi.Struct { +final class _SliceFfiUint8 extends ffi.Struct { external ffi.Pointer _bytes; @ffi.Size() @@ -256,7 +252,6 @@ class _SliceFfiUint8 extends ffi.Struct { slice._length = value.length; slice._bytes = allocator(slice._length); slice._bytes.asTypedList(slice._length).setAll(0, value); - return slice; } @@ -286,34 +281,27 @@ class _SliceFfiUint8 extends ffi.Struct { /// An unspecified error value class VoidError {} -class _Writeable { +final class _Writeable { final ffi.Pointer _underlying; _Writeable() : _underlying = _create(0); static final _create = - _capi Function(ffi.Size)>>( - 'diplomat_buffer_writeable_create') - .asFunction Function(int)>(); + _capi Function(ffi.Size)>>('diplomat_buffer_writeable_create') + .asFunction Function(int)>(); String finalize() { - final string = - _getBytes(_underlying).toDartString(length: _len(_underlying)); + final string = _getBytes(_underlying).toDartString(length: _len(_underlying)); _destroy(_underlying); return string; } + static final _len = + _capi)>>('diplomat_buffer_writeable_len') + .asFunction)>(isLeaf: true); - static final _len = - _capi)>>( - 'diplomat_buffer_writeable_len') - .asFunction)>(isLeaf: true); - static final _getBytes = _capi< - ffi.NativeFunction< - ffi.Pointer Function(ffi.Pointer)>>( - 'diplomat_buffer_writeable_get_bytes') - .asFunction Function(ffi.Pointer)>( - isLeaf: true); + static final _getBytes = + _capi Function(ffi.Pointer)>>('diplomat_buffer_writeable_get_bytes') + .asFunction Function(ffi.Pointer)>(isLeaf: true); static final _destroy = - _capi)>>( - 'diplomat_buffer_writeable_destroy') - .asFunction)>(isLeaf: true); + _capi)>>('diplomat_buffer_writeable_destroy') + .asFunction)>(isLeaf: true); } diff --git a/tool/src/dart/class.rs b/tool/src/dart/class.rs deleted file mode 100644 index b33309a96..000000000 --- a/tool/src/dart/class.rs +++ /dev/null @@ -1,973 +0,0 @@ -use super::DartContext; -use super::DartFormatter; -use askama::Template; -use diplomat_core::hir::{ - self, OpaqueOwner, ReturnType, SelfType, SuccessType, TyPosition, Type, TypeDef, TypeId, -}; -use std::borrow::Cow; -use std::collections::BTreeMap; -use std::collections::BTreeSet; -use std::fmt::Write; - -impl<'tcx> DartContext<'tcx> { - pub fn gen_root( - &self, - mut directives: BTreeSet>, - helper_classes: BTreeMap, - ) { - directives.insert(self.formatter.fmt_renamed_import("dart:ffi", "ffi")); - directives.insert( - self.formatter - .fmt_renamed_import("package:ffi/ffi.dart", "ffi2"), - ); - self.files.add_file( - self.formatter.fmt_file_name("lib"), - Class { - body: include_str!("../../templates/dart/init.dart").into(), - directives, - helper_classes, - } - .render(), - ); - } - - pub fn gen_ty( - &self, - id: TypeId, - directives: &mut BTreeSet>, - helper_classes: &mut BTreeMap, - ) { - let ty = self.tcx.resolve_type(id); - - let _guard = self.errors.set_context_ty(ty.name().as_str().into()); - - let name = self.formatter.fmt_type_name(id); - directives.insert(self.formatter.fmt_part(&name)); - - let mut tgcx = TyGenContext { - imports: directives, - helper_classes, - cx: self, - }; - - let body = match ty { - TypeDef::Enum(o) => tgcx.gen_enum(o, id, &name), - TypeDef::Opaque(o) => tgcx.gen_opaque_def(o, id, &name), - TypeDef::Struct(s) => tgcx.gen_struct_def(s, id, &name), - TypeDef::OutStruct(s) => tgcx.gen_struct_def(s, id, &name), - _ => unreachable!("unknown AST/HIR variant"), - }; - - self.files.add_file( - self.formatter.fmt_file_name(&name), - Class { - body, - directives: BTreeSet::from_iter([self.formatter.fmt_part_of_lib()]), - helper_classes: Default::default(), - } - .render(), - ); - } -} - -#[derive(PartialEq, Ord, PartialOrd, Clone, Eq, Debug)] -struct Class { - body: String, - directives: BTreeSet>, - helper_classes: BTreeMap, -} - -impl Class { - fn render(self) -> String { - #[derive(askama::Template)] - #[template(path = "dart/base.dart.jinja", escape = "none")] - struct ClassTemplate { - directives: BTreeSet>, - body: String, - helper_classes: BTreeMap, - } - - let Self { - body, - directives, - helper_classes, - .. - } = self; - - ClassTemplate { - body, - directives, - helper_classes, - } - .render() - .unwrap() - } -} - -pub struct TyGenContext<'a, 'dartcx, 'tcx> { - cx: &'dartcx DartContext<'tcx>, - imports: &'a mut BTreeSet>, - helper_classes: &'a mut BTreeMap, -} - -impl<'a, 'dartcx, 'tcx: 'dartcx> TyGenContext<'a, 'dartcx, 'tcx> { - fn gen_enum(&mut self, ty: &'tcx hir::EnumDef, id: TypeId, type_name: &str) -> String { - #[derive(Template)] - #[template(path = "dart/enum.dart.jinja", escape = "none")] - struct ImplTemplate<'a> { - ty: &'a hir::EnumDef, - fmt: &'a DartFormatter<'a>, - type_name: &'a str, - methods: &'a [MethodInfo<'a>], - docs: String, - is_contiguous: bool, - } - - let methods = ty - .methods - .iter() - .flat_map(|method| self.gen_method_info(id, method, type_name)) - .collect::>(); - - ImplTemplate { - ty, - fmt: &self.cx.formatter, - type_name, - methods: methods.as_slice(), - docs: self.cx.formatter.fmt_docs(&ty.docs), - is_contiguous: is_contiguous_enum(ty), - } - .render() - .unwrap() - } - - fn gen_opaque_def(&mut self, ty: &'tcx hir::OpaqueDef, id: TypeId, type_name: &str) -> String { - #[derive(Template)] - #[template(path = "dart/opaque.dart.jinja", escape = "none")] - struct ImplTemplate<'a> { - type_name: &'a str, - methods: &'a [MethodInfo<'a>], - docs: String, - destructor: String, - } - - self.imports - .insert(self.cx.formatter.fmt_renamed_import("dart:ffi", "ffi")); - - let methods = ty - .methods - .iter() - .flat_map(|method| self.gen_method_info(id, method, type_name)) - .collect::>(); - - let destructor = self.cx.formatter.fmt_destructor_name(id); - - ImplTemplate { - type_name, - methods: methods.as_slice(), - destructor, - docs: self.cx.formatter.fmt_docs(&ty.docs), - } - .render() - .unwrap() - } - - fn gen_struct_def( - &mut self, - ty: &'tcx hir::StructDef

, - id: TypeId, - type_name: &str, - ) -> String { - #[derive(Template)] - #[template(path = "dart/struct.dart.jinja", escape = "none")] - struct ImplTemplate<'a> { - type_name: &'a str, - fields: &'a [FieldInfo<'a>], - methods: &'a [MethodInfo<'a>], - docs: String, - } - - struct FieldInfo<'a> { - name: Cow<'a, str>, - annotation: Option<&'static str>, - ffi_cast_type_name: Cow<'a, str>, - dart_type_name: Cow<'a, str>, - get_expression: Cow<'a, str>, - set_expression: Cow<'a, str>, - set_slice_conversions: Vec>, - } - - self.imports - .insert(self.cx.formatter.fmt_renamed_import("dart:ffi", "ffi")); - - let fields = ty - .fields - .iter() - .map(|field| { - let name = self.cx.formatter.fmt_param_name(field.name.as_str()); - - let annotation = match field.ty { - hir::Type::Primitive(p) => { - Some(self.cx.formatter.fmt_primitive_as_ffi(p, false)) - } - hir::Type::Enum(_) => Some(self.cx.formatter.fmt_enum_as_ffi(false)), - _ => None, - }; - - let ffi_cast_type_name = if let hir::Type::Slice(s) = field.ty { - self.gen_slice(&s).into() - } else { - self.gen_type_name_ffi(&field.ty, true) - }; - - let dart_type_name = self.gen_type_name(&field.ty); - - let get_expression = - self.gen_c_to_dart_for_type(&field.ty, format!("_underlying.{name}").into()); - - let mut set_slice_conversions = Vec::new(); - - let set_expression = self.gen_dart_to_c_for_type( - &field.ty, - name.clone(), - &mut set_slice_conversions, - ); - - FieldInfo { - name, - annotation, - ffi_cast_type_name, - dart_type_name, - get_expression, - set_expression, - set_slice_conversions, - } - }) - .collect::>(); - - let methods = ty - .methods - .iter() - .flat_map(|method| self.gen_method_info(id, method, type_name)) - .collect::>(); - - ImplTemplate { - type_name, - fields: &fields, - methods: methods.as_slice(), - docs: self.cx.formatter.fmt_docs(&ty.docs), - } - .render() - .unwrap() - } - - fn gen_method_info( - &mut self, - id: TypeId, - method: &'tcx hir::Method, - type_name: &str, - ) -> Option> { - if method.attrs.disable { - return None; - } - - let _guard = self.cx.errors.set_context_method( - self.cx.formatter.fmt_type_name_diagnostics(id), - method.name.as_str().into(), - ); - - self.imports - .insert(self.cx.formatter.fmt_renamed_import("dart:ffi", "ffi")); - - let c_method_name = self.cx.formatter.fmt_c_method_name(id, method); - - let mut param_decls_dart = Vec::new(); - let mut param_types_ffi = Vec::new(); - let mut param_types_ffi_cast = Vec::new(); - let mut dart_to_ffi_params = Vec::new(); - - if let Some(param_self) = method.param_self.as_ref() { - param_types_ffi.push(self.gen_self_type_ffi(¶m_self.ty, false)); - param_types_ffi_cast.push(self.gen_self_type_ffi(¶m_self.ty, true)); - dart_to_ffi_params.push(self.gen_dart_to_c_self(¶m_self.ty)); - } - - let mut slice_conversions = Vec::new(); - - for param in method.params.iter() { - param_decls_dart.push(self.gen_ty_decl(¶m.ty, param.name.as_str())); - - let param_type_ffi = self.gen_type_name_ffi(¶m.ty, false); - let param_type_ffi_cast = self.gen_type_name_ffi(¶m.ty, true); - let conversion = self.gen_dart_to_c_for_type( - ¶m.ty, - self.cx.formatter.fmt_param_name(param.name.as_str()), - &mut slice_conversions, - ); - - if matches!(param.ty, hir::Type::Slice(..)) { - param_types_ffi.push(self.cx.formatter.fmt_pointer(¶m_type_ffi).into()); - param_types_ffi.push(self.cx.formatter.fmt_usize(false).into()); - - param_types_ffi_cast - .push(self.cx.formatter.fmt_pointer(¶m_type_ffi_cast).into()); - param_types_ffi_cast.push(self.cx.formatter.fmt_usize(true).into()); - - dart_to_ffi_params.push(format!("{conversion}._bytes").into()); - dart_to_ffi_params.push(format!("{conversion}._length").into()); - } else { - param_types_ffi.push(param_type_ffi); - param_types_ffi_cast.push(param_type_ffi_cast); - dart_to_ffi_params.push(conversion); - } - } - - if method.is_writeable() { - dart_to_ffi_params.push("writeable._underlying".into()); - param_types_ffi.push( - self.cx - .formatter - .fmt_pointer(self.cx.formatter.fmt_opaque()) - .into(), - ); - param_types_ffi_cast.push( - self.cx - .formatter - .fmt_pointer(self.cx.formatter.fmt_opaque()) - .into(), - ); - self.helper_classes.insert( - "writeable".into(), - include_str!("../../templates/dart/writeable.dart").into(), - ); - } - - let ffi_return_ty = self.gen_ffi_return_type_name(&method.output, false); - let ffi_cast_return_ty = self.gen_ffi_return_type_name(&method.output, true); - - let dart_return_expression: Option> = - self.gen_c_to_dart_for_return_type(&method.output, "result".into()); - - let params = param_decls_dart - .iter() - .map(|param| format!("{} {}", param.type_name, param.var_name)) - .collect::>() - .join(", "); - - let return_ty = self.gen_dart_return_type_name(&method.output); - - let declaration = if method.param_self.is_none() { - // Constructor - if return_ty == type_name { - if let Some(name) = self.cx.formatter.fmt_constructor_name(method) { - format!("factory {type_name}.{name}({params})") - } else { - format!("factory {type_name}({params})") - } - // Static field - } else if params.is_empty() - && !matches!(method.output, hir::ReturnType::Fallible(..)) - && return_ty != "bool" - { - let method_name = self - .cx - .formatter - .fmt_constructor_name(method) - .unwrap_or("singleton".into()); - format!( - "static final {return_ty} {method_name} = \ - _capi>('{c_method_name}')\ - .asFunction<{ffi_cast_return_ty} Function()>(isLeaf: true)();" - ) - // Static method - } else { - let method_name = self.cx.formatter.fmt_method_name(method); - format!("static {return_ty} {method_name}({params})") - } - // Getter - } else if method.params.is_empty() - // Returns some value - && method.output.return_type().is_some() - // If it returns a bool it has be a `isFoo`, otherwise the bool might be a success flag of a side effect - && (return_ty != "bool" || method.name.as_str().starts_with("is")) - // Conversions are not getters according to the style guide - && !(method.name.as_str().starts_with("to") || method.name.as_str().starts_with("into")) - // Mutates - && !method.name.as_str().starts_with("enable") - // Clone and build are not getters according to the style guide, and next is usually not pure - && !["clone", "next", "build"].contains(&method.name.as_str()) - { - let method_name = self.cx.formatter.fmt_method_name(method); - format!("{return_ty} get {method_name}",) - // Setter - } else if method.name.as_str().starts_with("set_") - && method.params.len() == 1 - && method.output.return_type().is_none() - // The corresponding getter exists, as required by the style guide - && self - .cx - .tcx - .resolve_type(id) - .methods() - .iter() - .any(|m| m.name.as_str() == method.name.as_str().strip_prefix("set_").unwrap()) - { - let method_name = self.cx.formatter.fmt_setter_name(method); - format!("set {method_name}({params})") - } else if method.name.as_str() == "to_string" - && method.output.is_writeable() - && params.is_empty() - { - "@override\n String toString()".to_string() - } else if method.name.as_str() == "get" - && method.output.return_type().is_some() - && method.params.len() == 1 - { - format!("{return_ty} operator []({params})") - } else { - let method_name = self.cx.formatter.fmt_method_name(method); - format!("{return_ty} {method_name}({params})") - }; - - let mut docs = self.cx.formatter.fmt_docs(&method.docs); - - if let hir::ReturnType::Fallible(_, e) = &method.output { - write!( - &mut docs, - "\n///\n/// Throws [{}] on failure.", - &if let Some(e) = e { - self.gen_type_name(e) - } else { - "VoidError".into() - }, - ) - .unwrap(); - } - - Some(MethodInfo { - method, - docs, - declaration, - c_method_name, - param_types_ffi, - param_types_ffi_cast, - ffi_return_ty, - ffi_cast_return_ty, - dart_to_ffi_params, - dart_return_expression, - slice_conversions, - }) - } - - /// Generates Dart code for referencing a particular type with a given name. - fn gen_ty_decl<'b, P: TyPosition>(&mut self, ty: &Type

, var_name: &'b str) -> NamedType<'b> - where - 'dartcx: 'b, - { - let var_name = self.cx.formatter.fmt_param_name(var_name); - let type_name = self.gen_type_name(ty); - - NamedType { - var_name, - type_name, - } - } - - /// Generates Dart code for referencing a particular Dart type. - /// - /// This function adds the necessary type imports to the decl and impl files. - fn gen_type_name(&mut self, ty: &Type

) -> Cow<'dartcx, str> { - match *ty { - Type::Primitive(prim) => self.cx.formatter.fmt_primitive_as_ffi(prim, true).into(), - Type::Opaque(ref op) => { - let op_id = op.tcx_id.into(); - let type_name = self.cx.formatter.fmt_type_name(op_id); - - if self.cx.tcx.resolve_type(op_id).attrs().disable { - self.cx - .errors - .push_error(format!("Found usage of disabled type {type_name}")) - } - let ret = if op.is_optional() { - self.cx.formatter.fmt_nullable(&type_name) - } else { - type_name - }; - - ret.into_owned().into() - } - Type::Struct(ref st) => { - let id = P::id_for_path(st); - let type_name = self.cx.formatter.fmt_type_name(id); - if self.cx.tcx.resolve_type(id).attrs().disable { - self.cx - .errors - .push_error(format!("Found usage of disabled type {type_name}")) - } - type_name - } - Type::Enum(ref e) => { - let id = e.tcx_id.into(); - let type_name = self.cx.formatter.fmt_type_name(id); - if self.cx.tcx.resolve_type(id).attrs().disable { - self.cx - .errors - .push_error(format!("Found usage of disabled type {type_name}")) - } - type_name - } - Type::Slice(hir::Slice::Str(_lifetime)) => self.cx.formatter.fmt_string().into(), - Type::Slice(hir::Slice::Primitive(_, p)) => { - self.imports - .insert(self.cx.formatter.fmt_import("dart:typed_data")); - self.cx.formatter.fmt_primitive_list_type(p).into() - } - _ => unreachable!("unknown AST/HIR variant"), - } - } - - /// Generates Dart code for referencing a particular FFI type with a given name. - fn gen_type_name_ffi<'b, P: TyPosition>(&mut self, ty: &Type

, cast: bool) -> Cow<'b, str> - where - 'dartcx: 'b, - { - match *ty { - Type::Primitive(prim) => self.cx.formatter.fmt_primitive_as_ffi(prim, cast).into(), - Type::Opaque(ref op) => { - let op_id = op.tcx_id.into(); - let type_name = self.cx.formatter.fmt_type_name(op_id); - if self.cx.tcx.resolve_type(op_id).attrs().disable { - self.cx - .errors - .push_error(format!("Found usage of disabled type {type_name}")) - } - self.cx - .formatter - .fmt_pointer(self.cx.formatter.fmt_opaque()) - .into() - } - Type::Struct(ref st) => { - let id = P::id_for_path(st); - let type_name = self.cx.formatter.fmt_type_name(id); - if self.cx.tcx.resolve_type(id).attrs().disable { - self.cx - .errors - .push_error(format!("Found usage of disabled type {type_name}")) - } - format!("_{type_name}Ffi").into() - } - Type::Enum(ref e) => { - let id = e.tcx_id.into(); - let type_name = self.cx.formatter.fmt_type_name(id); - if self.cx.tcx.resolve_type(id).attrs().disable { - self.cx - .errors - .push_error(format!("Found usage of disabled type {type_name}")) - } - self.cx.formatter.fmt_enum_as_ffi(cast).into() - } - Type::Slice(hir::Slice::Str(_lifetime)) => { - self.cx.formatter.fmt_utf8_primitive().into() - } - Type::Slice(hir::Slice::Primitive(_, p)) => { - self.cx.formatter.fmt_primitive_as_ffi(p, false).into() - } - _ => unreachable!("unknown AST/HIR variant"), - } - } - - fn gen_self_type_ffi(&self, ty: &SelfType, cast: bool) -> Cow<'tcx, str> { - match ty { - SelfType::Opaque(_) => self - .cx - .formatter - .fmt_pointer(self.cx.formatter.fmt_opaque()) - .into(), - SelfType::Struct(s) => format!("_{}Ffi", s.resolve(self.cx.tcx).name.as_str()).into(), - SelfType::Enum(_) => self.cx.formatter.fmt_enum_as_ffi(cast).into(), - _ => unreachable!("unknown AST/HIR variant"), - } - } - - /// Generates Dart code for referencing a particular FFI type. - /// - /// This function adds the necessary type imports to the decl and impl files. - - /// Generates a C++ expression that converts from the C++ self type to the corresponding C self type. - fn gen_dart_to_c_self(&self, ty: &SelfType) -> Cow<'static, str> { - match *ty { - SelfType::Enum(ref e) if is_contiguous_enum(e.resolve(self.cx.tcx)) => "index".into(), - SelfType::Opaque(..) | SelfType::Struct(..) | SelfType::Enum(..) => { - "_underlying".into() - } - _ => unreachable!("unknown AST/HIR variant"), - } - } - - /// Generates one or two C++ expressions that convert from a C++ type to the corresponding C type. - /// - /// Returns `PartiallyNamedExpression`s whose `suffix` is either empty, `Data`, or `Size` for - /// referencing fields of the C struct. - fn gen_dart_to_c_for_type<'b, P: TyPosition>( - &mut self, - ty: &Type

, - dart_name: Cow<'b, str>, - slice_conversions: &mut Vec>, - ) -> Cow<'b, str> { - match *ty { - Type::Primitive(..) => dart_name.clone(), - Type::Opaque(ref op) if op.is_optional() => format!( - "{dart_name} == null ? ffi.Pointer.fromAddress(0) ? {dart_name}._underlying" - ) - .into(), - Type::Enum(ref e) if is_contiguous_enum(e.resolve(self.cx.tcx)) => { - format!("{dart_name}.index").into() - } - Type::Opaque(..) | Type::Struct(..) | Type::Enum(..) => { - format!("{dart_name}._underlying").into() - } - Type::Slice(s) => { - let name = format!("{dart_name}Slice"); - slice_conversions.push( - format!( - "final {name} = {}._fromDart({dart_name}, alloc);", - &self.gen_slice(&s) - ) - .into(), - ); - name.into() - } - _ => unreachable!("unknown AST/HIR variant"), - } - } - - /// Generates the Dart type name of a return type. - fn gen_dart_return_type_name(&mut self, result_ty: &ReturnType) -> Cow<'dartcx, str> { - match *result_ty { - ReturnType::Infallible(None) => self.cx.formatter.fmt_void().into(), - ReturnType::Infallible(Some(ref ty)) => match ty { - SuccessType::Writeable => self.cx.formatter.fmt_string().into(), - SuccessType::OutType(o) => self.gen_type_name(o), - &_ => unreachable!("unknown AST/HIR variant"), - }, - ReturnType::Fallible(ref ok, _) => match ok { - Some(SuccessType::Writeable) => self.cx.formatter.fmt_string().into(), - None => self.cx.formatter.fmt_void().into(), - Some(SuccessType::OutType(o)) => self.gen_type_name(o), - &Some(_) => unreachable!("unknown AST/HIR variant"), - }, - } - } - - fn gen_slice(&mut self, slice: &hir::Slice) -> &'static str { - #[derive(askama::Template)] - #[template(path = "dart/slice.dart.jinja", escape = "none")] - struct SliceTemplate { - ffi_type: &'static str, - slice_ty: &'static str, - dart_ty: &'static str, - to_dart: &'static str, - from_dart: &'static str, - } - - self.imports.insert( - self.cx - .formatter - .fmt_renamed_import("package:ffi/ffi.dart", "ffi2"), - ); - - let dart_ty = match slice { - hir::Slice::Str(..) => self.cx.formatter.fmt_string(), - hir::Slice::Primitive(_, p) => { - self.imports - .insert(self.cx.formatter.fmt_import("dart:typed_data")); - self.cx.formatter.fmt_primitive_list_type(*p) - } - _ => todo!("{slice:?}"), - }; - - let slice_ty = match slice { - hir::Slice::Str(..) => self.cx.formatter.fmt_str_slice_type(), - hir::Slice::Primitive(_, p) => self.cx.formatter.fmt_slice_type(*p), - _ => todo!("{slice:?}"), - }; - - let ffi_type = match slice { - hir::Slice::Str(..) => self.cx.formatter.fmt_utf8_primitive(), - hir::Slice::Primitive(_, p) => self.cx.formatter.fmt_primitive_as_ffi(*p, false), - _ => todo!("{slice:?}"), - }; - - let to_dart = match slice { - hir::Slice::Str(..) => { - self.imports - .insert(self.cx.formatter.fmt_import("dart:convert")); - "Utf8Decoder().convert(_bytes.cast().asTypedList(_length))" - } - // TODO: How to read ffi.Size? - hir::Slice::Primitive(_, hir::PrimitiveType::IntSize(_)) => "this", - _ => "_bytes.asTypedList(_length)", - }; - - let from_dart = match slice { - hir::Slice::Str(..) => concat!( - " final units = Utf8Encoder().convert(value);\n", - " slice._length = units.length;\n", - // TODO: Figure out why Pointer cannot be allocated - " slice._bytes = allocator(slice._length).cast();\n", - " slice._bytes.cast().asTypedList(slice._length).setAll(0, units);\n" - ), - hir::Slice::Primitive(_, hir::PrimitiveType::IntSize(_)) => "", - _ => concat!( - " slice._length = value.length;\n", - " slice._bytes = allocator(slice._length);\n", - " slice._bytes.asTypedList(slice._length).setAll(0, value);\n" - ), - }; - - self.helper_classes.insert( - slice_ty.into(), - SliceTemplate { - ffi_type, - slice_ty, - dart_ty, - to_dart, - from_dart, - } - .render() - .unwrap(), - ); - - slice_ty - } - - /// Generates the Dart FFI type name of a return type. - fn gen_ffi_return_type_name( - &mut self, - result_ty: &ReturnType, - cast: bool, - ) -> Cow<'dartcx, str> { - match *result_ty { - ReturnType::Infallible(None) => if cast { - self.cx.formatter.fmt_void() - } else { - self.cx.formatter.fmt_ffi_void() - } - .into(), - ReturnType::Infallible(Some(ref ty)) => match ty { - SuccessType::Writeable => if cast { - self.cx.formatter.fmt_void() - } else { - self.cx.formatter.fmt_ffi_void() - } - .into(), - SuccessType::OutType(o) => { - if let hir::OutType::Slice(s) = o { - self.gen_slice(s).into() - } else { - self.gen_type_name_ffi(o, cast) - } - } - &_ => unreachable!("unknown AST/HIR variant"), - }, - ReturnType::Fallible(ref ok, ref err) => { - #[derive(askama::Template)] - #[template(path = "dart/result.dart.jinja", escape = "none")] - struct ResultTemplate { - name: String, - decls: Vec, - } - - let ok = match ok { - None | Some(SuccessType::Writeable) => None, - Some(SuccessType::OutType(o)) => Some(o), - &Some(_) => unreachable!("unknown AST/HIR variant"), - }; - - let err = err.as_ref(); - - let name = format!( - "_Result{}{}", - &self - .cx - .formatter - .fmt_type_as_ident(ok.map(|o| self.gen_type_name_ffi(o, false)).as_deref()), - &self.cx.formatter.fmt_type_as_ident( - err.map(|o| self.gen_type_name_ffi(o, false)).as_deref() - ) - ); - - let decls = - [ok.map(|o| (o, "ok")), err.map(|o| (o, "err"))] - .into_iter() - .flatten() - .map(|(o, field_name)| { - format!( - "{}external {} {field_name};\n", - match o { - hir::OutType::Primitive(p) => { - format!( - "@{}()\n\t\t", - self.cx.formatter.fmt_primitive_as_ffi(*p, false) - ) - } - hir::OutType::Enum(_) => format!( - "@{}()\n\t\t", - self.cx.formatter.fmt_enum_as_ffi(false) - ), - _ => String::new(), - }, - { self.gen_type_name_ffi(o, true) } - ) - }) - .collect(); - - self.helper_classes.insert( - name.clone(), - ResultTemplate { - name: name.clone(), - decls, - } - .render() - .unwrap(), - ); - - name.into() - } - } - } - - /// Generates a C++ expression that converts from a C type to the corresponding C++ type. - /// - /// If the type is a slice, this function assumes that `{var_name}_data` and `{var_name}_size` resolve - /// to valid expressions referencing the two different C variables for the pointer and the length. - fn gen_c_to_dart_for_type<'b, P: TyPosition>( - &mut self, - ty: &Type

, - var_name: Cow<'b, str>, - ) -> Cow<'b, str> { - match *ty { - Type::Primitive(..) => var_name, - Type::Opaque(ref op) => { - let id = op.tcx_id.into(); - let type_name = self.cx.formatter.fmt_type_name(id); - - match (op.owner.is_owned(), op.is_optional()) { - (false, _) => unimplemented!(), - (true, false) => format!("{type_name}._({var_name})").into(), - (true, true) => { - format!("{var_name}.address == 0 ? null : {type_name}._({var_name})").into() - } - } - } - Type::Struct(ref st) => { - let id = P::id_for_path(st); - let type_name = self.cx.formatter.fmt_type_name(id); - format!("{type_name}._({var_name})").into() - } - Type::Enum(ref e) if is_contiguous_enum(e.resolve(self.cx.tcx)) => { - let id = e.tcx_id.into(); - let type_name = self.cx.formatter.fmt_type_name(id); - format!("{type_name}.values[{var_name}]").into() - } - Type::Enum(ref e) => { - let id = e.tcx_id.into(); - let type_name = self.cx.formatter.fmt_type_name(id); - format!("{type_name}.values.firstWhere((v) => v._underlying == {var_name})").into() - } - Type::Slice(..) => format!("{var_name}._asDart").into(), - _ => unreachable!("unknown AST/HIR variant"), - } - } - - /// Generates a C++ expression that converts from a C return type to the corresponding C++ return type. - /// - /// If the type is `Writeable`, this function assumes that there is a variable named `writeable` in scope. - fn gen_c_to_dart_for_return_type<'b>( - &mut self, - result_ty: &ReturnType, - var_name: Cow<'b, str>, - ) -> Option> { - match *result_ty { - ReturnType::Infallible(None) => None, - ReturnType::Infallible(Some(SuccessType::Writeable)) => { - Some("return writeable.finalize();".into()) - } - ReturnType::Infallible(Some(SuccessType::OutType(ref out_ty))) => { - Some(format!("return {};", self.gen_c_to_dart_for_type(out_ty, var_name)).into()) - } - ReturnType::Fallible(ref ok, ref err) => { - let ok_path = format!("{var_name}.union.ok"); - let err_path = format!("{var_name}.union.err"); - let err_conversion = match err { - Some(o) => self.gen_c_to_dart_for_type(o, err_path.into()), - None => { - self.helper_classes.insert( - "voiderror".into(), - "/// An unspecified error value\nclass VoidError {}".into(), - ); - "VoidError()".into() - } - }; - let err_check = - format!("if (!{var_name}.isOk) {{ throw {err_conversion}; }}").into(); - let ok_conversion = match ok { - // Note: the `writeable` variable is a string initialized in the template - Some(SuccessType::Writeable) => "writeable.finalize()".into(), - Some(SuccessType::OutType(o)) => self.gen_c_to_dart_for_type(o, ok_path.into()), - None => return Some(err_check), - &Some(_) => unreachable!("unknown AST/HIR variant"), - }; - Some(format!("{err_check}\nreturn {ok_conversion};").into()) - } - ReturnType::Infallible(Some(_)) => unreachable!("unknown AST/HIR variant"), - } - } -} - -fn is_contiguous_enum(ty: &hir::EnumDef) -> bool { - ty.variants - .iter() - .enumerate() - .all(|(i, v)| i as isize == v.discriminant) -} - -/// A type name with a corresponding variable name, such as a struct field or a function parameter. -struct NamedType<'a> { - var_name: Cow<'a, str>, - type_name: Cow<'a, str>, -} - -/// Everything needed for rendering a method. -struct MethodInfo<'a> { - /// HIR of the method being rendered - method: &'a hir::Method, - /// - docs: String, - /// The declaration (everything before the parameter list) - declaration: String, - /// The C method name - c_method_name: Cow<'a, str>, - - param_types_ffi: Vec>, - param_types_ffi_cast: Vec>, - ffi_return_ty: Cow<'a, str>, - ffi_cast_return_ty: Cow<'a, str>, - - slice_conversions: Vec>, - - /// Dart conversion code for each parameter of the C function - dart_to_ffi_params: Vec>, - /// If the function has a return value, the Dart code for the conversion. Assumes that - /// the C function return value is saved to a variable named `result` or that the - /// writeable, if present, is saved to a variable named `writeable`. - dart_return_expression: Option>, -} - -#[derive(PartialEq, Ord, PartialOrd, Clone, Eq, Debug)] -struct ResultClass { - ok_name: String, - err_name: String, - ok_decl: Option, - err_decl: Option, -} diff --git a/tool/src/dart/formatter.rs b/tool/src/dart/formatter.rs index 359545d65..ab21974ec 100644 --- a/tool/src/dart/formatter.rs +++ b/tool/src/dart/formatter.rs @@ -59,7 +59,9 @@ impl<'tcx> DartFormatter<'tcx> { pub fn fmt_docs(&self, docs: &hir::Docs) -> String { docs.to_markdown(self.docs_url_generator, MarkdownStyle::Normal) + .trim() .replace('\n', "\n/// ") + .replace(" \n", "\n") .replace( &format!("`{}", self.strip_prefix.as_deref().unwrap_or("")), "`", diff --git a/tool/src/dart/mod.rs b/tool/src/dart/mod.rs index e5ef2dddb..207b2c2cf 100644 --- a/tool/src/dart/mod.rs +++ b/tool/src/dart/mod.rs @@ -1,50 +1,933 @@ -mod class; -mod formatter; - use crate::common::{ErrorStore, FileMap}; +use askama::Template; use diplomat_core::ast::DocsUrlGenerator; use diplomat_core::hir::TypeContext; +use diplomat_core::hir::{ + self, OpaqueOwner, ReturnType, SelfType, SuccessType, TyPosition, Type, TypeDef, TypeId, +}; use formatter::DartFormatter; +use std::borrow::Cow; +use std::collections::{BTreeMap, BTreeSet}; +use std::fmt::{Display, Write}; -/// This is the main object that drives this backend. Most execution steps -/// for this backend will be found as methods on this context -pub(crate) struct DartContext<'tcx> { - tcx: &'tcx TypeContext, - formatter: DartFormatter<'tcx>, - pub files: FileMap, - pub errors: ErrorStore<'tcx, String>, -} +mod formatter; + +/// Run file generation +pub fn run<'cx>( + tcx: &'cx TypeContext, + docs_url_generator: &'cx DocsUrlGenerator, + strip_prefix: Option, +) -> Result> { + let formatter = DartFormatter::new(tcx, docs_url_generator, strip_prefix); + + let files = FileMap::default(); + let errors = ErrorStore::default(); -impl<'tcx> DartContext<'tcx> { - pub fn new( - tcx: &'tcx TypeContext, - files: FileMap, - docs_url_generator: &'tcx DocsUrlGenerator, - strip_prefix: Option, - ) -> Self { - DartContext { + let mut directives = BTreeSet::default(); + let mut helper_classes = BTreeMap::default(); + + for (id, ty) in tcx.all_types() { + if ty.attrs().disable { + continue; + } + + let (file_name, body) = TyGenContext { tcx, - files, - formatter: DartFormatter::new(tcx, docs_url_generator, strip_prefix), - errors: ErrorStore::default(), + imports: &mut directives, + errors: &errors, + helper_classes: &mut helper_classes, + formatter: &formatter, + } + .gen(id); + + files.add_file( + file_name, + render_class( + body, + BTreeSet::from_iter([formatter.fmt_part_of_lib()]), + Default::default(), + ), + ); + } + + directives.insert(formatter.fmt_renamed_import("dart:ffi", "ffi")); + directives.insert(formatter.fmt_renamed_import("package:ffi/ffi.dart", "ffi2")); + files.add_file( + formatter.fmt_file_name("lib"), + render_class( + include_str!("../../templates/dart/init.dart").into(), + directives, + helper_classes, + ), + ); + + let errors = errors.take_all(); + if !errors.is_empty() { + Err(errors) + } else { + Ok(files) + } +} + +fn render_class( + body: String, + directives: BTreeSet>, + helper_classes: BTreeMap, +) -> String { + #[derive(askama::Template)] + #[template(path = "dart/base.dart.jinja", escape = "none")] + struct ClassTemplate { + directives: BTreeSet>, + body: String, + helper_classes: BTreeMap, + } + + ClassTemplate { + body, + directives, + helper_classes, + } + .render() + .unwrap() +} + +struct TyGenContext<'a, 'cx> { + tcx: &'cx TypeContext, + formatter: &'a DartFormatter<'cx>, + errors: &'a ErrorStore<'cx, String>, + imports: &'a mut BTreeSet>, + helper_classes: &'a mut BTreeMap, +} + +impl<'a, 'cx> TyGenContext<'a, 'cx> { + fn gen(&mut self, id: TypeId) -> (String, String) { + let ty = self.tcx.resolve_type(id); + + let _guard = self.errors.set_context_ty(ty.name().as_str().into()); + + let name = self.formatter.fmt_type_name(id); + self.imports.insert(self.formatter.fmt_part(&name)); + + ( + self.formatter.fmt_file_name(&name), + match ty { + TypeDef::Enum(e) => self.gen_enum(e, id, &name), + TypeDef::Opaque(o) => self.gen_opaque_def(o, id, &name), + TypeDef::Struct(s) => self.gen_struct_def(s, id, &name), + TypeDef::OutStruct(s) => self.gen_struct_def(s, id, &name), + _ => unreachable!("unknown AST/HIR variant"), + }, + ) + } + + fn gen_enum(&mut self, ty: &'cx hir::EnumDef, id: TypeId, type_name: &str) -> String { + #[derive(Template)] + #[template(path = "dart/enum.dart.jinja", escape = "none")] + struct ImplTemplate<'a> { + ty: &'a hir::EnumDef, + fmt: &'a DartFormatter<'a>, + type_name: &'a str, + methods: &'a [MethodInfo<'a>], + docs: String, + is_contiguous: bool, + } + + let methods = ty + .methods + .iter() + .flat_map(|method| self.gen_method_info(id, method, type_name)) + .collect::>(); + + ImplTemplate { + ty, + fmt: self.formatter, + type_name, + methods: methods.as_slice(), + docs: self.formatter.fmt_docs(&ty.docs), + is_contiguous: is_contiguous_enum(ty), } + .render() + .unwrap() } - /// Run file generation + fn gen_opaque_def(&mut self, ty: &'cx hir::OpaqueDef, id: TypeId, type_name: &str) -> String { + #[derive(Template)] + #[template(path = "dart/opaque.dart.jinja", escape = "none")] + struct ImplTemplate<'a> { + type_name: &'a str, + methods: &'a [MethodInfo<'a>], + docs: String, + destructor: String, + } + + self.imports + .insert(self.formatter.fmt_renamed_import("dart:ffi", "ffi")); + + let methods = ty + .methods + .iter() + .flat_map(|method| self.gen_method_info(id, method, type_name)) + .collect::>(); + + let destructor = self.formatter.fmt_destructor_name(id); + + ImplTemplate { + type_name, + methods: methods.as_slice(), + destructor, + docs: self.formatter.fmt_docs(&ty.docs), + } + .render() + .unwrap() + } + + fn gen_struct_def( + &mut self, + ty: &'cx hir::StructDef

, + id: TypeId, + type_name: &str, + ) -> String { + #[derive(Template)] + #[template(path = "dart/struct.dart.jinja", escape = "none")] + struct ImplTemplate<'a> { + type_name: &'a str, + fields: &'a [FieldInfo<'a>], + methods: &'a [MethodInfo<'a>], + docs: String, + } + + struct FieldInfo<'a> { + name: Cow<'a, str>, + annotation: Option<&'static str>, + ffi_cast_type_name: Cow<'a, str>, + dart_type_name: Cow<'a, str>, + get_expression: Cow<'a, str>, + set_expression: Cow<'a, str>, + set_slice_conversions: Vec>, + } + + self.imports + .insert(self.formatter.fmt_renamed_import("dart:ffi", "ffi")); + + let fields = ty + .fields + .iter() + .map(|field| { + let name = self.formatter.fmt_param_name(field.name.as_str()); + + let annotation = match field.ty { + hir::Type::Primitive(p) => Some(self.formatter.fmt_primitive_as_ffi(p, false)), + hir::Type::Enum(_) => Some(self.formatter.fmt_enum_as_ffi(false)), + _ => None, + }; + + let ffi_cast_type_name = if let hir::Type::Slice(s) = field.ty { + self.gen_slice(&s).into() + } else { + self.gen_type_name_ffi(&field.ty, true) + }; + + let dart_type_name = self.gen_type_name(&field.ty); + + let get_expression = + self.gen_c_to_dart_for_type(&field.ty, format!("_underlying.{name}").into()); + + let mut set_slice_conversions = Vec::new(); + + let set_expression = self.gen_dart_to_c_for_type( + &field.ty, + name.clone(), + &mut set_slice_conversions, + ); + + FieldInfo { + name, + annotation, + ffi_cast_type_name, + dart_type_name, + get_expression, + set_expression, + set_slice_conversions, + } + }) + .collect::>(); + + let methods = ty + .methods + .iter() + .flat_map(|method| self.gen_method_info(id, method, type_name)) + .collect::>(); + + ImplTemplate { + type_name, + fields: &fields, + methods: methods.as_slice(), + docs: self.formatter.fmt_docs(&ty.docs), + } + .render() + .unwrap() + } + + fn gen_method_info( + &mut self, + id: TypeId, + method: &'cx hir::Method, + type_name: &str, + ) -> Option> { + if method.attrs.disable { + return None; + } + + let _guard = self.errors.set_context_method( + self.formatter.fmt_type_name_diagnostics(id), + method.name.as_str().into(), + ); + + self.imports + .insert(self.formatter.fmt_renamed_import("dart:ffi", "ffi")); + + let c_method_name = self.formatter.fmt_c_method_name(id, method); + + let mut param_decls_dart = Vec::new(); + let mut param_types_ffi = Vec::new(); + let mut param_types_ffi_cast = Vec::new(); + let mut dart_to_ffi_params = Vec::new(); + + if let Some(param_self) = method.param_self.as_ref() { + param_types_ffi.push(self.gen_self_type_ffi(¶m_self.ty, false)); + param_types_ffi_cast.push(self.gen_self_type_ffi(¶m_self.ty, true)); + dart_to_ffi_params.push(self.gen_dart_to_c_self(¶m_self.ty)); + } + + let mut slice_conversions = Vec::new(); + + for param in method.params.iter() { + param_decls_dart.push(format!( + "{} {}", + self.gen_type_name(¶m.ty), + self.formatter.fmt_param_name(param.name.as_str()) + )); + + let param_type_ffi = self.gen_type_name_ffi(¶m.ty, false); + let param_type_ffi_cast = self.gen_type_name_ffi(¶m.ty, true); + let conversion = self.gen_dart_to_c_for_type( + ¶m.ty, + self.formatter.fmt_param_name(param.name.as_str()), + &mut slice_conversions, + ); + + if matches!(param.ty, hir::Type::Slice(..)) { + param_types_ffi.push(self.formatter.fmt_pointer(¶m_type_ffi).into()); + param_types_ffi.push(self.formatter.fmt_usize(false).into()); + + param_types_ffi_cast.push(self.formatter.fmt_pointer(¶m_type_ffi_cast).into()); + param_types_ffi_cast.push(self.formatter.fmt_usize(true).into()); + + dart_to_ffi_params.push(format!("{conversion}._bytes").into()); + dart_to_ffi_params.push(format!("{conversion}._length").into()); + } else { + param_types_ffi.push(param_type_ffi); + param_types_ffi_cast.push(param_type_ffi_cast); + dart_to_ffi_params.push(conversion); + } + } + + if method.is_writeable() { + dart_to_ffi_params.push("writeable._underlying".into()); + param_types_ffi.push( + self.formatter + .fmt_pointer(self.formatter.fmt_opaque()) + .into(), + ); + param_types_ffi_cast.push( + self.formatter + .fmt_pointer(self.formatter.fmt_opaque()) + .into(), + ); + self.helper_classes.insert( + "writeable".into(), + include_str!("../../templates/dart/writeable.dart").into(), + ); + } + + let ffi_return_ty = self.gen_ffi_return_type_name(&method.output, false); + let ffi_cast_return_ty = self.gen_ffi_return_type_name(&method.output, true); + + let dart_return_expression: Option> = + self.gen_c_to_dart_for_return_type(&method.output, "result".into()); + + let params = param_decls_dart.join(", "); + + let return_ty = self.gen_dart_return_type_name(&method.output); + + let declaration = if method.param_self.is_none() { + // Constructor + if return_ty == type_name { + if let Some(name) = self.formatter.fmt_constructor_name(method) { + format!("factory {type_name}.{name}({params})") + } else { + format!("factory {type_name}({params})") + } + // Static field + } else if params.is_empty() + && !matches!(method.output, hir::ReturnType::Fallible(..)) + && return_ty != "bool" + { + let method_name = self + .formatter + .fmt_constructor_name(method) + .unwrap_or("singleton".into()); + format!( + "static final {return_ty} {method_name} = \ + _capi>('{c_method_name}')\ + .asFunction<{ffi_cast_return_ty} Function()>(isLeaf: true)();" + ) + // Static method + } else { + let method_name = self.formatter.fmt_method_name(method); + format!("static {return_ty} {method_name}({params})") + } + // Getter + } else if method.params.is_empty() + // Returns some value + && method.output.return_type().is_some() + // If it returns a bool it has be a `isFoo`, otherwise the bool might be a success flag of a side effect + && (return_ty != "bool" || method.name.as_str().starts_with("is")) + // Conversions are not getters according to the style guide + && !(method.name.as_str().starts_with("to") || method.name.as_str().starts_with("into")) + // Mutates + && !method.name.as_str().starts_with("enable") + // Clone and build are not getters according to the style guide, and next is usually not pure + && !["clone", "next", "build"].contains(&method.name.as_str()) + { + let method_name = self.formatter.fmt_method_name(method); + format!("{return_ty} get {method_name}",) + // Setter + } else if method.name.as_str().starts_with("set_") + && method.params.len() == 1 + && method.output.return_type().is_none() + // The corresponding getter exists, as required by the style guide + && self + .tcx + .resolve_type(id) + .methods() + .iter() + .any(|m| m.name.as_str() == method.name.as_str().strip_prefix("set_").unwrap()) + { + let method_name = self.formatter.fmt_setter_name(method); + format!("set {method_name}({params})") + } else if method.name.as_str() == "to_string" + && method.output.is_writeable() + && params.is_empty() + { + "@override\n String toString()".to_string() + } else if method.name.as_str() == "get" + && method.output.return_type().is_some() + && method.params.len() == 1 + { + format!("{return_ty} operator []({params})") + } else { + let method_name = self.formatter.fmt_method_name(method); + format!("{return_ty} {method_name}({params})") + }; + + let mut docs = self.formatter.fmt_docs(&method.docs); + + if let hir::ReturnType::Fallible(_, e) = &method.output { + write!( + &mut docs, + "\n///\n/// Throws [{}] on failure.", + &if let Some(e) = e { + self.gen_type_name(e) + } else { + "VoidError".into() + }, + ) + .unwrap(); + } + + Some(MethodInfo { + method, + docs, + declaration, + c_method_name, + param_types_ffi, + param_types_ffi_cast, + ffi_return_ty, + ffi_cast_return_ty, + dart_to_ffi_params, + dart_return_expression, + slice_conversions, + }) + } + + /// Generates Dart code for referencing a particular Dart type. /// - /// Will populate self.files as a result - pub fn run(&self) { - let mut directives = Default::default(); - let mut helper_classes = Default::default(); + /// This function adds the necessary type imports to the decl and impl files. + fn gen_type_name(&mut self, ty: &Type

) -> Cow<'cx, str> { + match *ty { + Type::Primitive(prim) => self.formatter.fmt_primitive_as_ffi(prim, true).into(), + Type::Opaque(ref op) => { + let op_id = op.tcx_id.into(); + let type_name = self.formatter.fmt_type_name(op_id); + + if self.tcx.resolve_type(op_id).attrs().disable { + self.errors + .push_error(format!("Found usage of disabled type {type_name}")) + } + let ret = if op.is_optional() { + self.formatter.fmt_nullable(&type_name) + } else { + type_name + }; + + ret.into_owned().into() + } + Type::Struct(ref st) => { + let id = P::id_for_path(st); + let type_name = self.formatter.fmt_type_name(id); + if self.tcx.resolve_type(id).attrs().disable { + self.errors + .push_error(format!("Found usage of disabled type {type_name}")) + } + type_name + } + Type::Enum(ref e) => { + let id = e.tcx_id.into(); + let type_name = self.formatter.fmt_type_name(id); + if self.tcx.resolve_type(id).attrs().disable { + self.errors + .push_error(format!("Found usage of disabled type {type_name}")) + } + type_name + } + Type::Slice(hir::Slice::Str(_lifetime)) => self.formatter.fmt_string().into(), + Type::Slice(hir::Slice::Primitive(_, p)) => { + self.imports + .insert(self.formatter.fmt_import("dart:typed_data")); + self.formatter.fmt_primitive_list_type(p).into() + } + _ => unreachable!("unknown AST/HIR variant"), + } + } + + /// Generates Dart code for referencing a particular FFI type with a given name. + fn gen_type_name_ffi(&mut self, ty: &Type

, cast: bool) -> Cow<'cx, str> { + match *ty { + Type::Primitive(prim) => self.formatter.fmt_primitive_as_ffi(prim, cast).into(), + Type::Opaque(ref op) => { + let op_id = op.tcx_id.into(); + let type_name = self.formatter.fmt_type_name(op_id); + if self.tcx.resolve_type(op_id).attrs().disable { + self.errors + .push_error(format!("Found usage of disabled type {type_name}")) + } + self.formatter + .fmt_pointer(self.formatter.fmt_opaque()) + .into() + } + Type::Struct(ref st) => { + let id = P::id_for_path(st); + let type_name = self.formatter.fmt_type_name(id); + if self.tcx.resolve_type(id).attrs().disable { + self.errors + .push_error(format!("Found usage of disabled type {type_name}")) + } + format!("_{type_name}Ffi").into() + } + Type::Enum(ref e) => { + let id = e.tcx_id.into(); + let type_name = self.formatter.fmt_type_name(id); + if self.tcx.resolve_type(id).attrs().disable { + self.errors + .push_error(format!("Found usage of disabled type {type_name}")) + } + self.formatter.fmt_enum_as_ffi(cast).into() + } + Type::Slice(hir::Slice::Str(_lifetime)) => self.formatter.fmt_utf8_primitive().into(), + Type::Slice(hir::Slice::Primitive(_, p)) => { + self.formatter.fmt_primitive_as_ffi(p, false).into() + } + _ => unreachable!("unknown AST/HIR variant"), + } + } + + fn gen_self_type_ffi(&self, ty: &SelfType, cast: bool) -> Cow<'cx, str> { + match ty { + SelfType::Opaque(_) => self + .formatter + .fmt_pointer(self.formatter.fmt_opaque()) + .into(), + SelfType::Struct(s) => format!("_{}Ffi", s.resolve(self.tcx).name.as_str()).into(), + SelfType::Enum(_) => self.formatter.fmt_enum_as_ffi(cast).into(), + _ => unreachable!("unknown AST/HIR variant"), + } + } + + /// Generates Dart code for referencing a particular FFI type. + /// + /// This function adds the necessary type imports to the decl and impl files. + + /// Generates a C++ expression that converts from the C++ self type to the corresponding C self type. + fn gen_dart_to_c_self(&self, ty: &SelfType) -> Cow<'static, str> { + match *ty { + SelfType::Enum(ref e) if is_contiguous_enum(e.resolve(self.tcx)) => "index".into(), + SelfType::Opaque(..) | SelfType::Struct(..) | SelfType::Enum(..) => { + "_underlying".into() + } + _ => unreachable!("unknown AST/HIR variant"), + } + } + + /// Generates one or two C++ expressions that convert from a C++ type to the corresponding C type. + /// + /// Returns `PartiallyNamedExpression`s whose `suffix` is either empty, `Data`, or `Size` for + /// referencing fields of the C struct. + fn gen_dart_to_c_for_type( + &mut self, + ty: &Type

, + dart_name: Cow<'cx, str>, + slice_conversions: &mut Vec>, + ) -> Cow<'cx, str> { + match *ty { + Type::Primitive(..) => dart_name.clone(), + Type::Opaque(ref op) if op.is_optional() => format!( + "{dart_name} == null ? ffi.Pointer.fromAddress(0) ? {dart_name}._underlying" + ) + .into(), + Type::Enum(ref e) if is_contiguous_enum(e.resolve(self.tcx)) => { + format!("{dart_name}.index").into() + } + Type::Opaque(..) | Type::Struct(..) | Type::Enum(..) => { + format!("{dart_name}._underlying").into() + } + Type::Slice(s) => { + let name = format!("{dart_name}Slice"); + slice_conversions.push( + format!( + "final {name} = {}._fromDart({dart_name}, alloc);", + &self.gen_slice(&s) + ) + .into(), + ); + name.into() + } + _ => unreachable!("unknown AST/HIR variant"), + } + } + + /// Generates the Dart type name of a return type. + fn gen_dart_return_type_name(&mut self, result_ty: &ReturnType) -> Cow<'cx, str> { + match *result_ty { + ReturnType::Infallible(None) => self.formatter.fmt_void().into(), + ReturnType::Infallible(Some(ref ty)) => match ty { + SuccessType::Writeable => self.formatter.fmt_string().into(), + SuccessType::OutType(o) => self.gen_type_name(o), + &_ => unreachable!("unknown AST/HIR variant"), + }, + ReturnType::Fallible(ref ok, _) => match ok { + Some(SuccessType::Writeable) => self.formatter.fmt_string().into(), + None => self.formatter.fmt_void().into(), + Some(SuccessType::OutType(o)) => self.gen_type_name(o), + &Some(_) => unreachable!("unknown AST/HIR variant"), + }, + } + } + + fn gen_slice(&mut self, slice: &hir::Slice) -> &'static str { + #[derive(askama::Template)] + #[template(path = "dart/slice.dart.jinja", escape = "none")] + struct SliceTemplate { + ffi_type: &'static str, + slice_ty: &'static str, + dart_ty: &'static str, + to_dart: &'static str, + from_dart: &'static str, + } + + self.imports.insert( + self.formatter + .fmt_renamed_import("package:ffi/ffi.dart", "ffi2"), + ); + + let dart_ty = match slice { + hir::Slice::Str(..) => self.formatter.fmt_string(), + hir::Slice::Primitive(_, p) => { + self.imports + .insert(self.formatter.fmt_import("dart:typed_data")); + self.formatter.fmt_primitive_list_type(*p) + } + _ => todo!("{slice:?}"), + }; + + let slice_ty = match slice { + hir::Slice::Str(..) => self.formatter.fmt_str_slice_type(), + hir::Slice::Primitive(_, p) => self.formatter.fmt_slice_type(*p), + _ => todo!("{slice:?}"), + }; + + let ffi_type = match slice { + hir::Slice::Str(..) => self.formatter.fmt_utf8_primitive(), + hir::Slice::Primitive(_, p) => self.formatter.fmt_primitive_as_ffi(*p, false), + _ => todo!("{slice:?}"), + }; + + let to_dart = match slice { + hir::Slice::Str(..) => { + self.imports + .insert(self.formatter.fmt_import("dart:convert")); + "Utf8Decoder().convert(_bytes.cast().asTypedList(_length))" + } + // TODO: How to read ffi.Size? + hir::Slice::Primitive(_, hir::PrimitiveType::IntSize(_)) => "this", + _ => "_bytes.asTypedList(_length)", + }; + + let from_dart = match slice { + hir::Slice::Str(..) => concat!( + "final units = Utf8Encoder().convert(value);\n", + "slice._length = units.length;\n", + // TODO: Figure out why Pointer cannot be allocated + "slice._bytes = allocator(slice._length).cast();\n", + "slice._bytes.cast().asTypedList(slice._length).setAll(0, units);" + ), + hir::Slice::Primitive(_, hir::PrimitiveType::IntSize(_)) => "", + _ => concat!( + "slice._length = value.length;\n", + "slice._bytes = allocator(slice._length);\n", + "slice._bytes.asTypedList(slice._length).setAll(0, value);" + ), + }; - for (id, ty) in self.tcx.all_types() { - if ty.attrs().disable { - continue; + self.helper_classes.insert( + slice_ty.into(), + SliceTemplate { + ffi_type, + slice_ty, + dart_ty, + to_dart, + from_dart, } + .render() + .unwrap(), + ); + + slice_ty + } + + /// Generates the Dart FFI type name of a return type. + fn gen_ffi_return_type_name(&mut self, result_ty: &ReturnType, cast: bool) -> Cow<'cx, str> { + match *result_ty { + ReturnType::Infallible(None) => if cast { + self.formatter.fmt_void() + } else { + self.formatter.fmt_ffi_void() + } + .into(), + ReturnType::Infallible(Some(ref ty)) => match ty { + SuccessType::Writeable => if cast { + self.formatter.fmt_void() + } else { + self.formatter.fmt_ffi_void() + } + .into(), + SuccessType::OutType(o) => { + if let hir::OutType::Slice(s) = o { + self.gen_slice(s).into() + } else { + self.gen_type_name_ffi(o, cast) + } + } + &_ => unreachable!("unknown AST/HIR variant"), + }, + ReturnType::Fallible(ref ok, ref err) => { + #[derive(askama::Template)] + #[template(path = "dart/result.dart.jinja", escape = "none")] + struct ResultTemplate { + name: String, + decls: Vec, + } + + let ok = match ok { + None | Some(SuccessType::Writeable) => None, + Some(SuccessType::OutType(o)) => Some(o), + &Some(_) => unreachable!("unknown AST/HIR variant"), + }; - self.gen_ty(id, &mut directives, &mut helper_classes); + let err = err.as_ref(); + + let name = format!( + "_Result{}{}", + &self + .formatter + .fmt_type_as_ident(ok.map(|o| self.gen_type_name_ffi(o, false)).as_deref()), + &self.formatter.fmt_type_as_ident( + err.map(|o| self.gen_type_name_ffi(o, false)).as_deref() + ) + ); + + let decls = [ok.map(|o| (o, "ok")), err.map(|o| (o, "err"))] + .into_iter() + .flatten() + .map(|(o, field_name)| { + format!( + "{}external {} {field_name};", + match o { + hir::OutType::Primitive(p) => { + format!( + "@{}()\n", + self.formatter.fmt_primitive_as_ffi(*p, false) + ) + } + hir::OutType::Enum(_) => + format!("@{}()\n", self.formatter.fmt_enum_as_ffi(false)), + _ => String::new(), + }, + { self.gen_type_name_ffi(o, true) } + ) + }) + .collect(); + + self.helper_classes.insert( + name.clone(), + ResultTemplate { + name: name.clone(), + decls, + } + .render() + .unwrap(), + ); + + name.into() + } } + } + + /// Generates a C++ expression that converts from a C type to the corresponding C++ type. + /// + /// If the type is a slice, this function assumes that `{var_name}_data` and `{var_name}_size` resolve + /// to valid expressions referencing the two different C variables for the pointer and the length. + fn gen_c_to_dart_for_type( + &mut self, + ty: &Type

, + var_name: Cow<'cx, str>, + ) -> Cow<'cx, str> { + match *ty { + Type::Primitive(..) => var_name, + Type::Opaque(ref op) => { + let id = op.tcx_id.into(); + let type_name = self.formatter.fmt_type_name(id); - self.gen_root(directives, helper_classes); + match (op.owner.is_owned(), op.is_optional()) { + (false, _) => unimplemented!(), + (true, false) => format!("{type_name}._({var_name})").into(), + (true, true) => { + format!("{var_name}.address == 0 ? null : {type_name}._({var_name})").into() + } + } + } + Type::Struct(ref st) => { + let id = P::id_for_path(st); + let type_name = self.formatter.fmt_type_name(id); + format!("{type_name}._({var_name})").into() + } + Type::Enum(ref e) if is_contiguous_enum(e.resolve(self.tcx)) => { + let id = e.tcx_id.into(); + let type_name = self.formatter.fmt_type_name(id); + format!("{type_name}.values[{var_name}]").into() + } + Type::Enum(ref e) => { + let id = e.tcx_id.into(); + let type_name = self.formatter.fmt_type_name(id); + format!("{type_name}.values.firstWhere((v) => v._underlying == {var_name})").into() + } + Type::Slice(..) => format!("{var_name}._asDart").into(), + _ => unreachable!("unknown AST/HIR variant"), + } + } + + /// Generates a C++ expression that converts from a C return type to the corresponding C++ return type. + /// + /// If the type is `Writeable`, this function assumes that there is a variable named `writeable` in scope. + fn gen_c_to_dart_for_return_type( + &mut self, + result_ty: &ReturnType, + var_name: Cow<'cx, str>, + ) -> Option> { + match *result_ty { + ReturnType::Infallible(None) => None, + ReturnType::Infallible(Some(SuccessType::Writeable)) => { + Some("return writeable.finalize();".into()) + } + ReturnType::Infallible(Some(SuccessType::OutType(ref out_ty))) => { + Some(format!("return {};", self.gen_c_to_dart_for_type(out_ty, var_name)).into()) + } + ReturnType::Fallible(ref ok, ref err) => { + let ok_path = format!("{var_name}.union.ok"); + let err_path = format!("{var_name}.union.err"); + let err_conversion = match err { + Some(o) => self.gen_c_to_dart_for_type(o, err_path.into()), + None => { + self.helper_classes.insert( + "voiderror".into(), + "/// An unspecified error value\nclass VoidError {}".into(), + ); + "VoidError()".into() + } + }; + let err_check = + format!("if (!{var_name}.isOk) {{\n throw {err_conversion};\n}}").into(); + let ok_conversion = match ok { + // Note: the `writeable` variable is a string initialized in the template + Some(SuccessType::Writeable) => "writeable.finalize()".into(), + Some(SuccessType::OutType(o)) => self.gen_c_to_dart_for_type(o, ok_path.into()), + None => return Some(err_check), + &Some(_) => unreachable!("unknown AST/HIR variant"), + }; + Some(format!("{err_check}\nreturn {ok_conversion};").into()) + } + ReturnType::Infallible(Some(_)) => unreachable!("unknown AST/HIR variant"), + } } } + +fn is_contiguous_enum(ty: &hir::EnumDef) -> bool { + ty.variants + .iter() + .enumerate() + .all(|(i, v)| i as isize == v.discriminant) +} + +/// Everything needed for rendering a method. +struct MethodInfo<'a> { + /// HIR of the method being rendered + method: &'a hir::Method, + /// + docs: String, + /// The declaration (everything before the parameter list) + declaration: String, + /// The C method name + c_method_name: Cow<'a, str>, + + param_types_ffi: Vec>, + param_types_ffi_cast: Vec>, + ffi_return_ty: Cow<'a, str>, + ffi_cast_return_ty: Cow<'a, str>, + + slice_conversions: Vec>, + + /// Dart conversion code for each parameter of the C function + dart_to_ffi_params: Vec>, + /// If the function has a return value, the Dart code for the conversion. Assumes that + /// the C function return value is saved to a variable named `result` or that the + /// writeable, if present, is saved to a variable named `writeable`. + dart_return_expression: Option>, +} + +#[derive(PartialEq, Ord, PartialOrd, Clone, Eq, Debug)] +struct ResultClass { + ok_name: String, + err_name: String, + ok_decl: Option, + err_decl: Option, +} diff --git a/tool/src/lib.rs b/tool/src/lib.rs index 0c9d99a98..d9e50f6d5 100644 --- a/tool/src/lib.rs +++ b/tool/src/lib.rs @@ -95,10 +95,16 @@ pub fn gen( std::process::exit(1); } }; - let files = common::FileMap::default(); - let mut context = dart::DartContext::new(&tcx, files, docs_url_gen, strip_prefix); - context.run(); - out_texts = context.files.take_files(); + match dart::run(&tcx, docs_url_gen, strip_prefix) { + Ok(mut files) => out_texts = files.take_files(), + Err(errors) => { + eprintln!("Found errors whilst generating {target_language}:"); + for error in errors { + eprintln!("\t{}: {}", error.0, error.1); + } + errors_found = true; + } + }; } "c" => c::gen_bindings(&env, &mut out_texts).unwrap(), "cpp" => { @@ -198,24 +204,6 @@ pub fn gen( } } - if target_language == "dart" { - if !silent { - print!("{}", "Trying to run `dart format` ... ".green().bold()); - } - let _ = std::io::stdout().flush(); - if std::process::Command::new("dart") - .args([std::ffi::OsStr::new("format"), out_folder.as_os_str()]) - .output() - .is_ok() - { - if !silent { - println!("{}", "success".green().bold()); - } - } else if !silent { - println!("{}", "failure".red().bold()); - } - } - if let Some(docs_out_folder) = docs_out_folder { if !silent { println!( diff --git a/tool/templates/dart/base.dart.jinja b/tool/templates/dart/base.dart.jinja index 698abc0cb..9ef3ce879 100644 --- a/tool/templates/dart/base.dart.jinja +++ b/tool/templates/dart/base.dart.jinja @@ -5,11 +5,13 @@ {% for directive in directives -%} {{directive}} -{% endfor %} +{% endfor -%} + {{ body }} -{% for helper_class in helper_classes.values() -%} +{%- for helper_class in helper_classes.values() %} {{helper_class}} -{% endfor %} +{%- endfor %} + diff --git a/tool/templates/dart/enum.dart.jinja b/tool/templates/dart/enum.dart.jinja index daf640b58..11a8d267f 100644 --- a/tool/templates/dart/enum.dart.jinja +++ b/tool/templates/dart/enum.dart.jinja @@ -4,25 +4,24 @@ enum {{type_name}} { {%- for enum_variant in ty.variants %} {% if !enum_variant.docs.is_empty() -%} - /// {{fmt.fmt_docs(enum_variant.docs) }} + /// {{fmt.fmt_docs(enum_variant.docs).replace('\n', "\n ") }} {% endif -%} - {{fmt.fmt_enum_variant(enum_variant)}}{% if loop.last %};{% else %},{% endif %} + {{fmt.fmt_enum_variant(enum_variant)}}{% if loop.last %};{% else %}, +{% endif %} {%- endfor %} - {%- if !is_contiguous %} int get _underlying { switch (this) { {%- for enum_variant in ty.variants %} - case {{fmt.fmt_enum_variant(enum_variant)}}: - return {{ enum_variant.discriminant }}; + case {{fmt.fmt_enum_variant(enum_variant)}}: + return {{ enum_variant.discriminant }}; {%- endfor %} } } - {% endif -%} - -{%- for m in methods %} + {%- endif %} + {%- for m in methods %} {% include "method.dart.jinja" %} -{% endfor %} + {%-endfor %} } diff --git a/tool/templates/dart/init.dart b/tool/templates/dart/init.dart index b7870ab35..e4e4cd88b 100644 --- a/tool/templates/dart/init.dart +++ b/tool/templates/dart/init.dart @@ -1,3 +1,4 @@ + late final ffi.Pointer Function(String) _capi; void init(String path) => _capi = ffi.DynamicLibrary.open(path).lookup; diff --git a/tool/templates/dart/method.dart.jinja b/tool/templates/dart/method.dart.jinja index e70774a4a..f72577fc4 100644 --- a/tool/templates/dart/method.dart.jinja +++ b/tool/templates/dart/method.dart.jinja @@ -1,47 +1,48 @@ -{%- if !m.docs.is_empty() %} -/// {{m.docs}} -{%- endif %} -{{ m.declaration -}} -{%- if !m.declaration.starts_with("static final") -%} -{##} { {##} - {%- for slice_conversion in m.slice_conversions %} - {%- if loop.first %} - final alloc = ffi2.Arena(); - {%- endif %} - {{ slice_conversion }} - {%- endfor %} - {% if m.method.is_writeable() %} - final writeable = _Writeable(); - {%- endif %} - {% if m.method.output.returns_value() -%} - final result = {##} - {%- endif -%} - _{{ m.c_method_name -}}( - {%- for param in m.dart_to_ffi_params %} - {%- if !loop.first %},{% endif -%} - {{ param }} - {%- endfor -%} - ); - {%- if !m.slice_conversions.is_empty() -%} - alloc.releaseAll(); - {%- endif %} - {%- match m.dart_return_expression %} - {%- when Some with (statement) %} - {{statement}} - {%- when None %} - {%- endmatch %} + {%- if !m.docs.is_empty() %} + /// {{m.docs.replace('\n', "\n ")}} + {%- endif %} + {{ m.declaration -}} + {%- if !m.declaration.starts_with("static final") %} { + {%- for slice_conversion in m.slice_conversions %} + {%- if loop.first %} + final alloc = ffi2.Arena(); + {%- endif %} + {{ slice_conversion }} + {%- endfor %} + {%- if m.method.is_writeable() %} + final writeable = _Writeable(); + {%- endif %} + {%- if m.method.output.returns_value() %} + final result = {% else %} + {% endif -%} + _{{ m.c_method_name -}}( + {%- for param in m.dart_to_ffi_params %} + {%- if loop.first %}{% else %}, {% endif -%} + {{ param }} + {%- endfor -%} + ); + {%- if !m.slice_conversions.is_empty() %} + alloc.releaseAll(); + {%- endif %} + {%- match m.dart_return_expression %} + {%- when Some with (statement) %} + {{statement.replace('\n', "\n ")}} + {%- when None %} + {%- endmatch %} } + // ignore: non_constant_identifier_names - static final _{{ m.c_method_name -}} = _capi>('{{ m.c_method_name }}') - .asFunction<{{ m.ffi_cast_return_ty }} Function( - {%- for param in m.param_types_ffi_cast %} - {%- if !loop.first %}, {% endif -%} - {{ param }} - {%- endfor -%} - )>(isLeaf: true); -{% endif %} \ No newline at end of file + static final _{{ m.c_method_name }} = + _capi>('{{ m.c_method_name }}') + .asFunction<{{ m.ffi_cast_return_ty }} Function( + {%- for param in m.param_types_ffi_cast %} + {%- if !loop.first %}, {% endif -%} + {{ param }} + {%- endfor -%} + )>(isLeaf: true); +{%- endif %} \ No newline at end of file diff --git a/tool/templates/dart/opaque.dart.jinja b/tool/templates/dart/opaque.dart.jinja index 630bdd9c7..07b34f12c 100644 --- a/tool/templates/dart/opaque.dart.jinja +++ b/tool/templates/dart/opaque.dart.jinja @@ -1,18 +1,16 @@ {%- if !docs.is_empty() %} /// {{docs}} {%- endif %} -class {{type_name}} implements ffi.Finalizable { +final class {{type_name}} implements ffi.Finalizable { + final ffi.Pointer _underlying; - final ffi.Pointer _underlying; + {{type_name}}._(this._underlying) { + _finalizer.attach(this, _underlying.cast()); + } - {{type_name}}._(this._underlying) { - _finalizer.attach(this, _underlying.cast()); - } + static final _finalizer = ffi.NativeFinalizer(_capi('{{destructor}}')); - static final _finalizer = ffi.NativeFinalizer(_capi('{{destructor}}')); - - {% for m in methods -%} - {% include "method.dart.jinja" %} - - {% endfor -%} + {%- for m in methods %} +{% include "method.dart.jinja" %} + {%- endfor %} } diff --git a/tool/templates/dart/result.dart.jinja b/tool/templates/dart/result.dart.jinja index 1e5661456..623084cd5 100644 --- a/tool/templates/dart/result.dart.jinja +++ b/tool/templates/dart/result.dart.jinja @@ -1,16 +1,20 @@ -{%- if !decls.is_empty() -%} -class {{name}}Union extends ffi.Union { - {%- for decl in decls %} - {{decl}} - {%- endfor %} +{% if !decls.is_empty() -%} +final class {{name}}Union extends ffi.Union { + {% for decl in decls -%} + {% if !loop.first %} + + {% endif -%} + {{decl.replace('\n', "\n ")}} + {%- endfor %} } + {% endif -%} -class {{name}} extends ffi.Struct { - {% if !decls.is_empty() -%} - external {{name}}Union union; - {%- endif %} +final class {{name}} extends ffi.Struct { + {% if !decls.is_empty() -%} + external {{name}}Union union; + {%- endif %} - @ffi.Bool() - external bool isOk; + @ffi.Bool() + external bool isOk; } diff --git a/tool/templates/dart/slice.dart.jinja b/tool/templates/dart/slice.dart.jinja index 5886e84f2..6cf779d68 100644 --- a/tool/templates/dart/slice.dart.jinja +++ b/tool/templates/dart/slice.dart.jinja @@ -1,20 +1,21 @@ -class {{slice_ty}} extends ffi.Struct { +final class {{slice_ty}} extends ffi.Struct { external ffi.Pointer<{{ffi_type}}> _bytes; @ffi.Size() external int _length; - {%- if !from_dart.is_empty() %} + {% if !from_dart.is_empty() -%} /// Produces a slice from a Dart object. The Dart object's data is copied into the given allocator /// as it cannot be borrowed directly, and gets freed with the slice object. // ignore: unused_element static {{slice_ty}} _fromDart({{dart_ty}} value, ffi.Allocator allocator) { final pointer = allocator<{{slice_ty}}>(); - final slice = pointer.ref; - {{from_dart}} + final slice = pointer.ref; + {{from_dart.replace("\n", "\n ")}} return slice; } - {%- endif %} + + {% endif -%} // ignore: unused_element {{dart_ty}} get _asDart => {{to_dart}}; @@ -29,9 +30,9 @@ class {{slice_ty}} extends ffi.Struct { for (var i = 0; i < _length; i++) { {%- if ffi_type == "ffi2.Utf8" %} if (other._bytes.cast()[i] != _bytes.cast()[i]) { - {%- else -%} + {%- else %} if (other._bytes[i] != _bytes[i]) { - {% endif -%} + {%- endif %} return false; } } @@ -42,4 +43,3 @@ class {{slice_ty}} extends ffi.Struct { @override int get hashCode => _length.hashCode; } - diff --git a/tool/templates/dart/struct.dart.jinja b/tool/templates/dart/struct.dart.jinja index 936343401..7ff68cabe 100644 --- a/tool/templates/dart/struct.dart.jinja +++ b/tool/templates/dart/struct.dart.jinja @@ -1,57 +1,61 @@ {%- if !docs.is_empty() %} /// {{docs}} {%- endif %} -class _{{type_name}}Ffi extends ffi.Struct { - {%- for field in fields %} - {%- match field.annotation %} - {%- when Some with (annotation) %} - @{{annotation}}() - {%- when None %} - {%- endmatch %} - external {{field.ffi_cast_type_name}} {{field.name}}; - {%- endfor %} +final class _{{type_name}}Ffi extends ffi.Struct { + {%- for field in fields %} + {%- match field.annotation %} + {%- when Some with (annotation) %} + @{{annotation}}() + {%- when None %} + {%- endmatch %} + external {{field.ffi_cast_type_name}} {{field.name}}; + {%- endfor %} } -class {{type_name}} { - final _{{type_name}}Ffi _underlying; - - // ignore: unused_element - {{type_name}}._(this._underlying); - - factory {{type_name}}() { - final pointer = ffi2.calloc<_{{type_name}}Ffi>(); - final result = {{type_name}}._(pointer.ref); - _callocFree.attach(result, pointer.cast()); - return result; - } - - {% for field in fields -%} - {{field.dart_type_name}} get {{field.name}} => {{ field.get_expression }}; - set {{field.name}}({{field.dart_type_name}} {{field.name}}) { - {%- if !field.set_slice_conversions.is_empty() %} - final alloc = ffi2.calloc; - alloc.free(_underlying.{{field.name}}._bytes); - {# TODO: What if the field is a struct containing a pointer? #} - {%- endif %} - {%- for conversion in field.set_slice_conversions -%} - {{ conversion }} - {%- endfor %} - _underlying.{{field.name}} = {{field.set_expression}}; - } - - {%~ endfor %} - {%- for m in methods -%} - {%- include "method.dart.jinja" %} - - {%- endfor %} - - @override - bool operator ==(Object other) => - other is {{type_name}} - {%- for field in fields %} - && other._underlying.{{field.name}} == _underlying.{{field.name}} - {%- endfor %}; - - @override - int get hashCode => Object.hashAll([{% for field in fields %}_underlying.{{field.name}},{% endfor %}]); +final class {{type_name}} { + final _{{type_name}}Ffi _underlying; + + // ignore: unused_element + {{type_name}}._(this._underlying); + + factory {{type_name}}() { + final pointer = ffi2.calloc<_{{type_name}}Ffi>(); + final result = {{type_name}}._(pointer.ref); + _callocFree.attach(result, pointer.cast()); + return result; + } + + {%- for field in fields %} + + {{field.dart_type_name}} get {{field.name}} => {{ field.get_expression }}; + set {{field.name}}({{field.dart_type_name}} {{field.name}}) { + {%- if !field.set_slice_conversions.is_empty() %} + final alloc = ffi2.calloc; + alloc.free(_underlying.{{field.name}}._bytes); + {# TODO: What if the field is a struct containing a pointer? #} + {%- endif %} + {%- for conversion in field.set_slice_conversions -%} + {{ conversion }} + {%- endfor %} + _underlying.{{field.name}} = {{field.set_expression}}; + } + {%- endfor %} + + {%- for m in methods %} +{% include "method.dart.jinja" %} + {%- endfor %} + + @override + bool operator ==(Object other) => + other is {{type_name}} + {%- for field in fields %} && + other._underlying.{{field.name}} == _underlying.{{field.name}} + {%- endfor %}; + + @override + int get hashCode => Object.hashAll([ + {%- for field in fields %} + _underlying.{{field.name}}, + {%- endfor %} + ]); } diff --git a/tool/templates/dart/writeable.dart b/tool/templates/dart/writeable.dart index cb0349252..1e4e0701a 100644 --- a/tool/templates/dart/writeable.dart +++ b/tool/templates/dart/writeable.dart @@ -1,28 +1,24 @@ -class _Writeable { +final class _Writeable { final ffi.Pointer _underlying; _Writeable() : _underlying = _create(0); static final _create = - _capi Function(ffi.Size)>>( - 'diplomat_buffer_writeable_create') - .asFunction Function(int)>(); + _capi Function(ffi.Size)>>('diplomat_buffer_writeable_create') + .asFunction Function(int)>(); String finalize() { final string = _getBytes(_underlying).toDartString(length: _len(_underlying)); _destroy(_underlying); return string; } - static final _len = - _capi)>>( - 'diplomat_buffer_writeable_len') - .asFunction)>(isLeaf: true); - static final _getBytes = _capi< - ffi.NativeFunction< - ffi.Pointer Function(ffi.Pointer)>>( - 'diplomat_buffer_writeable_get_bytes') - .asFunction Function(ffi.Pointer)>(isLeaf: true); + static final _len = + _capi)>>('diplomat_buffer_writeable_len') + .asFunction)>(isLeaf: true); + + static final _getBytes = + _capi Function(ffi.Pointer)>>('diplomat_buffer_writeable_get_bytes') + .asFunction Function(ffi.Pointer)>(isLeaf: true); static final _destroy = - _capi)>>( - 'diplomat_buffer_writeable_destroy') - .asFunction)>(isLeaf: true); -} + _capi)>>('diplomat_buffer_writeable_destroy') + .asFunction)>(isLeaf: true); +} \ No newline at end of file