diff --git a/example/dart/lib/lib.g.dart b/example/dart/lib/lib.g.dart index e838640d1..7c9c41147 100644 --- a/example/dart/lib/lib.g.dart +++ b/example/dart/lib/lib.g.dart @@ -14,6 +14,23 @@ part 'ICU4XFixedDecimalFormatterOptions.g.dart'; part 'ICU4XFixedDecimalGroupingStrategy.g.dart'; part 'ICU4XLocale.g.dart'; +/// A [Rune] is a Unicode code point, such as `a`, or `💡`. +/// +/// The recommended way to obtain a [Rune] is to create it from a +/// [String], which is conceptually a list of [Runes]. For example, +/// `'a'.runes.first` is equal to the [Rune] `a`. +/// +/// Dart does not have a character/rune literal, so integer literals +/// need to be used. For example the Unicode code point U+1F4A1, `💡`, +/// can be represented by `0x1F4A1`. Note that only values in the ranges +/// `0x0..0xD7FF` and `0xE000..0x10FFFF` (both inclusive) are Unicode +/// code points, and hence valid [Rune]s. +/// +/// A [String] can be constructed from a [Rune] using [String.fromCharCode]. +typedef Rune = int; +/// A list of [Rune]s. +typedef RuneList = Uint32List; + late final ffi.Pointer Function(String) _capi; void init(String path) => _capi = ffi.DynamicLibrary.open(path).lookup; diff --git a/feature_tests/dart/lib/MyStruct.g.dart b/feature_tests/dart/lib/MyStruct.g.dart index 975bfd221..40669bd5a 100644 --- a/feature_tests/dart/lib/MyStruct.g.dart +++ b/feature_tests/dart/lib/MyStruct.g.dart @@ -17,7 +17,7 @@ final class _MyStructFfi extends ffi.Struct { @ffi.Int32() external int e; @ffi.Uint32() - external int f; + external Rune f; @ffi.Int32() external int g; } @@ -60,8 +60,8 @@ final class MyStruct { _underlying.e = e; } - int get f => _underlying.f; - set f(int f) { + Rune get f => _underlying.f; + set f(Rune f) { _underlying.f = f; } diff --git a/feature_tests/dart/lib/OptionOpaqueChar.g.dart b/feature_tests/dart/lib/OptionOpaqueChar.g.dart index d097777f8..e2db8de8c 100644 --- a/feature_tests/dart/lib/OptionOpaqueChar.g.dart +++ b/feature_tests/dart/lib/OptionOpaqueChar.g.dart @@ -14,12 +14,12 @@ final class OptionOpaqueChar implements ffi.Finalizable { static final _finalizer = ffi.NativeFinalizer(_capi('OptionOpaqueChar_destroy')); - void assertChar(int ch) { + void assertChar(Rune ch) { _OptionOpaqueChar_assert_char(_underlying, ch); } // ignore: non_constant_identifier_names static final _OptionOpaqueChar_assert_char = _capi, ffi.Uint32)>>('OptionOpaqueChar_assert_char') - .asFunction, int)>(isLeaf: true); + .asFunction, Rune)>(isLeaf: true); } diff --git a/feature_tests/dart/lib/lib.g.dart b/feature_tests/dart/lib/lib.g.dart index b2174046b..606270c5f 100644 --- a/feature_tests/dart/lib/lib.g.dart +++ b/feature_tests/dart/lib/lib.g.dart @@ -33,6 +33,23 @@ part 'ResultOpaque.g.dart'; part 'Two.g.dart'; part 'UnimportedEnum.g.dart'; +/// A [Rune] is a Unicode code point, such as `a`, or `💡`. +/// +/// The recommended way to obtain a [Rune] is to create it from a +/// [String], which is conceptually a list of [Runes]. For example, +/// `'a'.runes.first` is equal to the [Rune] `a`. +/// +/// Dart does not have a character/rune literal, so integer literals +/// need to be used. For example the Unicode code point U+1F4A1, `💡`, +/// can be represented by `0x1F4A1`. Note that only values in the ranges +/// `0x0..0xD7FF` and `0xE000..0x10FFFF` (both inclusive) are Unicode +/// code points, and hence valid [Rune]s. +/// +/// A [String] can be constructed from a [Rune] using [String.fromCharCode]. +typedef Rune = int; +/// A list of [Rune]s. +typedef RuneList = Uint32List; + late final ffi.Pointer Function(String) _capi; void init(String path) => _capi = ffi.DynamicLibrary.open(path).lookup; diff --git a/tool/src/dart/formatter.rs b/tool/src/dart/formatter.rs index ab21974ec..832e3467b 100644 --- a/tool/src/dart/formatter.rs +++ b/tool/src/dart/formatter.rs @@ -210,7 +210,7 @@ impl<'tcx> DartFormatter<'tcx> { if cast { match prim { PrimitiveType::Bool => "bool", - PrimitiveType::Char => "int", + PrimitiveType::Char => "Rune", PrimitiveType::Int(_) | PrimitiveType::IntSize(_) => "int", PrimitiveType::Int128(_) => panic!("i128 not supported in Dart"), PrimitiveType::Float(_) => "double", @@ -240,7 +240,7 @@ impl<'tcx> DartFormatter<'tcx> { pub fn fmt_primitive_list_type(&self, prim: hir::PrimitiveType) -> &'static str { use diplomat_core::hir::{FloatType, IntType, PrimitiveType}; match prim { - PrimitiveType::Char => "Uint32List", + PrimitiveType::Char => "RuneList", PrimitiveType::Int(IntType::I8) => "Int8List", PrimitiveType::Int(IntType::U8) => "Uint8List", PrimitiveType::Int(IntType::I16) => "Int16List", @@ -260,7 +260,7 @@ impl<'tcx> DartFormatter<'tcx> { pub fn fmt_slice_type(&self, prim: hir::PrimitiveType) -> &'static str { use diplomat_core::hir::{FloatType, IntType, PrimitiveType}; match prim { - PrimitiveType::Char => "_SliceFfiUint32", + PrimitiveType::Char => "_SliceRune", PrimitiveType::Int(IntType::I8) => "_SliceFfiInt8", PrimitiveType::Int(IntType::U8) => "_SliceFfiUint8", PrimitiveType::Int(IntType::I16) => "_SliceFfiInt16", diff --git a/tool/src/dart/mod.rs b/tool/src/dart/mod.rs index 207b2c2cf..4d64070ef 100644 --- a/tool/src/dart/mod.rs +++ b/tool/src/dart/mod.rs @@ -51,6 +51,7 @@ pub fn run<'cx>( } directives.insert(formatter.fmt_renamed_import("dart:ffi", "ffi")); + directives.insert(formatter.fmt_import("dart:typed_data")); directives.insert(formatter.fmt_renamed_import("package:ffi/ffi.dart", "ffi2")); files.add_file( formatter.fmt_file_name("lib"), diff --git a/tool/templates/dart/init.dart b/tool/templates/dart/init.dart index e4e4cd88b..ddd1b84c6 100644 --- a/tool/templates/dart/init.dart +++ b/tool/templates/dart/init.dart @@ -1,4 +1,21 @@ +/// A [Rune] is a Unicode code point, such as `a`, or `💡`. +/// +/// The recommended way to obtain a [Rune] is to create it from a +/// [String], which is conceptually a list of [Runes]. For example, +/// `'a'.runes.first` is equal to the [Rune] `a`. +/// +/// Dart does not have a character/rune literal, so integer literals +/// need to be used. For example the Unicode code point U+1F4A1, `💡`, +/// can be represented by `0x1F4A1`. Note that only values in the ranges +/// `0x0..0xD7FF` and `0xE000..0x10FFFF` (both inclusive) are Unicode +/// code points, and hence valid [Rune]s. +/// +/// A [String] can be constructed from a [Rune] using [String.fromCharCode]. +typedef Rune = int; +/// A list of [Rune]s. +typedef RuneList = Uint32List; + late final ffi.Pointer Function(String) _capi; void init(String path) => _capi = ffi.DynamicLibrary.open(path).lookup;