From 5724c2356c271ec622be0fd37040e4d7ed2cdce0 Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 24 Jul 2024 16:58:32 +0200 Subject: [PATCH 01/26] Squashed commit: Verify using hashes --- .github/workflows/intl4x.yml | 35 +++- .github/workflows/intl4x_artifacts.yml | 75 ++++++++ pkgs/intl4x/CHANGELOG.md | 3 +- pkgs/intl4x/hook/README.md | 14 ++ pkgs/intl4x/hook/build.dart | 63 +++---- pkgs/intl4x/hook/hashes.dart | 45 +++++ pkgs/intl4x/hook/version.dart | 5 + pkgs/intl4x/lib/src/bindings/Bidi.g.dart | 8 +- .../lib/src/bindings/CodePointMapData8.g.dart | 19 ++ .../lib/src/bindings/CustomTimeZone.g.dart | 35 +++- pkgs/intl4x/lib/src/bindings/Date.g.dart | 14 ++ pkgs/intl4x/lib/src/bindings/DateTime.g.dart | 14 ++ pkgs/intl4x/lib/src/bindings/Error.g.dart | 14 +- .../GeneralCategoryNameToMaskMapper.g.dart | 4 +- pkgs/intl4x/lib/src/bindings/IsoDate.g.dart | 14 ++ .../lib/src/bindings/IsoDateTime.g.dart | 14 ++ .../lib/src/bindings/MeasureUnit.g.dart | 36 ++++ .../lib/src/bindings/MeasureUnitParser.g.dart | 64 +++++++ .../PropertyValueNameToEnumMapper.g.dart | 42 ++++- .../lib/src/bindings/TimeZoneIdMapper.g.dart | 167 ++++++++++++++++++ ...oneIdMapperWithFastCanonicalization.g.dart | 127 +++++++++++++ .../lib/src/bindings/UnitsConverter.g.dart | 67 +++++++ .../src/bindings/UnitsConverterFactory.g.dart | 94 ++++++++++ pkgs/intl4x/lib/src/bindings/lib.g.dart | 6 + pkgs/intl4x/pubspec.yaml | 3 +- pkgs/intl4x/tool/generate_hashes.dart | 105 +++++++++++ 26 files changed, 1029 insertions(+), 58 deletions(-) create mode 100644 pkgs/intl4x/hook/README.md create mode 100644 pkgs/intl4x/hook/hashes.dart create mode 100644 pkgs/intl4x/hook/version.dart create mode 100644 pkgs/intl4x/lib/src/bindings/MeasureUnit.g.dart create mode 100644 pkgs/intl4x/lib/src/bindings/MeasureUnitParser.g.dart create mode 100644 pkgs/intl4x/lib/src/bindings/TimeZoneIdMapper.g.dart create mode 100644 pkgs/intl4x/lib/src/bindings/TimeZoneIdMapperWithFastCanonicalization.g.dart create mode 100644 pkgs/intl4x/lib/src/bindings/UnitsConverter.g.dart create mode 100644 pkgs/intl4x/lib/src/bindings/UnitsConverterFactory.g.dart create mode 100644 pkgs/intl4x/tool/generate_hashes.dart diff --git a/.github/workflows/intl4x.yml b/.github/workflows/intl4x.yml index 9987cc57..2aa00140 100644 --- a/.github/workflows/intl4x.yml +++ b/.github/workflows/intl4x.yml @@ -17,7 +17,7 @@ on: jobs: build: - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} env: ICU4X_BUILD_MODE: checkout @@ -29,6 +29,7 @@ jobs: strategy: matrix: sdk: [stable, dev] # {pkgs.versions} + os: [ubuntu-latest, windows-latest, macos-latest] include: - sdk: dev run-tests: true @@ -45,6 +46,11 @@ jobs: - run: dart --enable-experiment=native-assets analyze --fatal-infos + - run: | + dart --enable-experiment=native-assets tool/generate_hashes.dart + git diff --name-only --exit-code + if: ${{matrix.sdk == 'dev' && matrix.os == 'ubuntu-latest'}} + - run: dart --enable-experiment=native-assets format --output=none --set-exit-if-changed . if: ${{matrix.run-tests}} @@ -53,3 +59,30 @@ jobs: - run: dart --enable-experiment=native-assets test -p chrome if: ${{matrix.run-tests}} + + build_fetch: + runs-on: ${{ matrix.os }} + + env: + ICU4X_BUILD_MODE: fetch + + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + + defaults: + run: + working-directory: pkgs/intl4x + + steps: + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + with: + submodules: true + + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + with: + sdk: dev + + - run: dart --enable-experiment=native-assets pub get + + - run: dart --enable-experiment=native-assets test diff --git a/.github/workflows/intl4x_artifacts.yml b/.github/workflows/intl4x_artifacts.yml index 4cecc7ab..8d28bdef 100644 --- a/.github/workflows/intl4x_artifacts.yml +++ b/.github/workflows/intl4x_artifacts.yml @@ -4,6 +4,10 @@ permissions: contents: write on: + pull_request: + branches: [ main ] + paths: + - pkgs/intl4x/hook/hashes.dart push: tags: - 'intl4x-icu*' @@ -140,7 +144,78 @@ jobs: with: name: dart-${{matrix.os}}-libs path: submodules/icu4x/bin + + check_hashes: + needs: dart-libs + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + with: + sdk: dev + + - name: Download binaries + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e + with: + merge-multiple: true + + - name: Display structure of downloaded files + run: ls -R + + - name: Check hashes against recomputed ones + run: | + cd pkgs/intl4x + dart pub get + dart --enable-experiment=native-assets tool/generate_hashes.dart local ../.. + git diff --exit-code + build_local: + needs: dart-libs + runs-on: ${{ matrix.os }} + + env: + ICU4X_BUILD_MODE: local + + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + + steps: + - name: Download binaries + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e + with: + merge-multiple: true + + - run: echo "LOCAL_ICU4X_BINARY=$(realpath linux_x64)" >> $GITHUB_ENV + if: matrix.os == 'ubuntu-latest' + + - run: echo "LOCAL_ICU4X_BINARY=$(realpath macos_x64)" >> $GITHUB_ENV + if: matrix.os == 'macos-latest' + + - run: echo "LOCAL_ICU4X_BINARY=$(realpath windows_x64)" >> $GITHUB_ENV + if: matrix.os == 'windows-latest' + + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + with: + submodules: true + + - name: Display structure of downloaded files + run: ls -R + + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + with: + sdk: dev + + - run: | + cd pkgs/intl4x + dart pub get + + - run: | + cd pkgs/intl4x + dart --enable-experiment=native-assets test + release: needs: dart-libs runs-on: ubuntu-latest diff --git a/pkgs/intl4x/CHANGELOG.md b/pkgs/intl4x/CHANGELOG.md index 64b06e3d..3b605e58 100644 --- a/pkgs/intl4x/CHANGELOG.md +++ b/pkgs/intl4x/CHANGELOG.md @@ -1,10 +1,11 @@ ## 0.9.2-wip - Copy files instead of symlinking, for easier upgrading. +- Get binaries from Github and check their hashes. ## 0.9.1 -- Small fixes in imports +- Small fixes in imports. ## 0.9.0 diff --git a/pkgs/intl4x/hook/README.md b/pkgs/intl4x/hook/README.md new file mode 100644 index 00000000..ac175130 --- /dev/null +++ b/pkgs/intl4x/hook/README.md @@ -0,0 +1,14 @@ +### How to update the ICU4X version used in package:intl4x. + +#### First PR +1. Create PR. +2. Update `submodules/icu4x` to whatever branch/hash you want. +3. Land PR. +4. Tag with `intl4x-icu*`, push. This creates new release with the new binaries. + +#### Second PR +1. Create PR. +2. Run `bash tools/regenerate_bindings.sh`, and fix resulting errors. +3. Update `const version` in `hook/version.dart` to tag. +4. Regenerate hashes using `dart --enable-experiment=native-assets run tool/generate_hashes.dart`. +5. Land PR. diff --git a/pkgs/intl4x/hook/build.dart b/pkgs/intl4x/hook/build.dart index 82d0fba3..cd64b2b6 100644 --- a/pkgs/intl4x/hook/build.dart +++ b/pkgs/intl4x/hook/build.dart @@ -4,17 +4,23 @@ import 'dart:io'; -import 'package:archive/archive_io.dart'; +import 'package:crypto/crypto.dart' show sha256; import 'package:native_assets_cli/native_assets_cli.dart'; import 'package:path/path.dart' as path; +import 'hashes.dart'; +import 'version.dart'; + const crateName = 'icu_capi'; const package = 'intl4x'; const assetId = 'src/bindings/lib.g.dart'; +final env = 'ICU4X_BUILD_MODE'; + void main(List args) async { await build(args, (config, output) async { - final buildMode = switch (Platform.environment['ICU4X_BUILD_MODE']) { + final environmentBuildMode = Platform.environment[env]; + final buildMode = switch (environmentBuildMode) { 'local' => LocalMode(), 'checkout' => CheckoutMode(config), 'fetch' || null => FetchMode(config), @@ -30,6 +36,8 @@ Unknown build mode for icu4x. Set the `ICU4X_BUILD_MODE` environment variable wi }; final builtLibrary = await buildMode.build(); + // For debugging purposes + output.addMetadatum(env, environmentBuildMode ?? 'fetch'); output.addAsset(NativeCodeAsset( package: package, @@ -44,25 +52,11 @@ Unknown build mode for icu4x. Set the `ICU4X_BUILD_MODE` environment variable wi [ ...buildMode.dependencies, config.packageRoot.resolve('hook/build.dart'), - //TODO: Fix this, currently causes a rebuild for checkout mode - //builtLibrary, ], ); }); } -void unzipFirstFile({required File input, required File output}) { - final inputStream = InputFileStream(input.path); - final archive = ZipDecoder().decodeBuffer(inputStream); - final file = archive.files.firstOrNull; - // If it's a file and not a directory - if (file?.isFile ?? false) { - final outputStream = OutputFileStream(output.path); - file!.writeContent(outputStream); - outputStream.close(); - } -} - sealed class BuildMode { List get dependencies; @@ -76,33 +70,32 @@ final class FetchMode implements BuildMode { @override Future build() async { - // TODO: Get a nicer CDN than a generated link to a privately owned repo. + final target = '${config.targetOS}_${config.targetArchitecture}'; final uri = Uri.parse( - 'https://nightly.link/mosuem/i18n/workflows/intl4x_artifacts/main/lib-$platformName-latest.zip'); + 'https://github.com/dart-lang/i18n/releases/download/$version/$target'); final request = await HttpClient().getUrl(uri); final response = await request.close(); if (response.statusCode != 200) { throw ArgumentError('The request to $uri failed'); } - final zippedDynamicLibrary = - File(path.join(Directory.systemTemp.path, 'tmp.zip')); - zippedDynamicLibrary.createSync(); - await response.pipe(zippedDynamicLibrary.openWrite()); - - final dynamicLibrary = - File.fromUri(config.outputDirectory.resolve('icu4xlib')); + final dynamicLibrary = File.fromUri( + config.outputDirectory.resolve(config.targetOS.dylibFileName('icu4x'))); await dynamicLibrary.create(); - unzipFirstFile(input: zippedDynamicLibrary, output: dynamicLibrary); - return dynamicLibrary.uri; - } + await response.pipe(dynamicLibrary.openWrite()); - String get platformName { - if (Platform.isMacOS) { - return 'macos'; - } else if (Platform.isWindows) { - return 'windows'; + final bytes = await dynamicLibrary.readAsBytes(); + final fileHash = sha256.convert(bytes).toString(); + final expectedFileHash = fileHashes[( + config.targetOS, + config.targetArchitecture, + )]; + if (fileHash == expectedFileHash) { + return dynamicLibrary.uri; } else { - return 'ubuntu'; + throw Exception( + 'The pre-built binary for the target $target at $uri has a hash of ' + '$fileHash, which does not match $expectedFileHash fixed in the ' + 'build hook of package:intl4x.'); } } @@ -235,7 +228,7 @@ Future buildLib(BuildConfig config, String workingDirectory) async { if (!(await file.exists())) { throw FileSystemException('Building the dylib failed', builtPath); } - await file.copy(dylibFileUri.path); + await file.copy(dylibFileUri.toFilePath(windows: Platform.isWindows)); } return dylibFileUri; } diff --git a/pkgs/intl4x/hook/hashes.dart b/pkgs/intl4x/hook/hashes.dart new file mode 100644 index 00000000..9ae3d6de --- /dev/null +++ b/pkgs/intl4x/hook/hashes.dart @@ -0,0 +1,45 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// THIS FILE IS AUTOGENERATED BY `tool/generate_hashes.dart`. TO UPDATE, RUN +// +// dart --enable-experiment=native-assets run tool/generate_hashes.dart +// + +import 'package:native_assets_cli/native_assets_cli.dart'; + +const fileHashes = <(OS, Architecture), String>{ + (OS.android, Architecture.arm): + '77ab3a39e1af15c66f8bdf0c8e647aaf320887f7d37407b78ce2ffd143f3b718', + (OS.android, Architecture.arm64): + '55c090d7496e60072a17e3a9e30438e800e8b4c2f344359be670eee6154ea05a', + (OS.android, Architecture.ia32): + '2e594433fb3cba873de4f2237a7b80ad3f750699738b74f34179a992d56cd34b', + (OS.android, Architecture.x64): + 'd87ac1768dd6865e9f95cf57af39aa96cacb7ead202780af6178b8265098172a', + (OS.iOS, Architecture.arm): + 'a5e90b0748a00c925ce23d3ca09ca612cbdc99174eb565aa8fc658126d58b0fe', + (OS.iOS, Architecture.arm64): + '73349677c7e25d5fe442bc5e240a6e14022a6bf0c8fb8c09644460010c9b93d6', + (OS.iOS, Architecture.x64): + 'dd27c4782b702dc480c4db0cb09dd0a3924e12d06de8a4085cf333b61db508e3', + (OS.linux, Architecture.arm): + '8fe4a44b69b53f475bd14febec830896faf3b56b25f36b137bf5641c9860f530', + (OS.linux, Architecture.arm64): + '0832fb2949f40bf0eda0d401870694dc80f56eec1abe62c6ff0b010fff4d240a', + (OS.linux, Architecture.riscv64): + '551fa6590670384e0783e8bc60eb3f7fe7f576edb8883ced4e82016df00c1096', + (OS.linux, Architecture.x64): + 'a213781c145eff8db953e59366da5430f8c85739d4e07a88d02bc58ccffce523', + (OS.macOS, Architecture.arm64): + '7bedb90113d98917959f26b075fb4cae4404767b84029d6b0d8c68d3828f28c8', + (OS.macOS, Architecture.x64): + '19b7f6614f5b5603629f4cedc7891f1d7ec6e27699f9ce7d6fedcd0204f5cc03', + (OS.windows, Architecture.arm64): + '15502b3f71d4947ea9a91cb3ad6b123f915c75bf3c8f63c0befe7a10b24ccbd9', + (OS.windows, Architecture.ia32): + '8fec764279d157cec54fb2b40af9adcb19936e9d413ef5d608c00f42e51b1e53', + (OS.windows, Architecture.x64): + 'b223858026d6c893fff035df1382e6e2703c328e512b432aaf88b90a5b8b91b9' +}; diff --git a/pkgs/intl4x/hook/version.dart b/pkgs/intl4x/hook/version.dart new file mode 100644 index 00000000..1e94fda8 --- /dev/null +++ b/pkgs/intl4x/hook/version.dart @@ -0,0 +1,5 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +const version = 'intl4x-v.0.9.2-artifacts'; diff --git a/pkgs/intl4x/lib/src/bindings/Bidi.g.dart b/pkgs/intl4x/lib/src/bindings/Bidi.g.dart index d445de3f..ad36faaa 100644 --- a/pkgs/intl4x/lib/src/bindings/Bidi.g.dart +++ b/pkgs/intl4x/lib/src/bindings/Bidi.g.dart @@ -48,7 +48,7 @@ final class Bidi implements ffi.Finalizable { final textArena = _FinalizedArena(); // This lifetime edge depends on lifetimes: 'text core.List textEdges = [textArena]; - final result = _ICU4XBidi_for_text( + final result = _ICU4XBidi_for_text_valid_utf8( _ffi, textView.allocIn(textArena.arena), textView.length, defaultLevel); return BidiInfo._fromFfi(result, [], textEdges); } @@ -121,15 +121,15 @@ external void _ICU4XBidi_destroy(ffi.Pointer self); // ignore: non_constant_identifier_names external _ResultOpaqueInt32 _ICU4XBidi_create(ffi.Pointer provider); -@meta.ResourceIdentifier('ICU4XBidi_for_text') +@meta.ResourceIdentifier('ICU4XBidi_for_text_valid_utf8') @ffi.Native< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Size, - ffi.Uint8)>(isLeaf: true, symbol: 'ICU4XBidi_for_text') + ffi.Uint8)>(isLeaf: true, symbol: 'ICU4XBidi_for_text_valid_utf8') // ignore: non_constant_identifier_names -external ffi.Pointer _ICU4XBidi_for_text( +external ffi.Pointer _ICU4XBidi_for_text_valid_utf8( ffi.Pointer self, ffi.Pointer textData, int textLength, diff --git a/pkgs/intl4x/lib/src/bindings/CodePointMapData8.g.dart b/pkgs/intl4x/lib/src/bindings/CodePointMapData8.g.dart index 6d111262..d8250178 100644 --- a/pkgs/intl4x/lib/src/bindings/CodePointMapData8.g.dart +++ b/pkgs/intl4x/lib/src/bindings/CodePointMapData8.g.dart @@ -128,6 +128,18 @@ final class CodePointMapData8 implements ffi.Finalizable { return CodePointMapData8._fromFfi(result.union.ok, []); } + /// See the [Rust documentation for `hangul_syllable_type`](https://docs.rs/icu/latest/icu/properties/maps/fn.hangul_syllable_type.html) for more information. + /// + /// Throws [Error] on failure. + factory CodePointMapData8.hangulSyllableType(DataProvider provider) { + final result = + _ICU4XCodePointMapData8_load_hangul_syllable_type(provider._ffi); + if (!result.isOk) { + throw Error.values.firstWhere((v) => v._ffi == result.union.err); + } + return CodePointMapData8._fromFfi(result.union.ok, []); + } + /// See the [Rust documentation for `indic_syllabic_category`](https://docs.rs/icu/latest/icu/properties/maps/fn.indic_syllabic_category.html) for more information. /// /// Throws [Error] on failure. @@ -271,6 +283,13 @@ external _ResultOpaqueInt32 _ICU4XCodePointMapData8_load_bidi_class( external _ResultOpaqueInt32 _ICU4XCodePointMapData8_load_east_asian_width( ffi.Pointer provider); +@meta.ResourceIdentifier('ICU4XCodePointMapData8_load_hangul_syllable_type') +@ffi.Native<_ResultOpaqueInt32 Function(ffi.Pointer)>( + isLeaf: true, symbol: 'ICU4XCodePointMapData8_load_hangul_syllable_type') +// ignore: non_constant_identifier_names +external _ResultOpaqueInt32 _ICU4XCodePointMapData8_load_hangul_syllable_type( + ffi.Pointer provider); + @meta.ResourceIdentifier('ICU4XCodePointMapData8_load_indic_syllabic_category') @ffi.Native<_ResultOpaqueInt32 Function(ffi.Pointer)>( isLeaf: true, symbol: 'ICU4XCodePointMapData8_load_indic_syllabic_category') diff --git a/pkgs/intl4x/lib/src/bindings/CustomTimeZone.g.dart b/pkgs/intl4x/lib/src/bindings/CustomTimeZone.g.dart index 4bdc9b64..ec6b3017 100644 --- a/pkgs/intl4x/lib/src/bindings/CustomTimeZone.g.dart +++ b/pkgs/intl4x/lib/src/bindings/CustomTimeZone.g.dart @@ -198,6 +198,23 @@ final class CustomTimeZone implements ffi.Finalizable { } } + /// Sets the `time_zone_id` field from an IANA string by looking up + /// the corresponding BCP-47 string. + /// + /// Errors if the string is not a valid BCP-47 time zone ID. + /// + /// Throws [Error] on failure. + void trySetIanaTimeZoneId2(TimeZoneIdMapper mapper, String id) { + final temp = ffi2.Arena(); + final idView = id.utf8View; + final result = _ICU4XCustomTimeZone_try_set_iana_time_zone_id_2( + _ffi, mapper._ffi, idView.allocIn(temp), idView.length); + temp.releaseAll(); + if (!result.isOk) { + throw Error.values.firstWhere((v) => v._ffi == result.union.err); + } + } + /// Clears the `time_zone_id` field. /// /// See the [Rust documentation for `time_zone_id`](https://docs.rs/icu/latest/icu/timezone/struct.CustomTimeZone.html#structfield.time_zone_id) for more information. @@ -319,7 +336,8 @@ final class CustomTimeZone implements ffi.Finalizable { return writeable.finalize(); } - /// Sets the `zone_variant` field to standard time. + /// Sets the `zone_variant` field to "standard" time, which may or may + /// not correspond to a display name with "Standard" in its name. /// /// See the [Rust documentation for `standard`](https://docs.rs/icu/latest/icu/timezone/struct.ZoneVariant.html#method.standard) for more information. /// @@ -328,7 +346,8 @@ final class CustomTimeZone implements ffi.Finalizable { _ICU4XCustomTimeZone_set_standard_time(_ffi); } - /// Sets the `zone_variant` field to daylight time. + /// Sets the `zone_variant` field to "daylight" time, which may or may + /// not correspond to a display name with "Daylight" in its name. /// /// See the [Rust documentation for `daylight`](https://docs.rs/icu/latest/icu/timezone/struct.ZoneVariant.html#method.daylight) for more information. /// @@ -478,6 +497,18 @@ external _ResultVoidInt32 _ICU4XCustomTimeZone_try_set_iana_time_zone_id( ffi.Pointer idData, int idLength); +@meta.ResourceIdentifier('ICU4XCustomTimeZone_try_set_iana_time_zone_id_2') +@ffi.Native< + _ResultVoidInt32 Function(ffi.Pointer, + ffi.Pointer, ffi.Pointer, ffi.Size)>( + isLeaf: true, symbol: 'ICU4XCustomTimeZone_try_set_iana_time_zone_id_2') +// ignore: non_constant_identifier_names +external _ResultVoidInt32 _ICU4XCustomTimeZone_try_set_iana_time_zone_id_2( + ffi.Pointer self, + ffi.Pointer mapper, + ffi.Pointer idData, + int idLength); + @meta.ResourceIdentifier('ICU4XCustomTimeZone_clear_time_zone_id') @ffi.Native)>( isLeaf: true, symbol: 'ICU4XCustomTimeZone_clear_time_zone_id') diff --git a/pkgs/intl4x/lib/src/bindings/Date.g.dart b/pkgs/intl4x/lib/src/bindings/Date.g.dart index db72664b..94333d07 100644 --- a/pkgs/intl4x/lib/src/bindings/Date.g.dart +++ b/pkgs/intl4x/lib/src/bindings/Date.g.dart @@ -82,6 +82,14 @@ final class Date implements ffi.Finalizable { return IsoDate._fromFfi(result, []); } + /// Returns the 1-indexed day in the year for this date + /// + /// See the [Rust documentation for `day_of_year_info`](https://docs.rs/icu/latest/icu/calendar/struct.Date.html#method.day_of_year_info) for more information. + int get dayOfYear { + final result = _ICU4XDate_day_of_year(_ffi); + return result; + } + /// Returns the 1-indexed day in the month for this date /// /// See the [Rust documentation for `day_of_month`](https://docs.rs/icu/latest/icu/calendar/struct.Date.html#method.day_of_month) for more information. @@ -257,6 +265,12 @@ external ffi.Pointer _ICU4XDate_to_calendar( external ffi.Pointer _ICU4XDate_to_iso( ffi.Pointer self); +@meta.ResourceIdentifier('ICU4XDate_day_of_year') +@ffi.Native)>( + isLeaf: true, symbol: 'ICU4XDate_day_of_year') +// ignore: non_constant_identifier_names +external int _ICU4XDate_day_of_year(ffi.Pointer self); + @meta.ResourceIdentifier('ICU4XDate_day_of_month') @ffi.Native)>( isLeaf: true, symbol: 'ICU4XDate_day_of_month') diff --git a/pkgs/intl4x/lib/src/bindings/DateTime.g.dart b/pkgs/intl4x/lib/src/bindings/DateTime.g.dart index e4f41303..345a7717 100644 --- a/pkgs/intl4x/lib/src/bindings/DateTime.g.dart +++ b/pkgs/intl4x/lib/src/bindings/DateTime.g.dart @@ -151,6 +151,14 @@ final class DateTime implements ffi.Finalizable { return result; } + /// Returns the 1-indexed day in the year for this date + /// + /// See the [Rust documentation for `day_of_year_info`](https://docs.rs/icu/latest/icu/calendar/struct.Date.html#method.day_of_year_info) for more information. + int get dayOfYear { + final result = _ICU4XDateTime_day_of_year(_ffi); + return result; + } + /// Returns the 1-indexed day in the month for this date /// /// See the [Rust documentation for `day_of_month`](https://docs.rs/icu/latest/icu/calendar/struct.Date.html#method.day_of_month) for more information. @@ -387,6 +395,12 @@ external int _ICU4XDateTime_second(ffi.Pointer self); // ignore: non_constant_identifier_names external int _ICU4XDateTime_nanosecond(ffi.Pointer self); +@meta.ResourceIdentifier('ICU4XDateTime_day_of_year') +@ffi.Native)>( + isLeaf: true, symbol: 'ICU4XDateTime_day_of_year') +// ignore: non_constant_identifier_names +external int _ICU4XDateTime_day_of_year(ffi.Pointer self); + @meta.ResourceIdentifier('ICU4XDateTime_day_of_month') @ffi.Native)>( isLeaf: true, symbol: 'ICU4XDateTime_day_of_month') diff --git a/pkgs/intl4x/lib/src/bindings/Error.g.dart b/pkgs/intl4x/lib/src/bindings/Error.g.dart index 8f18a7e6..529d9ec8 100644 --- a/pkgs/intl4x/lib/src/bindings/Error.g.dart +++ b/pkgs/intl4x/lib/src/bindings/Error.g.dart @@ -6,7 +6,7 @@ part of 'lib.g.dart'; /// /// The error names are stable and can be checked against as strings in the JS API /// -/// Additional information: [1](https://docs.rs/fixed_decimal/latest/fixed_decimal/enum.FixedDecimalError.html), [2](https://docs.rs/icu/latest/icu/calendar/enum.CalendarError.html), [3](https://docs.rs/icu/latest/icu/collator/enum.CollatorError.html), [4](https://docs.rs/icu/latest/icu/datetime/enum.DateTimeError.html), [5](https://docs.rs/icu/latest/icu/decimal/enum.DecimalError.html), [6](https://docs.rs/icu/latest/icu/list/enum.ListError.html), [7](https://docs.rs/icu/latest/icu/locid/enum.ParserError.html), [8](https://docs.rs/icu/latest/icu/locid_transform/enum.LocaleTransformError.html), [9](https://docs.rs/icu/latest/icu/normalizer/enum.NormalizerError.html), [10](https://docs.rs/icu/latest/icu/plurals/enum.PluralsError.html), [11](https://docs.rs/icu/latest/icu/properties/enum.PropertiesError.html), [12](https://docs.rs/icu/latest/icu/provider/struct.DataError.html), [13](https://docs.rs/icu/latest/icu/provider/enum.DataErrorKind.html), [14](https://docs.rs/icu/latest/icu/segmenter/enum.SegmenterError.html), [15](https://docs.rs/icu/latest/icu/timezone/enum.TimeZoneError.html) +/// Additional information: [1](https://docs.rs/fixed_decimal/latest/fixed_decimal/enum.FixedDecimalError.html), [2](https://docs.rs/icu/latest/icu/calendar/enum.CalendarError.html), [3](https://docs.rs/icu/latest/icu/collator/enum.CollatorError.html), [4](https://docs.rs/icu/latest/icu/datetime/enum.DateTimeError.html), [5](https://docs.rs/icu/latest/icu/decimal/enum.DecimalError.html), [6](https://docs.rs/icu/latest/icu/list/enum.ListError.html), [7](https://docs.rs/icu/latest/icu/locid/enum.ParserError.html), [8](https://docs.rs/icu/latest/icu/locid_transform/enum.LocaleTransformError.html), [9](https://docs.rs/icu/latest/icu/normalizer/enum.NormalizerError.html), [10](https://docs.rs/icu/latest/icu/plurals/enum.PluralsError.html), [11](https://docs.rs/icu/latest/icu/properties/enum.PropertiesError.html), [12](https://docs.rs/icu/latest/icu/provider/struct.DataError.html), [13](https://docs.rs/icu/latest/icu/provider/enum.DataErrorKind.html), [14](https://docs.rs/icu/latest/icu/segmenter/enum.SegmenterError.html), [15](https://docs.rs/icu/latest/icu/timezone/enum.TimeZoneError.html), [16](https://docs.rs/icu_experimental/latest/icu_experimental/units/enum.ConversionError.html) enum Error { /// The error is not currently categorized as ICU4XError. /// Please file a bug @@ -17,8 +17,12 @@ enum Error { /// Most APIs that return a string may return this error writeableError, + /// Some input was out of bounds outOfBoundsError, + /// Input expected to be UTF-8 was ill-formed + utf8Error, + dataMissingDataKeyError, dataMissingVariantError, @@ -124,7 +128,9 @@ enum Error { normalizerFutureExtensionError, - normalizerValidationError; + normalizerValidationError, + + invalidCldrUnitIdentifierError; int get _ffi { switch (this) { @@ -134,6 +140,8 @@ enum Error { return 1; case outOfBoundsError: return 2; + case utf8Error: + return 3; case dataMissingDataKeyError: return 256; case dataMissingVariantError: @@ -238,6 +246,8 @@ enum Error { return 2816; case normalizerValidationError: return 2817; + case invalidCldrUnitIdentifierError: + return 3072; } } } diff --git a/pkgs/intl4x/lib/src/bindings/GeneralCategoryNameToMaskMapper.g.dart b/pkgs/intl4x/lib/src/bindings/GeneralCategoryNameToMaskMapper.g.dart index b2c74513..fa366554 100644 --- a/pkgs/intl4x/lib/src/bindings/GeneralCategoryNameToMaskMapper.g.dart +++ b/pkgs/intl4x/lib/src/bindings/GeneralCategoryNameToMaskMapper.g.dart @@ -4,7 +4,7 @@ part of 'lib.g.dart'; /// A type capable of looking up General Category mask values from a string name. /// -/// See the [Rust documentation for `get_name_to_enum_mapper`](https://docs.rs/icu/latest/icu/properties/struct.GeneralCategoryGroup.html#method.get_name_to_enum_mapper) for more information. +/// See the [Rust documentation for `name_to_enum_mapper`](https://docs.rs/icu/latest/icu/properties/struct.GeneralCategoryGroup.html#method.name_to_enum_mapper) for more information. /// /// See the [Rust documentation for `PropertyValueNameToEnumMapper`](https://docs.rs/icu/latest/icu/properties/names/struct.PropertyValueNameToEnumMapper.html) for more information. final class GeneralCategoryNameToMaskMapper implements ffi.Finalizable { @@ -51,7 +51,7 @@ final class GeneralCategoryNameToMaskMapper implements ffi.Finalizable { return result; } - /// See the [Rust documentation for `get_name_to_enum_mapper`](https://docs.rs/icu/latest/icu/properties/struct.GeneralCategoryGroup.html#method.get_name_to_enum_mapper) for more information. + /// See the [Rust documentation for `name_to_enum_mapper`](https://docs.rs/icu/latest/icu/properties/struct.GeneralCategoryGroup.html#method.name_to_enum_mapper) for more information. /// /// Throws [Error] on failure. factory GeneralCategoryNameToMaskMapper(DataProvider provider) { diff --git a/pkgs/intl4x/lib/src/bindings/IsoDate.g.dart b/pkgs/intl4x/lib/src/bindings/IsoDate.g.dart index 3bef0034..128dbdcb 100644 --- a/pkgs/intl4x/lib/src/bindings/IsoDate.g.dart +++ b/pkgs/intl4x/lib/src/bindings/IsoDate.g.dart @@ -60,6 +60,14 @@ final class IsoDate implements ffi.Finalizable { return Date._fromFfi(result, []); } + /// Returns the 1-indexed day in the year for this date + /// + /// See the [Rust documentation for `day_of_year_info`](https://docs.rs/icu/latest/icu/calendar/struct.Date.html#method.day_of_year_info) for more information. + int get dayOfYear { + final result = _ICU4XIsoDate_day_of_year(_ffi); + return result; + } + /// Returns the 1-indexed day in the month for this date /// /// See the [Rust documentation for `day_of_month`](https://docs.rs/icu/latest/icu/calendar/struct.Date.html#method.day_of_month) for more information. @@ -183,6 +191,12 @@ external ffi.Pointer _ICU4XIsoDate_to_calendar( external ffi.Pointer _ICU4XIsoDate_to_any( ffi.Pointer self); +@meta.ResourceIdentifier('ICU4XIsoDate_day_of_year') +@ffi.Native)>( + isLeaf: true, symbol: 'ICU4XIsoDate_day_of_year') +// ignore: non_constant_identifier_names +external int _ICU4XIsoDate_day_of_year(ffi.Pointer self); + @meta.ResourceIdentifier('ICU4XIsoDate_day_of_month') @ffi.Native)>( isLeaf: true, symbol: 'ICU4XIsoDate_day_of_month') diff --git a/pkgs/intl4x/lib/src/bindings/IsoDateTime.g.dart b/pkgs/intl4x/lib/src/bindings/IsoDateTime.g.dart index 4835abab..6e2b8ee7 100644 --- a/pkgs/intl4x/lib/src/bindings/IsoDateTime.g.dart +++ b/pkgs/intl4x/lib/src/bindings/IsoDateTime.g.dart @@ -139,6 +139,14 @@ final class IsoDateTime implements ffi.Finalizable { return result; } + /// Returns the 1-indexed day in the year for this date + /// + /// See the [Rust documentation for `day_of_year_info`](https://docs.rs/icu/latest/icu/calendar/struct.Date.html#method.day_of_year_info) for more information. + int get dayOfYear { + final result = _ICU4XIsoDateTime_day_of_year(_ffi); + return result; + } + /// Returns the 1-indexed day in the month for this date /// /// See the [Rust documentation for `day_of_month`](https://docs.rs/icu/latest/icu/calendar/struct.Date.html#method.day_of_month) for more information. @@ -333,6 +341,12 @@ external int _ICU4XIsoDateTime_second(ffi.Pointer self); // ignore: non_constant_identifier_names external int _ICU4XIsoDateTime_nanosecond(ffi.Pointer self); +@meta.ResourceIdentifier('ICU4XIsoDateTime_day_of_year') +@ffi.Native)>( + isLeaf: true, symbol: 'ICU4XIsoDateTime_day_of_year') +// ignore: non_constant_identifier_names +external int _ICU4XIsoDateTime_day_of_year(ffi.Pointer self); + @meta.ResourceIdentifier('ICU4XIsoDateTime_day_of_month') @ffi.Native)>( isLeaf: true, symbol: 'ICU4XIsoDateTime_day_of_month') diff --git a/pkgs/intl4x/lib/src/bindings/MeasureUnit.g.dart b/pkgs/intl4x/lib/src/bindings/MeasureUnit.g.dart new file mode 100644 index 00000000..de3ab053 --- /dev/null +++ b/pkgs/intl4x/lib/src/bindings/MeasureUnit.g.dart @@ -0,0 +1,36 @@ +// generated by diplomat-tool + +part of 'lib.g.dart'; + +/// An ICU4X Measurement Unit object which represents a single unit of measurement +/// such as `meter`, `second`, `kilometer-per-hour`, `square-meter`, etc. +/// +/// You can create an instance of this object using [`MeasureUnitParser`] by calling the `parse_measure_unit` method. +/// +/// See the [Rust documentation for `MeasureUnit`](https://docs.rs/icu/latest/icu/experimental/units/measureunit/struct.MeasureUnit.html) for more information. +final class MeasureUnit implements ffi.Finalizable { + final ffi.Pointer _ffi; + + // These are "used" in the sense that they keep dependencies alive + // ignore: unused_field + final core.List _selfEdge; + + // This takes in a list of lifetime edges (including for &self borrows) + // corresponding to data this may borrow from. These should be flat arrays containing + // references to objects, and this object will hold on to them to keep them alive and + // maintain borrow validity. + MeasureUnit._fromFfi(this._ffi, this._selfEdge) { + if (_selfEdge.isEmpty) { + _finalizer.attach(this, _ffi.cast()); + } + } + + static final _finalizer = + ffi.NativeFinalizer(ffi.Native.addressOf(_ICU4XMeasureUnit_destroy)); +} + +@meta.ResourceIdentifier('ICU4XMeasureUnit_destroy') +@ffi.Native)>( + isLeaf: true, symbol: 'ICU4XMeasureUnit_destroy') +// ignore: non_constant_identifier_names +external void _ICU4XMeasureUnit_destroy(ffi.Pointer self); diff --git a/pkgs/intl4x/lib/src/bindings/MeasureUnitParser.g.dart b/pkgs/intl4x/lib/src/bindings/MeasureUnitParser.g.dart new file mode 100644 index 00000000..3c4c0143 --- /dev/null +++ b/pkgs/intl4x/lib/src/bindings/MeasureUnitParser.g.dart @@ -0,0 +1,64 @@ +// generated by diplomat-tool + +part of 'lib.g.dart'; + +/// An ICU4X Measurement Unit parser object which is capable of parsing the CLDR unit identifier +/// (e.g. `meter-per-square-second`) and get the [`MeasureUnit`]. +/// +/// See the [Rust documentation for `MeasureUnitParser`](https://docs.rs/icu/latest/icu/experimental/units/measureunit/struct.MeasureUnitParser.html) for more information. +final class MeasureUnitParser implements ffi.Finalizable { + final ffi.Pointer _ffi; + + // These are "used" in the sense that they keep dependencies alive + // ignore: unused_field + final core.List _selfEdge; + // ignore: unused_field + final core.List _aEdge; + + // This takes in a list of lifetime edges (including for &self borrows) + // corresponding to data this may borrow from. These should be flat arrays containing + // references to objects, and this object will hold on to them to keep them alive and + // maintain borrow validity. + MeasureUnitParser._fromFfi(this._ffi, this._selfEdge, this._aEdge) { + if (_selfEdge.isEmpty) { + _finalizer.attach(this, _ffi.cast()); + } + } + + static final _finalizer = ffi.NativeFinalizer( + ffi.Native.addressOf(_ICU4XMeasureUnitParser_destroy)); + + /// Parses the CLDR unit identifier (e.g. `meter-per-square-second`) and returns the corresponding [`MeasureUnit`]. + /// Returns an error if the unit identifier is not valid. + /// + /// See the [Rust documentation for `parse`](https://docs.rs/icu/latest/icu/experimental/units/measureunit/struct.MeasureUnitParser.html#method.parse) for more information. + /// + /// Throws [Error] on failure. + MeasureUnit parse(String unitId) { + final temp = ffi2.Arena(); + final unitIdView = unitId.utf8View; + final result = _ICU4XMeasureUnitParser_parse( + _ffi, unitIdView.allocIn(temp), unitIdView.length); + temp.releaseAll(); + if (!result.isOk) { + throw Error.values.firstWhere((v) => v._ffi == result.union.err); + } + return MeasureUnit._fromFfi(result.union.ok, []); + } +} + +@meta.ResourceIdentifier('ICU4XMeasureUnitParser_destroy') +@ffi.Native)>( + isLeaf: true, symbol: 'ICU4XMeasureUnitParser_destroy') +// ignore: non_constant_identifier_names +external void _ICU4XMeasureUnitParser_destroy(ffi.Pointer self); + +@meta.ResourceIdentifier('ICU4XMeasureUnitParser_parse') +@ffi.Native< + _ResultOpaqueInt32 Function(ffi.Pointer, ffi.Pointer, + ffi.Size)>(isLeaf: true, symbol: 'ICU4XMeasureUnitParser_parse') +// ignore: non_constant_identifier_names +external _ResultOpaqueInt32 _ICU4XMeasureUnitParser_parse( + ffi.Pointer self, + ffi.Pointer unitIdData, + int unitIdLength); diff --git a/pkgs/intl4x/lib/src/bindings/PropertyValueNameToEnumMapper.g.dart b/pkgs/intl4x/lib/src/bindings/PropertyValueNameToEnumMapper.g.dart index ed2786f7..f4c7f166 100644 --- a/pkgs/intl4x/lib/src/bindings/PropertyValueNameToEnumMapper.g.dart +++ b/pkgs/intl4x/lib/src/bindings/PropertyValueNameToEnumMapper.g.dart @@ -55,7 +55,7 @@ final class PropertyValueNameToEnumMapper implements ffi.Finalizable { return result; } - /// See the [Rust documentation for `get_name_to_enum_mapper`](https://docs.rs/icu/latest/icu/properties/struct.GeneralCategory.html#method.get_name_to_enum_mapper) for more information. + /// See the [Rust documentation for `name_to_enum_mapper`](https://docs.rs/icu/latest/icu/properties/struct.GeneralCategory.html#method.name_to_enum_mapper) for more information. /// /// Throws [Error] on failure. factory PropertyValueNameToEnumMapper.generalCategory(DataProvider provider) { @@ -67,12 +67,14 @@ final class PropertyValueNameToEnumMapper implements ffi.Finalizable { return PropertyValueNameToEnumMapper._fromFfi(result.union.ok, []); } - /// See the [Rust documentation for `name_to_enum_mapper`](https://docs.rs/icu/latest/icu/properties/struct.BidiClass.html#method.name_to_enum_mapper) for more information. + /// See the [Rust documentation for `name_to_enum_mapper`](https://docs.rs/icu/latest/icu/properties/struct.HangulSyllableType.html#method.name_to_enum_mapper) for more information. /// /// Throws [Error] on failure. - factory PropertyValueNameToEnumMapper.bidiClass(DataProvider provider) { + factory PropertyValueNameToEnumMapper.hangulSyllableType( + DataProvider provider) { final result = - _ICU4XPropertyValueNameToEnumMapper_load_bidi_class(provider._ffi); + _ICU4XPropertyValueNameToEnumMapper_load_hangul_syllable_type( + provider._ffi); if (!result.isOk) { throw Error.values.firstWhere((v) => v._ffi == result.union.err); } @@ -91,6 +93,18 @@ final class PropertyValueNameToEnumMapper implements ffi.Finalizable { return PropertyValueNameToEnumMapper._fromFfi(result.union.ok, []); } + /// See the [Rust documentation for `name_to_enum_mapper`](https://docs.rs/icu/latest/icu/properties/struct.BidiClass.html#method.name_to_enum_mapper) for more information. + /// + /// Throws [Error] on failure. + factory PropertyValueNameToEnumMapper.bidiClass(DataProvider provider) { + final result = + _ICU4XPropertyValueNameToEnumMapper_load_bidi_class(provider._ffi); + if (!result.isOk) { + throw Error.values.firstWhere((v) => v._ffi == result.union.err); + } + return PropertyValueNameToEnumMapper._fromFfi(result.union.ok, []); + } + /// See the [Rust documentation for `name_to_enum_mapper`](https://docs.rs/icu/latest/icu/properties/struct.IndicSyllabicCategory.html#method.name_to_enum_mapper) for more information. /// /// Throws [Error] on failure. @@ -117,7 +131,7 @@ final class PropertyValueNameToEnumMapper implements ffi.Finalizable { return PropertyValueNameToEnumMapper._fromFfi(result.union.ok, []); } - /// See the [Rust documentation for `get_name_to_enum_mapper`](https://docs.rs/icu/latest/icu/properties/struct.GraphemeClusterBreak.html#method.get_name_to_enum_mapper) for more information. + /// See the [Rust documentation for `name_to_enum_mapper`](https://docs.rs/icu/latest/icu/properties/struct.GraphemeClusterBreak.html#method.name_to_enum_mapper) for more information. /// /// Throws [Error] on failure. factory PropertyValueNameToEnumMapper.graphemeClusterBreak( @@ -207,12 +221,15 @@ external _ResultOpaqueInt32 _ICU4XPropertyValueNameToEnumMapper_load_general_category( ffi.Pointer provider); -@meta.ResourceIdentifier('ICU4XPropertyValueNameToEnumMapper_load_bidi_class') +@meta.ResourceIdentifier( + 'ICU4XPropertyValueNameToEnumMapper_load_hangul_syllable_type') @ffi.Native<_ResultOpaqueInt32 Function(ffi.Pointer)>( - isLeaf: true, symbol: 'ICU4XPropertyValueNameToEnumMapper_load_bidi_class') + isLeaf: true, + symbol: 'ICU4XPropertyValueNameToEnumMapper_load_hangul_syllable_type') // ignore: non_constant_identifier_names -external _ResultOpaqueInt32 _ICU4XPropertyValueNameToEnumMapper_load_bidi_class( - ffi.Pointer provider); +external _ResultOpaqueInt32 + _ICU4XPropertyValueNameToEnumMapper_load_hangul_syllable_type( + ffi.Pointer provider); @meta.ResourceIdentifier( 'ICU4XPropertyValueNameToEnumMapper_load_east_asian_width') @@ -224,6 +241,13 @@ external _ResultOpaqueInt32 _ICU4XPropertyValueNameToEnumMapper_load_east_asian_width( ffi.Pointer provider); +@meta.ResourceIdentifier('ICU4XPropertyValueNameToEnumMapper_load_bidi_class') +@ffi.Native<_ResultOpaqueInt32 Function(ffi.Pointer)>( + isLeaf: true, symbol: 'ICU4XPropertyValueNameToEnumMapper_load_bidi_class') +// ignore: non_constant_identifier_names +external _ResultOpaqueInt32 _ICU4XPropertyValueNameToEnumMapper_load_bidi_class( + ffi.Pointer provider); + @meta.ResourceIdentifier( 'ICU4XPropertyValueNameToEnumMapper_load_indic_syllabic_category') @ffi.Native<_ResultOpaqueInt32 Function(ffi.Pointer)>( diff --git a/pkgs/intl4x/lib/src/bindings/TimeZoneIdMapper.g.dart b/pkgs/intl4x/lib/src/bindings/TimeZoneIdMapper.g.dart new file mode 100644 index 00000000..9c9eb3e6 --- /dev/null +++ b/pkgs/intl4x/lib/src/bindings/TimeZoneIdMapper.g.dart @@ -0,0 +1,167 @@ +// generated by diplomat-tool + +part of 'lib.g.dart'; + +/// A mapper between IANA time zone identifiers and BCP-47 time zone identifiers. +/// +/// This mapper supports two-way mapping, but it is optimized for the case of IANA to BCP-47. +/// It also supports normalizing and canonicalizing the IANA strings. +/// +/// See the [Rust documentation for `TimeZoneIdMapper`](https://docs.rs/icu/latest/icu/timezone/struct.TimeZoneIdMapper.html) for more information. +final class TimeZoneIdMapper implements ffi.Finalizable { + final ffi.Pointer _ffi; + + // These are "used" in the sense that they keep dependencies alive + // ignore: unused_field + final core.List _selfEdge; + + // This takes in a list of lifetime edges (including for &self borrows) + // corresponding to data this may borrow from. These should be flat arrays containing + // references to objects, and this object will hold on to them to keep them alive and + // maintain borrow validity. + TimeZoneIdMapper._fromFfi(this._ffi, this._selfEdge) { + if (_selfEdge.isEmpty) { + _finalizer.attach(this, _ffi.cast()); + } + } + + static final _finalizer = + ffi.NativeFinalizer(ffi.Native.addressOf(_ICU4XTimeZoneIdMapper_destroy)); + + /// See the [Rust documentation for `new`](https://docs.rs/icu/latest/icu/timezone/struct.TimeZoneIdMapper.html#method.new) for more information. + /// + /// Throws [Error] on failure. + factory TimeZoneIdMapper(DataProvider provider) { + final result = _ICU4XTimeZoneIdMapper_create(provider._ffi); + if (!result.isOk) { + throw Error.values.firstWhere((v) => v._ffi == result.union.err); + } + return TimeZoneIdMapper._fromFfi(result.union.ok, []); + } + + /// See the [Rust documentation for `iana_to_bcp47`](https://docs.rs/icu/latest/icu/timezone/struct.TimeZoneIdMapperBorrowed.html#method.iana_to_bcp47) for more information. + /// + /// Throws [Error] on failure. + String ianaToBcp47(String value) { + final temp = ffi2.Arena(); + final valueView = value.utf8View; + final writeable = _Writeable(); + final result = _ICU4XTimeZoneIdMapper_iana_to_bcp47( + _ffi, valueView.allocIn(temp), valueView.length, writeable._ffi); + temp.releaseAll(); + if (!result.isOk) { + throw Error.values.firstWhere((v) => v._ffi == result.union.err); + } + return writeable.finalize(); + } + + /// See the [Rust documentation for `normalize_iana`](https://docs.rs/icu/latest/icu/timezone/struct.TimeZoneIdMapperBorrowed.html#method.normalize_iana) for more information. + /// + /// Throws [Error] on failure. + String normalizeIana(String value) { + final temp = ffi2.Arena(); + final valueView = value.utf8View; + final writeable = _Writeable(); + final result = _ICU4XTimeZoneIdMapper_normalize_iana( + _ffi, valueView.allocIn(temp), valueView.length, writeable._ffi); + temp.releaseAll(); + if (!result.isOk) { + throw Error.values.firstWhere((v) => v._ffi == result.union.err); + } + return writeable.finalize(); + } + + /// See the [Rust documentation for `canonicalize_iana`](https://docs.rs/icu/latest/icu/timezone/struct.TimeZoneIdMapperBorrowed.html#method.canonicalize_iana) for more information. + /// + /// Throws [Error] on failure. + String canonicalizeIana(String value) { + final temp = ffi2.Arena(); + final valueView = value.utf8View; + final writeable = _Writeable(); + final result = _ICU4XTimeZoneIdMapper_canonicalize_iana( + _ffi, valueView.allocIn(temp), valueView.length, writeable._ffi); + temp.releaseAll(); + if (!result.isOk) { + throw Error.values.firstWhere((v) => v._ffi == result.union.err); + } + return writeable.finalize(); + } + + /// See the [Rust documentation for `find_canonical_iana_from_bcp47`](https://docs.rs/icu/latest/icu/timezone/struct.TimeZoneIdMapperBorrowed.html#method.find_canonical_iana_from_bcp47) for more information. + /// + /// Throws [Error] on failure. + String findCanonicalIanaFromBcp47(String value) { + final temp = ffi2.Arena(); + final valueView = value.utf8View; + final writeable = _Writeable(); + final result = _ICU4XTimeZoneIdMapper_find_canonical_iana_from_bcp47( + _ffi, valueView.allocIn(temp), valueView.length, writeable._ffi); + temp.releaseAll(); + if (!result.isOk) { + throw Error.values.firstWhere((v) => v._ffi == result.union.err); + } + return writeable.finalize(); + } +} + +@meta.ResourceIdentifier('ICU4XTimeZoneIdMapper_destroy') +@ffi.Native)>( + isLeaf: true, symbol: 'ICU4XTimeZoneIdMapper_destroy') +// ignore: non_constant_identifier_names +external void _ICU4XTimeZoneIdMapper_destroy(ffi.Pointer self); + +@meta.ResourceIdentifier('ICU4XTimeZoneIdMapper_create') +@ffi.Native<_ResultOpaqueInt32 Function(ffi.Pointer)>( + isLeaf: true, symbol: 'ICU4XTimeZoneIdMapper_create') +// ignore: non_constant_identifier_names +external _ResultOpaqueInt32 _ICU4XTimeZoneIdMapper_create( + ffi.Pointer provider); + +@meta.ResourceIdentifier('ICU4XTimeZoneIdMapper_iana_to_bcp47') +@ffi.Native< + _ResultVoidInt32 Function(ffi.Pointer, + ffi.Pointer, ffi.Size, ffi.Pointer)>( + isLeaf: true, symbol: 'ICU4XTimeZoneIdMapper_iana_to_bcp47') +// ignore: non_constant_identifier_names +external _ResultVoidInt32 _ICU4XTimeZoneIdMapper_iana_to_bcp47( + ffi.Pointer self, + ffi.Pointer valueData, + int valueLength, + ffi.Pointer writeable); + +@meta.ResourceIdentifier('ICU4XTimeZoneIdMapper_normalize_iana') +@ffi.Native< + _ResultVoidInt32 Function(ffi.Pointer, + ffi.Pointer, ffi.Size, ffi.Pointer)>( + isLeaf: true, symbol: 'ICU4XTimeZoneIdMapper_normalize_iana') +// ignore: non_constant_identifier_names +external _ResultVoidInt32 _ICU4XTimeZoneIdMapper_normalize_iana( + ffi.Pointer self, + ffi.Pointer valueData, + int valueLength, + ffi.Pointer writeable); + +@meta.ResourceIdentifier('ICU4XTimeZoneIdMapper_canonicalize_iana') +@ffi.Native< + _ResultVoidInt32 Function(ffi.Pointer, + ffi.Pointer, ffi.Size, ffi.Pointer)>( + isLeaf: true, symbol: 'ICU4XTimeZoneIdMapper_canonicalize_iana') +// ignore: non_constant_identifier_names +external _ResultVoidInt32 _ICU4XTimeZoneIdMapper_canonicalize_iana( + ffi.Pointer self, + ffi.Pointer valueData, + int valueLength, + ffi.Pointer writeable); + +@meta.ResourceIdentifier('ICU4XTimeZoneIdMapper_find_canonical_iana_from_bcp47') +@ffi.Native< + _ResultVoidInt32 Function(ffi.Pointer, + ffi.Pointer, ffi.Size, ffi.Pointer)>( + isLeaf: true, + symbol: 'ICU4XTimeZoneIdMapper_find_canonical_iana_from_bcp47') +// ignore: non_constant_identifier_names +external _ResultVoidInt32 _ICU4XTimeZoneIdMapper_find_canonical_iana_from_bcp47( + ffi.Pointer self, + ffi.Pointer valueData, + int valueLength, + ffi.Pointer writeable); diff --git a/pkgs/intl4x/lib/src/bindings/TimeZoneIdMapperWithFastCanonicalization.g.dart b/pkgs/intl4x/lib/src/bindings/TimeZoneIdMapperWithFastCanonicalization.g.dart new file mode 100644 index 00000000..705286b9 --- /dev/null +++ b/pkgs/intl4x/lib/src/bindings/TimeZoneIdMapperWithFastCanonicalization.g.dart @@ -0,0 +1,127 @@ +// generated by diplomat-tool + +part of 'lib.g.dart'; + +/// A mapper between IANA time zone identifiers and BCP-47 time zone identifiers. +/// +/// This mapper supports two-way mapping, but it is optimized for the case of IANA to BCP-47. +/// It also supports normalizing and canonicalizing the IANA strings. +/// +/// See the [Rust documentation for `TimeZoneIdMapperWithFastCanonicalization`](https://docs.rs/icu/latest/icu/timezone/struct.TimeZoneIdMapperWithFastCanonicalization.html) for more information. +final class TimeZoneIdMapperWithFastCanonicalization + implements ffi.Finalizable { + final ffi.Pointer _ffi; + + // These are "used" in the sense that they keep dependencies alive + // ignore: unused_field + final core.List _selfEdge; + + // This takes in a list of lifetime edges (including for &self borrows) + // corresponding to data this may borrow from. These should be flat arrays containing + // references to objects, and this object will hold on to them to keep them alive and + // maintain borrow validity. + TimeZoneIdMapperWithFastCanonicalization._fromFfi(this._ffi, this._selfEdge) { + if (_selfEdge.isEmpty) { + _finalizer.attach(this, _ffi.cast()); + } + } + + static final _finalizer = ffi.NativeFinalizer(ffi.Native.addressOf( + _ICU4XTimeZoneIdMapperWithFastCanonicalization_destroy)); + + /// See the [Rust documentation for `new`](https://docs.rs/icu/latest/icu/timezone/struct.TimeZoneIdMapperWithFastCanonicalization.html#method.new) for more information. + /// + /// Throws [Error] on failure. + factory TimeZoneIdMapperWithFastCanonicalization(DataProvider provider) { + final result = + _ICU4XTimeZoneIdMapperWithFastCanonicalization_create(provider._ffi); + if (!result.isOk) { + throw Error.values.firstWhere((v) => v._ffi == result.union.err); + } + return TimeZoneIdMapperWithFastCanonicalization._fromFfi( + result.union.ok, []); + } + + /// See the [Rust documentation for `canonicalize_iana`](https://docs.rs/icu/latest/icu/timezone/struct.TimeZoneIdMapperWithFastCanonicalizationBorrowed.html#method.canonicalize_iana) for more information. + /// + /// Throws [Error] on failure. + String canonicalizeIana(String value) { + final temp = ffi2.Arena(); + final valueView = value.utf8View; + final writeable = _Writeable(); + final result = + _ICU4XTimeZoneIdMapperWithFastCanonicalization_canonicalize_iana( + _ffi, valueView.allocIn(temp), valueView.length, writeable._ffi); + temp.releaseAll(); + if (!result.isOk) { + throw Error.values.firstWhere((v) => v._ffi == result.union.err); + } + return writeable.finalize(); + } + + /// See the [Rust documentation for `canonical_iana_from_bcp47`](https://docs.rs/icu/latest/icu/timezone/struct.TimeZoneIdMapperWithFastCanonicalizationBorrowed.html#method.canonical_iana_from_bcp47) for more information. + /// + /// Throws [Error] on failure. + String canonicalIanaFromBcp47(String value) { + final temp = ffi2.Arena(); + final valueView = value.utf8View; + final writeable = _Writeable(); + final result = + _ICU4XTimeZoneIdMapperWithFastCanonicalization_canonical_iana_from_bcp47( + _ffi, valueView.allocIn(temp), valueView.length, writeable._ffi); + temp.releaseAll(); + if (!result.isOk) { + throw Error.values.firstWhere((v) => v._ffi == result.union.err); + } + return writeable.finalize(); + } +} + +@meta + .ResourceIdentifier('ICU4XTimeZoneIdMapperWithFastCanonicalization_destroy') +@ffi.Native)>( + isLeaf: true, + symbol: 'ICU4XTimeZoneIdMapperWithFastCanonicalization_destroy') +// ignore: non_constant_identifier_names +external void _ICU4XTimeZoneIdMapperWithFastCanonicalization_destroy( + ffi.Pointer self); + +@meta.ResourceIdentifier('ICU4XTimeZoneIdMapperWithFastCanonicalization_create') +@ffi.Native<_ResultOpaqueInt32 Function(ffi.Pointer)>( + isLeaf: true, + symbol: 'ICU4XTimeZoneIdMapperWithFastCanonicalization_create') +// ignore: non_constant_identifier_names +external _ResultOpaqueInt32 + _ICU4XTimeZoneIdMapperWithFastCanonicalization_create( + ffi.Pointer provider); + +@meta.ResourceIdentifier( + 'ICU4XTimeZoneIdMapperWithFastCanonicalization_canonicalize_iana') +@ffi.Native< + _ResultVoidInt32 Function(ffi.Pointer, + ffi.Pointer, ffi.Size, ffi.Pointer)>( + isLeaf: true, + symbol: 'ICU4XTimeZoneIdMapperWithFastCanonicalization_canonicalize_iana') +// ignore: non_constant_identifier_names +external _ResultVoidInt32 + _ICU4XTimeZoneIdMapperWithFastCanonicalization_canonicalize_iana( + ffi.Pointer self, + ffi.Pointer valueData, + int valueLength, + ffi.Pointer writeable); + +@meta.ResourceIdentifier( + 'ICU4XTimeZoneIdMapperWithFastCanonicalization_canonical_iana_from_bcp47') +@ffi.Native< + _ResultVoidInt32 Function(ffi.Pointer, + ffi.Pointer, ffi.Size, ffi.Pointer)>( + isLeaf: true, + symbol: + 'ICU4XTimeZoneIdMapperWithFastCanonicalization_canonical_iana_from_bcp47') +// ignore: non_constant_identifier_names +external _ResultVoidInt32 + _ICU4XTimeZoneIdMapperWithFastCanonicalization_canonical_iana_from_bcp47( + ffi.Pointer self, + ffi.Pointer valueData, + int valueLength, + ffi.Pointer writeable); diff --git a/pkgs/intl4x/lib/src/bindings/UnitsConverter.g.dart b/pkgs/intl4x/lib/src/bindings/UnitsConverter.g.dart new file mode 100644 index 00000000..63abfb79 --- /dev/null +++ b/pkgs/intl4x/lib/src/bindings/UnitsConverter.g.dart @@ -0,0 +1,67 @@ +// generated by diplomat-tool + +part of 'lib.g.dart'; + +/// An ICU4X Units Converter object, capable of converting between two [`MeasureUnit`]s. +/// +/// You can create an instance of this object using [`UnitsConverterFactory`] by calling the `converter` method. +/// +/// See the [Rust documentation for `UnitsConverter`](https://docs.rs/icu/latest/icu/experimental/units/converter/struct.UnitsConverter.html) for more information. +final class UnitsConverter implements ffi.Finalizable { + final ffi.Pointer _ffi; + + // These are "used" in the sense that they keep dependencies alive + // ignore: unused_field + final core.List _selfEdge; + + // This takes in a list of lifetime edges (including for &self borrows) + // corresponding to data this may borrow from. These should be flat arrays containing + // references to objects, and this object will hold on to them to keep them alive and + // maintain borrow validity. + UnitsConverter._fromFfi(this._ffi, this._selfEdge) { + if (_selfEdge.isEmpty) { + _finalizer.attach(this, _ffi.cast()); + } + } + + static final _finalizer = + ffi.NativeFinalizer(ffi.Native.addressOf(_ICU4XUnitsConverter_destroy)); + + /// Converts the input value in float from the input unit to the output unit (that have been used to create this converter). + /// NOTE: + /// The conversion using floating-point operations is not as accurate as the conversion using ratios. + /// + /// See the [Rust documentation for `convert`](https://docs.rs/icu/latest/icu/experimental/units/converter/struct.UnitsConverter.html#method.convert) for more information. + double convertDouble(double value) { + final result = _ICU4XUnitsConverter_convert_f64(_ffi, value); + return result; + } + + /// Clones the current [`UnitsConverter`] object. + /// + /// See the [Rust documentation for `clone`](https://docs.rs/icu/latest/icu/experimental/units/converter/struct.UnitsConverter.html#method.clone) for more information. + UnitsConverter clone() { + final result = _ICU4XUnitsConverter_clone(_ffi); + return UnitsConverter._fromFfi(result, []); + } +} + +@meta.ResourceIdentifier('ICU4XUnitsConverter_destroy') +@ffi.Native)>( + isLeaf: true, symbol: 'ICU4XUnitsConverter_destroy') +// ignore: non_constant_identifier_names +external void _ICU4XUnitsConverter_destroy(ffi.Pointer self); + +@meta.ResourceIdentifier('ICU4XUnitsConverter_convert_f64') +@ffi.Native, ffi.Double)>( + isLeaf: true, symbol: 'ICU4XUnitsConverter_convert_f64') +// ignore: non_constant_identifier_names +external double _ICU4XUnitsConverter_convert_f64( + ffi.Pointer self, double value); + +@meta.ResourceIdentifier('ICU4XUnitsConverter_clone') +@ffi.Native Function(ffi.Pointer)>( + isLeaf: true, symbol: 'ICU4XUnitsConverter_clone') +// ignore: non_constant_identifier_names +external ffi.Pointer _ICU4XUnitsConverter_clone( + ffi.Pointer self); diff --git a/pkgs/intl4x/lib/src/bindings/UnitsConverterFactory.g.dart b/pkgs/intl4x/lib/src/bindings/UnitsConverterFactory.g.dart new file mode 100644 index 00000000..85c1e96b --- /dev/null +++ b/pkgs/intl4x/lib/src/bindings/UnitsConverterFactory.g.dart @@ -0,0 +1,94 @@ +// generated by diplomat-tool + +part of 'lib.g.dart'; + +/// An ICU4X Units Converter Factory object, capable of creating converters a [`UnitsConverter`] +/// for converting between two [`MeasureUnit`]s. +/// Also, it can parse the CLDR unit identifier (e.g. `meter-per-square-second`) and get the [`MeasureUnit`]. +/// +/// See the [Rust documentation for `ConverterFactory`](https://docs.rs/icu/latest/icu/experimental/units/converter_factory/struct.ConverterFactory.html) for more information. +final class UnitsConverterFactory implements ffi.Finalizable { + final ffi.Pointer _ffi; + + // These are "used" in the sense that they keep dependencies alive + // ignore: unused_field + final core.List _selfEdge; + + // This takes in a list of lifetime edges (including for &self borrows) + // corresponding to data this may borrow from. These should be flat arrays containing + // references to objects, and this object will hold on to them to keep them alive and + // maintain borrow validity. + UnitsConverterFactory._fromFfi(this._ffi, this._selfEdge) { + if (_selfEdge.isEmpty) { + _finalizer.attach(this, _ffi.cast()); + } + } + + static final _finalizer = ffi.NativeFinalizer( + ffi.Native.addressOf(_ICU4XUnitsConverterFactory_destroy)); + + /// Construct a new [`UnitsConverterFactory`] instance. + /// + /// See the [Rust documentation for `new`](https://docs.rs/icu/latest/icu/experimental/units/converter_factory/struct.ConverterFactory.html#method.new) for more information. + /// + /// Throws [Error] on failure. + factory UnitsConverterFactory(DataProvider provider) { + final result = _ICU4XUnitsConverterFactory_create(provider._ffi); + if (!result.isOk) { + throw Error.values.firstWhere((v) => v._ffi == result.union.err); + } + return UnitsConverterFactory._fromFfi(result.union.ok, []); + } + + /// Creates a new [`UnitsConverter`] from the input and output [`MeasureUnit`]s. + /// Returns nothing if the conversion between the two units is not possible. + /// For example, conversion between `meter` and `second` is not possible. + /// + /// See the [Rust documentation for `converter`](https://docs.rs/icu/latest/icu/experimental/units/converter_factory/struct.ConverterFactory.html#method.converter) for more information. + UnitsConverter? converter(MeasureUnit from, MeasureUnit to) { + final result = + _ICU4XUnitsConverterFactory_converter(_ffi, from._ffi, to._ffi); + return result.address == 0 ? null : UnitsConverter._fromFfi(result, []); + } + + /// Creates a parser to parse the CLDR unit identifier (e.g. `meter-per-square-second`) and get the [`MeasureUnit`]. + /// + /// See the [Rust documentation for `parser`](https://docs.rs/icu/latest/icu/experimental/units/converter_factory/struct.ConverterFactory.html#method.parser) for more information. + MeasureUnitParser parser() { + // This lifetime edge depends on lifetimes: 'a + core.List aEdges = [this]; + final result = _ICU4XUnitsConverterFactory_parser(_ffi); + return MeasureUnitParser._fromFfi(result, [], aEdges); + } +} + +@meta.ResourceIdentifier('ICU4XUnitsConverterFactory_destroy') +@ffi.Native)>( + isLeaf: true, symbol: 'ICU4XUnitsConverterFactory_destroy') +// ignore: non_constant_identifier_names +external void _ICU4XUnitsConverterFactory_destroy(ffi.Pointer self); + +@meta.ResourceIdentifier('ICU4XUnitsConverterFactory_create') +@ffi.Native<_ResultOpaqueInt32 Function(ffi.Pointer)>( + isLeaf: true, symbol: 'ICU4XUnitsConverterFactory_create') +// ignore: non_constant_identifier_names +external _ResultOpaqueInt32 _ICU4XUnitsConverterFactory_create( + ffi.Pointer provider); + +@meta.ResourceIdentifier('ICU4XUnitsConverterFactory_converter') +@ffi.Native< + ffi.Pointer Function(ffi.Pointer, + ffi.Pointer, ffi.Pointer)>( + isLeaf: true, symbol: 'ICU4XUnitsConverterFactory_converter') +// ignore: non_constant_identifier_names +external ffi.Pointer _ICU4XUnitsConverterFactory_converter( + ffi.Pointer self, + ffi.Pointer from, + ffi.Pointer to); + +@meta.ResourceIdentifier('ICU4XUnitsConverterFactory_parser') +@ffi.Native Function(ffi.Pointer)>( + isLeaf: true, symbol: 'ICU4XUnitsConverterFactory_parser') +// ignore: non_constant_identifier_names +external ffi.Pointer _ICU4XUnitsConverterFactory_parser( + ffi.Pointer self); diff --git a/pkgs/intl4x/lib/src/bindings/lib.g.dart b/pkgs/intl4x/lib/src/bindings/lib.g.dart index 3b27dc8c..cb9e50df 100644 --- a/pkgs/intl4x/lib/src/bindings/lib.g.dart +++ b/pkgs/intl4x/lib/src/bindings/lib.g.dart @@ -94,6 +94,8 @@ part 'LocaleFallbackSupplement.g.dart'; part 'LocaleFallbacker.g.dart'; part 'LocaleFallbackerWithConfig.g.dart'; part 'Logger.g.dart'; +part 'MeasureUnit.g.dart'; +part 'MeasureUnitParser.g.dart'; part 'MetazoneCalculator.g.dart'; part 'PluralCategories.g.dart'; part 'PluralCategory.g.dart'; @@ -116,11 +118,15 @@ part 'Time.g.dart'; part 'TimeFormatter.g.dart'; part 'TimeLength.g.dart'; part 'TimeZoneFormatter.g.dart'; +part 'TimeZoneIdMapper.g.dart'; +part 'TimeZoneIdMapperWithFastCanonicalization.g.dart'; part 'TitlecaseMapper.g.dart'; part 'TitlecaseOptions.g.dart'; part 'TrailingCase.g.dart'; part 'TransformResult.g.dart'; part 'UnicodeSetData.g.dart'; +part 'UnitsConverter.g.dart'; +part 'UnitsConverterFactory.g.dart'; part 'WeekCalculator.g.dart'; part 'WeekOf.g.dart'; part 'WeekRelativeUnit.g.dart'; diff --git a/pkgs/intl4x/pubspec.yaml b/pkgs/intl4x/pubspec.yaml index 0b875615..a1a444c2 100644 --- a/pkgs/intl4x/pubspec.yaml +++ b/pkgs/intl4x/pubspec.yaml @@ -17,7 +17,7 @@ environment: sdk: ">=3.3.0 <4.0.0" dependencies: - archive: ^3.4.10 + crypto: ^3.0.3 ffi: ^2.1.0 js: ^0.7.1 meta: ^1.12.0 @@ -28,5 +28,4 @@ dev_dependencies: args: ^2.4.2 collection: ^1.18.0 dart_flutter_team_lints: ^3.1.0 - lints: ^4.0.0 test: ^1.22.1 diff --git a/pkgs/intl4x/tool/generate_hashes.dart b/pkgs/intl4x/tool/generate_hashes.dart new file mode 100644 index 00000000..59eefe88 --- /dev/null +++ b/pkgs/intl4x/tool/generate_hashes.dart @@ -0,0 +1,105 @@ +import 'dart:io'; + +import 'package:crypto/crypto.dart'; +import 'package:native_assets_cli/native_assets_cli.dart'; + +import '../hook/version.dart'; + +final httpClient = HttpClient(); + +Future main(List args) async { + final mode = args.firstOrNull; + String folder() => args[1]; + + print('Checking hashes for $version'); + final fileHashes = <(OS, Architecture), String>{}; + final dynamicLibrary = File.fromUri(Directory.systemTemp.uri.resolve('lib')); + await dynamicLibrary.create(); + for (final os in OS.values) { + for (final architecture in Architecture.values) { + final target = '${os}_$architecture'; + print('Checking hash for $target'); + final bool success; + if (mode == 'fetch' || mode == null) { + success = await _fetchLibrary(target, httpClient, dynamicLibrary); + } else if (mode == 'local') { + success = await _copyLibrary(target, folder(), dynamicLibrary); + } else { + throw UnsupportedError('Mode must be fetch or local'); + } + if (success) { + final bytes = await dynamicLibrary.readAsBytes(); + final fileHash = sha256.convert(bytes).toString(); + fileHashes[(os, architecture)] = fileHash; + print('Hash is $fileHash'); + } else { + print('Could not get library'); + } + } + } + httpClient.close(force: true); + + await File('hook/hashes.dart').writeAsString(''' +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// THIS FILE IS AUTOGENERATED BY `tool/generate_hashes.dart`. TO UPDATE, RUN +// +// dart --enable-experiment=native-assets run tool/generate_hashes.dart +// + +import 'package:native_assets_cli/native_assets_cli.dart'; + +const fileHashes = <(OS, Architecture), String>{ +${fileHashes.map((key, value) => MapEntry( + ('OS.${key.$1.varName}', 'Architecture.${key.$2}'), + "'$value'", + )).entries.map( + (e) => ' ${e.key}:\n ${e.value}', + ).join(',\n')} +}; +'''); +} + +Future _copyLibrary( + String target, + String folder, + File dynamicLibrary, +) async { + final fileUri = Directory.current.uri.resolve(folder).resolve(target); + final file = File.fromUri(fileUri); + print('Copy file from ${fileUri.toFilePath()} to ${dynamicLibrary.path}'); + if (await file.exists()) { + await file.copy(dynamicLibrary.path); + return true; + } + return false; +} + +Future _fetchLibrary( + String target, HttpClient httpClient, File dynamicLibrary) async { + final uri = Uri.parse( + 'https://github.com/dart-lang/i18n/releases/download/$version/$target'); + print('Fetch file from $uri'); + final request = await httpClient.getUrl(uri); + final response = await request.close(); + if (response.statusCode != 200) { + print('File not found at $uri'); + return false; + } + await response.pipe(dynamicLibrary.openWrite()); + return true; +} + +extension OSExt on OS { + String get varName => switch (this) { + OS.linux => 'linux', + OS.windows => 'windows', + OS.fuchsia => 'fuchsia', + OS.android => 'android', + OS.macOS => 'macOS', + OS.iOS => 'iOS', + OS() => throw UnimplementedError(), + }; +} From 965ccf9d2f1f280a36652eda8d4a92fcb2b4f419 Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 24 Jul 2024 17:00:52 +0200 Subject: [PATCH 02/26] Set version to newest tag --- pkgs/intl4x/hook/version.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/intl4x/hook/version.dart b/pkgs/intl4x/hook/version.dart index 1e94fda8..9a1803af 100644 --- a/pkgs/intl4x/hook/version.dart +++ b/pkgs/intl4x/hook/version.dart @@ -2,4 +2,4 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -const version = 'intl4x-v.0.9.2-artifacts'; +const version = 'intl4x-icu-v.0.9.2-artifacts'; From 880bec391942132bac814e0b599207ccda8e6b17 Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 24 Jul 2024 17:19:24 +0200 Subject: [PATCH 03/26] Reset hashes --- .github/workflows/intl4x_artifacts.yml | 10 ++++++++-- pkgs/intl4x/hook/hashes.dart | 6 +++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.github/workflows/intl4x_artifacts.yml b/.github/workflows/intl4x_artifacts.yml index 8d28bdef..9ca3a1bc 100644 --- a/.github/workflows/intl4x_artifacts.yml +++ b/.github/workflows/intl4x_artifacts.yml @@ -145,7 +145,7 @@ jobs: name: dart-${{matrix.os}}-libs path: submodules/icu4x/bin - check_hashes: + check_hashes_local: needs: dart-libs if: github.event_name == 'pull_request' runs-on: ubuntu-latest @@ -164,7 +164,7 @@ jobs: - name: Display structure of downloaded files run: ls -R - - name: Check hashes against recomputed ones + - name: Check hashes of locally built artifacts run: | cd pkgs/intl4x dart pub get @@ -208,6 +208,12 @@ jobs: with: sdk: dev + - name: Check hashes of released artifacts + run: | + dart --enable-experiment=native-assets tool/generate_hashes.dart + git diff --name-only --exit-code + if: ${{matrix.os == 'ubuntu-latest'}} + - run: | cd pkgs/intl4x dart pub get diff --git a/pkgs/intl4x/hook/hashes.dart b/pkgs/intl4x/hook/hashes.dart index 9ae3d6de..4f5ab628 100644 --- a/pkgs/intl4x/hook/hashes.dart +++ b/pkgs/intl4x/hook/hashes.dart @@ -37,9 +37,9 @@ const fileHashes = <(OS, Architecture), String>{ (OS.macOS, Architecture.x64): '19b7f6614f5b5603629f4cedc7891f1d7ec6e27699f9ce7d6fedcd0204f5cc03', (OS.windows, Architecture.arm64): - '15502b3f71d4947ea9a91cb3ad6b123f915c75bf3c8f63c0befe7a10b24ccbd9', + 'a270cfc9fa0ef40365c61f87f6b34a1a5ff1185c38dcc795a71e953ea8ca2a6a', (OS.windows, Architecture.ia32): - '8fec764279d157cec54fb2b40af9adcb19936e9d413ef5d608c00f42e51b1e53', + 'c9a84f023227e19924bbf3c78cf4309b9e5ace6d34a1be55d669c27cbb4a4efc', (OS.windows, Architecture.x64): - 'b223858026d6c893fff035df1382e6e2703c328e512b432aaf88b90a5b8b91b9' + '0b172c58ea610f7412de11d1257c14358c5b8c7694ff59a0d1536dd51ade1241' }; From ffdc5403435897227da64d4418fcb1cc70c77a24 Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 24 Jul 2024 17:21:44 +0200 Subject: [PATCH 04/26] Remove checking from intl4x build --- .github/workflows/intl4x.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/intl4x.yml b/.github/workflows/intl4x.yml index 2aa00140..c46dc55f 100644 --- a/.github/workflows/intl4x.yml +++ b/.github/workflows/intl4x.yml @@ -46,11 +46,6 @@ jobs: - run: dart --enable-experiment=native-assets analyze --fatal-infos - - run: | - dart --enable-experiment=native-assets tool/generate_hashes.dart - git diff --name-only --exit-code - if: ${{matrix.sdk == 'dev' && matrix.os == 'ubuntu-latest'}} - - run: dart --enable-experiment=native-assets format --output=none --set-exit-if-changed . if: ${{matrix.run-tests}} From f4e8cedebe533c64c3f661b38685b0c6d5548f5d Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 24 Jul 2024 17:56:18 +0200 Subject: [PATCH 05/26] Fix path --- .github/workflows/intl4x_artifacts.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/intl4x_artifacts.yml b/.github/workflows/intl4x_artifacts.yml index 9ca3a1bc..7a1e7a3f 100644 --- a/.github/workflows/intl4x_artifacts.yml +++ b/.github/workflows/intl4x_artifacts.yml @@ -210,6 +210,7 @@ jobs: - name: Check hashes of released artifacts run: | + cd pkgs/intl4x dart --enable-experiment=native-assets tool/generate_hashes.dart git diff --name-only --exit-code if: ${{matrix.os == 'ubuntu-latest'}} From 374f40563bcf53443529ac40b70fe3713abd8584 Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 24 Jul 2024 18:41:33 +0200 Subject: [PATCH 06/26] Add pub get --- .github/workflows/intl4x_artifacts.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/intl4x_artifacts.yml b/.github/workflows/intl4x_artifacts.yml index 7a1e7a3f..4f39ced7 100644 --- a/.github/workflows/intl4x_artifacts.yml +++ b/.github/workflows/intl4x_artifacts.yml @@ -211,8 +211,9 @@ jobs: - name: Check hashes of released artifacts run: | cd pkgs/intl4x + dart pub get dart --enable-experiment=native-assets tool/generate_hashes.dart - git diff --name-only --exit-code + git diff --exit-code if: ${{matrix.os == 'ubuntu-latest'}} - run: | From 1f93f7fc2a01c0f07fdc0430e05d370f0a9e0c5c Mon Sep 17 00:00:00 2001 From: Moritz Date: Thu, 25 Jul 2024 09:14:31 +0200 Subject: [PATCH 07/26] Do not fail fast --- .github/workflows/intl4x_artifacts.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/intl4x_artifacts.yml b/.github/workflows/intl4x_artifacts.yml index 4f39ced7..0034c07c 100644 --- a/.github/workflows/intl4x_artifacts.yml +++ b/.github/workflows/intl4x_artifacts.yml @@ -149,6 +149,8 @@ jobs: needs: dart-libs if: github.event_name == 'pull_request' runs-on: ubuntu-latest + strategy: + fail-fast: false steps: - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 @@ -179,6 +181,7 @@ jobs: ICU4X_BUILD_MODE: local strategy: + fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] From de100cb4d24cca77cfd4c2dbde954607a18f97fa Mon Sep 17 00:00:00 2001 From: Moritz Date: Thu, 25 Jul 2024 13:16:07 +0200 Subject: [PATCH 08/26] Remove checks for local hashes --- .github/workflows/intl4x_artifacts.yml | 28 -------------------------- 1 file changed, 28 deletions(-) diff --git a/.github/workflows/intl4x_artifacts.yml b/.github/workflows/intl4x_artifacts.yml index 0034c07c..7ef3d00f 100644 --- a/.github/workflows/intl4x_artifacts.yml +++ b/.github/workflows/intl4x_artifacts.yml @@ -145,34 +145,6 @@ jobs: name: dart-${{matrix.os}}-libs path: submodules/icu4x/bin - check_hashes_local: - needs: dart-libs - if: github.event_name == 'pull_request' - runs-on: ubuntu-latest - strategy: - fail-fast: false - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 - with: - sdk: dev - - - name: Download binaries - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e - with: - merge-multiple: true - - - name: Display structure of downloaded files - run: ls -R - - - name: Check hashes of locally built artifacts - run: | - cd pkgs/intl4x - dart pub get - dart --enable-experiment=native-assets tool/generate_hashes.dart local ../.. - git diff --exit-code - build_local: needs: dart-libs runs-on: ${{ matrix.os }} From 0afb237ae7784099c90fbeee680f831257915c12 Mon Sep 17 00:00:00 2001 From: Moritz Date: Thu, 25 Jul 2024 13:19:42 +0200 Subject: [PATCH 09/26] Switch order of execution --- .github/workflows/intl4x_artifacts.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/intl4x_artifacts.yml b/.github/workflows/intl4x_artifacts.yml index 7ef3d00f..9058585c 100644 --- a/.github/workflows/intl4x_artifacts.yml +++ b/.github/workflows/intl4x_artifacts.yml @@ -158,10 +158,6 @@ jobs: os: [ubuntu-latest, windows-latest, macos-latest] steps: - - name: Download binaries - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e - with: - merge-multiple: true - run: echo "LOCAL_ICU4X_BINARY=$(realpath linux_x64)" >> $GITHUB_ENV if: matrix.os == 'ubuntu-latest' @@ -175,6 +171,11 @@ jobs: - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 with: submodules: true + + - name: Download binaries + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e + with: + merge-multiple: true - name: Display structure of downloaded files run: ls -R From 1423c3acdf1018254c1717f1536b815acab85449 Mon Sep 17 00:00:00 2001 From: Moritz Date: Thu, 25 Jul 2024 14:00:42 +0200 Subject: [PATCH 10/26] Fix setting envs --- .github/workflows/intl4x_artifacts.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/intl4x_artifacts.yml b/.github/workflows/intl4x_artifacts.yml index 9058585c..4fe2815a 100644 --- a/.github/workflows/intl4x_artifacts.yml +++ b/.github/workflows/intl4x_artifacts.yml @@ -159,19 +159,19 @@ jobs: steps: - - run: echo "LOCAL_ICU4X_BINARY=$(realpath linux_x64)" >> $GITHUB_ENV + - run: export LOCAL_ICU4X_BINARY=$(realpath linux_x64) if: matrix.os == 'ubuntu-latest' - - run: echo "LOCAL_ICU4X_BINARY=$(realpath macos_x64)" >> $GITHUB_ENV + - run: export LOCAL_ICU4X_BINARY=$(realpath macos_x64) if: matrix.os == 'macos-latest' - - run: echo "LOCAL_ICU4X_BINARY=$(realpath windows_x64)" >> $GITHUB_ENV + - run: $env:LOCAL_ICU4X_BINARY = $(realpath windows_x64) if: matrix.os == 'windows-latest' - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 with: submodules: true - + - name: Download binaries uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e with: From 6c80c3af187f1f2ce0449b4ca57f5b5eab7c4017 Mon Sep 17 00:00:00 2001 From: Moritz Date: Thu, 25 Jul 2024 14:19:31 +0200 Subject: [PATCH 11/26] Cleaner separation --- .github/workflows/intl4x.yml | 107 ++++++++++++++++++++++++- .github/workflows/intl4x_artifacts.yml | 28 +------ pkgs/intl4x/tool/generate_hashes.dart | 29 +------ 3 files changed, 110 insertions(+), 54 deletions(-) diff --git a/.github/workflows/intl4x.yml b/.github/workflows/intl4x.yml index c46dc55f..a8b7642d 100644 --- a/.github/workflows/intl4x.yml +++ b/.github/workflows/intl4x.yml @@ -16,7 +16,7 @@ on: - cron: '0 0 * * 0' # weekly jobs: - build: + build_checkout: runs-on: ${{ matrix.os }} env: @@ -81,3 +81,108 @@ jobs: - run: dart --enable-experiment=native-assets pub get - run: dart --enable-experiment=native-assets test + + build_local: + name: Build Dart binaries + strategy: + fail-fast: false + matrix: + os: [ ubuntu-latest, macos-latest, windows-latest ] + runs-on: ${{ matrix.os }} + + env: + ICU4X_BUILD_MODE: local + + steps: + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + with: + submodules: true + + - name: Install Rust toolchains + run: | + rustup toolchain install stable + + - name: Show the selected Rust toolchain + run: rustup show + + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + with: + sdk: dev + + - name: Build Linux + if: matrix.os == 'ubuntu-latest' + run: | + cd submodules/icu4x + + mkdir bin + + cd ffi/dart + dart pub get + cd ../.. + dart run ffi/dart/tool/build_libs.dart bin/linux_x64 linux_x64 dynamic default_components,experimental_components + + cargo run -p icu_datagen -- --locales full --keys all --format blob --out bin/full.postcard + + cd provider/datagen # avoid global feature resolution + rustup target add x86_64-unknown-linux-gnu + cargo build --release --bin icu4x-datagen --no-default-features --features bin,blob_exporter,blob_input,rayon,experimental_components --target x86_64-unknown-linux-gnu + cd ../.. + + cp target/aarch64-unknown-linux-gnu/release/icu4x-datagen bin/linux_arm64-datagen + cp target/riscv64gc-unknown-linux-gnu/release/icu4x-datagen bin/linux_riscv64-datagen + cp target/x86_64-unknown-linux-gnu/release/icu4x-datagen bin/linux_x64-datagen + + - name: Build Mac + if: matrix.os == 'macos-latest' + run: | + cd submodules/icu4x + + mkdir bin + + cd ffi/dart + dart pub get + cd ../.. + dart run ffi/dart/tool/build_libs.dart bin/macos_x64 macos_x64 dynamic default_components,experimental_components + + cd provider/datagen # avoid global feature resolution + rustup target add x86_64-apple-darwin + cargo build --release --bin icu4x-datagen --no-default-features --features bin,blob_exporter,blob_input,rayon,experimental_components --target x86_64-apple-darwin + cd ../.. + + cp target/x86_64-apple-darwin/release/icu4x-datagen bin/macos_x64-datagen + + - name: Build Windows + if: matrix.os == 'windows-latest' + run: | + cd submodules/icu4x + + mkdir bin + + cd ffi/dart + dart pub get + cd ../.. + dart run ffi/dart/tool/build_libs.dart bin/windows_x64 windows_x64 dynamic default_components,experimental_components + + cd provider/datagen # avoid global feature resolution + rustup target add x86_64-pc-windows-msvc + cargo build --release --bin icu4x-datagen --no-default-features --features bin,blob_exporter,blob_input,rayon,experimental_components --target x86_64-pc-windows-msvc + cd ../.. + + cp target/x86_64-pc-windows-msvc/release/icu4x-datagen.exe bin/windows_x64-datagen.exe + + - run: export LOCAL_ICU4X_BINARY=$(realpath bin/linux_x64) + if: matrix.os == 'ubuntu-latest' + + - run: export LOCAL_ICU4X_BINARY=$(realpath bin/macos_x64) + if: matrix.os == 'macos-latest' + + - run: $env:LOCAL_ICU4X_BINARY = $(realpath bin/windows_x64) + if: matrix.os == 'windows-latest' + + - run: | + cd pkgs/intl4x + dart pub get + + - run: | + cd pkgs/intl4x + dart --enable-experiment=native-assets test \ No newline at end of file diff --git a/.github/workflows/intl4x_artifacts.yml b/.github/workflows/intl4x_artifacts.yml index 4fe2815a..c8f56e57 100644 --- a/.github/workflows/intl4x_artifacts.yml +++ b/.github/workflows/intl4x_artifacts.yml @@ -145,29 +145,14 @@ jobs: name: dart-${{matrix.os}}-libs path: submodules/icu4x/bin - build_local: + check_hashes: needs: dart-libs - runs-on: ${{ matrix.os }} + runs-on: ubuntu-latest env: ICU4X_BUILD_MODE: local - - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, windows-latest, macos-latest] steps: - - - run: export LOCAL_ICU4X_BINARY=$(realpath linux_x64) - if: matrix.os == 'ubuntu-latest' - - - run: export LOCAL_ICU4X_BINARY=$(realpath macos_x64) - if: matrix.os == 'macos-latest' - - - run: $env:LOCAL_ICU4X_BINARY = $(realpath windows_x64) - if: matrix.os == 'windows-latest' - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 with: submodules: true @@ -190,15 +175,6 @@ jobs: dart pub get dart --enable-experiment=native-assets tool/generate_hashes.dart git diff --exit-code - if: ${{matrix.os == 'ubuntu-latest'}} - - - run: | - cd pkgs/intl4x - dart pub get - - - run: | - cd pkgs/intl4x - dart --enable-experiment=native-assets test release: needs: dart-libs diff --git a/pkgs/intl4x/tool/generate_hashes.dart b/pkgs/intl4x/tool/generate_hashes.dart index 59eefe88..4d7ad828 100644 --- a/pkgs/intl4x/tool/generate_hashes.dart +++ b/pkgs/intl4x/tool/generate_hashes.dart @@ -8,9 +8,6 @@ import '../hook/version.dart'; final httpClient = HttpClient(); Future main(List args) async { - final mode = args.firstOrNull; - String folder() => args[1]; - print('Checking hashes for $version'); final fileHashes = <(OS, Architecture), String>{}; final dynamicLibrary = File.fromUri(Directory.systemTemp.uri.resolve('lib')); @@ -19,21 +16,14 @@ Future main(List args) async { for (final architecture in Architecture.values) { final target = '${os}_$architecture'; print('Checking hash for $target'); - final bool success; - if (mode == 'fetch' || mode == null) { - success = await _fetchLibrary(target, httpClient, dynamicLibrary); - } else if (mode == 'local') { - success = await _copyLibrary(target, folder(), dynamicLibrary); - } else { - throw UnsupportedError('Mode must be fetch or local'); - } + final success = await _fetchLibrary(target, httpClient, dynamicLibrary); if (success) { final bytes = await dynamicLibrary.readAsBytes(); final fileHash = sha256.convert(bytes).toString(); fileHashes[(os, architecture)] = fileHash; print('Hash is $fileHash'); } else { - print('Could not get library'); + print('Could not fetch library'); } } } @@ -62,21 +52,6 @@ ${fileHashes.map((key, value) => MapEntry( '''); } -Future _copyLibrary( - String target, - String folder, - File dynamicLibrary, -) async { - final fileUri = Directory.current.uri.resolve(folder).resolve(target); - final file = File.fromUri(fileUri); - print('Copy file from ${fileUri.toFilePath()} to ${dynamicLibrary.path}'); - if (await file.exists()) { - await file.copy(dynamicLibrary.path); - return true; - } - return false; -} - Future _fetchLibrary( String target, HttpClient httpClient, File dynamicLibrary) async { final uri = Uri.parse( From c68cdc08bf1015ed7ae52cd9e88f1a5034176017 Mon Sep 17 00:00:00 2001 From: Moritz Date: Thu, 25 Jul 2024 14:22:15 +0200 Subject: [PATCH 12/26] Remove unused --- .github/workflows/intl4x.yml | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/.github/workflows/intl4x.yml b/.github/workflows/intl4x.yml index a8b7642d..36529681 100644 --- a/.github/workflows/intl4x.yml +++ b/.github/workflows/intl4x.yml @@ -121,17 +121,6 @@ jobs: cd ../.. dart run ffi/dart/tool/build_libs.dart bin/linux_x64 linux_x64 dynamic default_components,experimental_components - cargo run -p icu_datagen -- --locales full --keys all --format blob --out bin/full.postcard - - cd provider/datagen # avoid global feature resolution - rustup target add x86_64-unknown-linux-gnu - cargo build --release --bin icu4x-datagen --no-default-features --features bin,blob_exporter,blob_input,rayon,experimental_components --target x86_64-unknown-linux-gnu - cd ../.. - - cp target/aarch64-unknown-linux-gnu/release/icu4x-datagen bin/linux_arm64-datagen - cp target/riscv64gc-unknown-linux-gnu/release/icu4x-datagen bin/linux_riscv64-datagen - cp target/x86_64-unknown-linux-gnu/release/icu4x-datagen bin/linux_x64-datagen - - name: Build Mac if: matrix.os == 'macos-latest' run: | @@ -144,13 +133,6 @@ jobs: cd ../.. dart run ffi/dart/tool/build_libs.dart bin/macos_x64 macos_x64 dynamic default_components,experimental_components - cd provider/datagen # avoid global feature resolution - rustup target add x86_64-apple-darwin - cargo build --release --bin icu4x-datagen --no-default-features --features bin,blob_exporter,blob_input,rayon,experimental_components --target x86_64-apple-darwin - cd ../.. - - cp target/x86_64-apple-darwin/release/icu4x-datagen bin/macos_x64-datagen - - name: Build Windows if: matrix.os == 'windows-latest' run: | @@ -163,13 +145,6 @@ jobs: cd ../.. dart run ffi/dart/tool/build_libs.dart bin/windows_x64 windows_x64 dynamic default_components,experimental_components - cd provider/datagen # avoid global feature resolution - rustup target add x86_64-pc-windows-msvc - cargo build --release --bin icu4x-datagen --no-default-features --features bin,blob_exporter,blob_input,rayon,experimental_components --target x86_64-pc-windows-msvc - cd ../.. - - cp target/x86_64-pc-windows-msvc/release/icu4x-datagen.exe bin/windows_x64-datagen.exe - - run: export LOCAL_ICU4X_BINARY=$(realpath bin/linux_x64) if: matrix.os == 'ubuntu-latest' From 755151ef9424cdba48671787e0f428cd91bcc123 Mon Sep 17 00:00:00 2001 From: Moritz Date: Thu, 25 Jul 2024 14:25:55 +0200 Subject: [PATCH 13/26] Fix paths --- .github/workflows/intl4x.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/intl4x.yml b/.github/workflows/intl4x.yml index 36529681..176c8293 100644 --- a/.github/workflows/intl4x.yml +++ b/.github/workflows/intl4x.yml @@ -145,13 +145,13 @@ jobs: cd ../.. dart run ffi/dart/tool/build_libs.dart bin/windows_x64 windows_x64 dynamic default_components,experimental_components - - run: export LOCAL_ICU4X_BINARY=$(realpath bin/linux_x64) + - run: export LOCAL_ICU4X_BINARY=$(realpath submodules/icu4x/bin/linux_x64) if: matrix.os == 'ubuntu-latest' - - run: export LOCAL_ICU4X_BINARY=$(realpath bin/macos_x64) + - run: export LOCAL_ICU4X_BINARY=$(realpath submodules/icu4x/bin/macos_x64) if: matrix.os == 'macos-latest' - - run: $env:LOCAL_ICU4X_BINARY = $(realpath bin/windows_x64) + - run: $env:LOCAL_ICU4X_BINARY = $(realpath submodules/icu4x/bin/windows_x64) if: matrix.os == 'windows-latest' - run: | From c9e6e6eb866e9f12286956cfe39816a60c423ee2 Mon Sep 17 00:00:00 2001 From: Moritz Date: Thu, 25 Jul 2024 14:37:23 +0200 Subject: [PATCH 14/26] Try different env setter --- .github/workflows/intl4x.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/intl4x.yml b/.github/workflows/intl4x.yml index 176c8293..9b391ffb 100644 --- a/.github/workflows/intl4x.yml +++ b/.github/workflows/intl4x.yml @@ -145,14 +145,17 @@ jobs: cd ../.. dart run ffi/dart/tool/build_libs.dart bin/windows_x64 windows_x64 dynamic default_components,experimental_components - - run: export LOCAL_ICU4X_BINARY=$(realpath submodules/icu4x/bin/linux_x64) + - run: echo "LOCAL_ICU4X_BINARY=$(realpath submodules/icu4x/bin/linux_x64)" >> $GITHUB_ENV if: matrix.os == 'ubuntu-latest' - - run: export LOCAL_ICU4X_BINARY=$(realpath submodules/icu4x/bin/macos_x64) + - run: echo "LOCAL_ICU4X_BINARY=$(realpath submodules/icu4x/bin/macos_x64)" >> $GITHUB_ENV if: matrix.os == 'macos-latest' - - run: $env:LOCAL_ICU4X_BINARY = $(realpath submodules/icu4x/bin/windows_x64) + - run: echo "LOCAL_ICU4X_BINARY=$(realpath submodules/icu4x/bin/windows_x64)" >> $GITHUB_ENV if: matrix.os == 'windows-latest' + + - name: Display structure of downloaded files + run: ls -R - run: | cd pkgs/intl4x From 411719fc9867ccb433b91a0b6571f26a0183431a Mon Sep 17 00:00:00 2001 From: Moritz Date: Thu, 25 Jul 2024 14:43:03 +0200 Subject: [PATCH 15/26] Compile to arm --- .github/workflows/intl4x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/intl4x.yml b/.github/workflows/intl4x.yml index 9b391ffb..77316cb0 100644 --- a/.github/workflows/intl4x.yml +++ b/.github/workflows/intl4x.yml @@ -131,7 +131,7 @@ jobs: cd ffi/dart dart pub get cd ../.. - dart run ffi/dart/tool/build_libs.dart bin/macos_x64 macos_x64 dynamic default_components,experimental_components + dart run ffi/dart/tool/build_libs.dart bin/macos_arm64 macos_arm64 dynamic default_components,experimental_components - name: Build Windows if: matrix.os == 'windows-latest' From 0dc089fc2931fb0f9c611d2c8e7ee93672533234 Mon Sep 17 00:00:00 2001 From: Moritz Date: Thu, 25 Jul 2024 14:47:10 +0200 Subject: [PATCH 16/26] Add nicer check for LOCAL_ICU4X_BINARY --- pkgs/intl4x/hook/build.dart | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/pkgs/intl4x/hook/build.dart b/pkgs/intl4x/hook/build.dart index cd64b2b6..894436ce 100644 --- a/pkgs/intl4x/hook/build.dart +++ b/pkgs/intl4x/hook/build.dart @@ -104,7 +104,16 @@ final class FetchMode implements BuildMode { } final class LocalMode implements BuildMode { - String get _localBinaryPath => Platform.environment['LOCAL_ICU4X_BINARY']!; + String get _localBinaryPath { + final localPath = Platform.environment['LOCAL_ICU4X_BINARY']; + if (localPath != null) { + return localPath; + } + throw ArgumentError('`LOCAL_ICU4X_BINARY` is empty. ' + 'If the `ICU4X_BUILD_MODE` is set to `local`, the ' + '`LOCAL_ICU4X_BINARY` environment variable must contain the path to ' + 'the binary.'); + } @override Future build() async => Uri.file(_localBinaryPath); From 47e656ea279e36c8321e786a3dce5c4cbc4043aa Mon Sep 17 00:00:00 2001 From: Moritz Date: Thu, 25 Jul 2024 14:48:44 +0200 Subject: [PATCH 17/26] Try different env for win --- .github/workflows/intl4x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/intl4x.yml b/.github/workflows/intl4x.yml index 77316cb0..0dbe928e 100644 --- a/.github/workflows/intl4x.yml +++ b/.github/workflows/intl4x.yml @@ -151,7 +151,7 @@ jobs: - run: echo "LOCAL_ICU4X_BINARY=$(realpath submodules/icu4x/bin/macos_x64)" >> $GITHUB_ENV if: matrix.os == 'macos-latest' - - run: echo "LOCAL_ICU4X_BINARY=$(realpath submodules/icu4x/bin/windows_x64)" >> $GITHUB_ENV + - run: echo ("LOCAL_ICU4X_BINARY=" + $(realpath submodules/icu4x/bin/windows_x64)) >> $env:GITHUB_ENV if: matrix.os == 'windows-latest' - name: Display structure of downloaded files From 6ab7cbe5d29c779f97a6513352769d73246ed449 Mon Sep 17 00:00:00 2001 From: Moritz Date: Thu, 25 Jul 2024 14:52:49 +0200 Subject: [PATCH 18/26] Point to correct macos --- .github/workflows/intl4x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/intl4x.yml b/.github/workflows/intl4x.yml index 0dbe928e..59ec27ff 100644 --- a/.github/workflows/intl4x.yml +++ b/.github/workflows/intl4x.yml @@ -148,7 +148,7 @@ jobs: - run: echo "LOCAL_ICU4X_BINARY=$(realpath submodules/icu4x/bin/linux_x64)" >> $GITHUB_ENV if: matrix.os == 'ubuntu-latest' - - run: echo "LOCAL_ICU4X_BINARY=$(realpath submodules/icu4x/bin/macos_x64)" >> $GITHUB_ENV + - run: echo "LOCAL_ICU4X_BINARY=$(realpath submodules/icu4x/bin/macos_arm64)" >> $GITHUB_ENV if: matrix.os == 'macos-latest' - run: echo ("LOCAL_ICU4X_BINARY=" + $(realpath submodules/icu4x/bin/windows_x64)) >> $env:GITHUB_ENV From b640cbd29f83f2f582a0464e09ab9365f6bbc0df Mon Sep 17 00:00:00 2001 From: Moritz Date: Thu, 25 Jul 2024 14:59:33 +0200 Subject: [PATCH 19/26] Path seperators --- .github/workflows/intl4x.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/intl4x.yml b/.github/workflows/intl4x.yml index 59ec27ff..ebaa1eb1 100644 --- a/.github/workflows/intl4x.yml +++ b/.github/workflows/intl4x.yml @@ -83,7 +83,6 @@ jobs: - run: dart --enable-experiment=native-assets test build_local: - name: Build Dart binaries strategy: fail-fast: false matrix: @@ -151,7 +150,7 @@ jobs: - run: echo "LOCAL_ICU4X_BINARY=$(realpath submodules/icu4x/bin/macos_arm64)" >> $GITHUB_ENV if: matrix.os == 'macos-latest' - - run: echo ("LOCAL_ICU4X_BINARY=" + $(realpath submodules/icu4x/bin/windows_x64)) >> $env:GITHUB_ENV + - run: echo ("LOCAL_ICU4X_BINARY=" + $(realpath submodules\icu4x\bin\windows_x64)) >> $env:GITHUB_ENV if: matrix.os == 'windows-latest' - name: Display structure of downloaded files From 19e949207b99fb3d86d08f9976463172bc77393a Mon Sep 17 00:00:00 2001 From: Moritz Date: Thu, 25 Jul 2024 15:08:20 +0200 Subject: [PATCH 20/26] replace slashes --- .github/workflows/intl4x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/intl4x.yml b/.github/workflows/intl4x.yml index ebaa1eb1..ddfeb133 100644 --- a/.github/workflows/intl4x.yml +++ b/.github/workflows/intl4x.yml @@ -150,7 +150,7 @@ jobs: - run: echo "LOCAL_ICU4X_BINARY=$(realpath submodules/icu4x/bin/macos_arm64)" >> $GITHUB_ENV if: matrix.os == 'macos-latest' - - run: echo ("LOCAL_ICU4X_BINARY=" + $(realpath submodules\icu4x\bin\windows_x64)) >> $env:GITHUB_ENV + - run: echo ("LOCAL_ICU4X_BINARY=" + $(realpath submodules\icu4x\bin\windows_x64) -replace '/', '\') >> $env:GITHUB_ENV if: matrix.os == 'windows-latest' - name: Display structure of downloaded files From 5c0ce72a28fe85fdedc567c8c216f23f487d441a Mon Sep 17 00:00:00 2001 From: Moritz Date: Thu, 25 Jul 2024 15:15:11 +0200 Subject: [PATCH 21/26] try something different --- .github/workflows/intl4x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/intl4x.yml b/.github/workflows/intl4x.yml index ddfeb133..5d00216d 100644 --- a/.github/workflows/intl4x.yml +++ b/.github/workflows/intl4x.yml @@ -150,7 +150,7 @@ jobs: - run: echo "LOCAL_ICU4X_BINARY=$(realpath submodules/icu4x/bin/macos_arm64)" >> $GITHUB_ENV if: matrix.os == 'macos-latest' - - run: echo ("LOCAL_ICU4X_BINARY=" + $(realpath submodules\icu4x\bin\windows_x64) -replace '/', '\') >> $env:GITHUB_ENV + - run: echo ("LOCAL_ICU4X_BINARY=" + (Get-Item submodules\icu4x\bin\windows_x64 | Resolve-Path -Relative) -replace '/', '\') >> $env:GITHUB_ENV if: matrix.os == 'windows-latest' - name: Display structure of downloaded files From 310e0af03481e95ef61476c35351396b6cf1b373 Mon Sep 17 00:00:00 2001 From: Moritz Date: Thu, 25 Jul 2024 15:21:25 +0200 Subject: [PATCH 22/26] non relative --- .github/workflows/intl4x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/intl4x.yml b/.github/workflows/intl4x.yml index 5d00216d..94e800cc 100644 --- a/.github/workflows/intl4x.yml +++ b/.github/workflows/intl4x.yml @@ -150,7 +150,7 @@ jobs: - run: echo "LOCAL_ICU4X_BINARY=$(realpath submodules/icu4x/bin/macos_arm64)" >> $GITHUB_ENV if: matrix.os == 'macos-latest' - - run: echo ("LOCAL_ICU4X_BINARY=" + (Get-Item submodules\icu4x\bin\windows_x64 | Resolve-Path -Relative) -replace '/', '\') >> $env:GITHUB_ENV + - run: echo ("LOCAL_ICU4X_BINARY=" + (Get-Item submodules\icu4x\bin\windows_x64 | Resolve-Path ) -replace '/', '\') >> $env:GITHUB_ENV if: matrix.os == 'windows-latest' - name: Display structure of downloaded files From 2e3d8b74df16e70e26043ce2983f4e281c60739f Mon Sep 17 00:00:00 2001 From: Moritz Date: Thu, 25 Jul 2024 15:27:05 +0200 Subject: [PATCH 23/26] More tryes --- .github/workflows/intl4x.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/intl4x.yml b/.github/workflows/intl4x.yml index 94e800cc..1f71a309 100644 --- a/.github/workflows/intl4x.yml +++ b/.github/workflows/intl4x.yml @@ -150,8 +150,10 @@ jobs: - run: echo "LOCAL_ICU4X_BINARY=$(realpath submodules/icu4x/bin/macos_arm64)" >> $GITHUB_ENV if: matrix.os == 'macos-latest' - - run: echo ("LOCAL_ICU4X_BINARY=" + (Get-Item submodules\icu4x\bin\windows_x64 | Resolve-Path ) -replace '/', '\') >> $env:GITHUB_ENV + - run: echo ("LOCAL_ICU4X_BINARY=" + (Get-Item submodules\icu4x\bin\windows_x64).FullName -replace '/', '\') >> $env:GITHUB_ENV if: matrix.os == 'windows-latest' + + - run: echo $LOCAL_ICU4X_BINARY - name: Display structure of downloaded files run: ls -R From bfdb85d312fe788de878a50cf098241cd7dc400b Mon Sep 17 00:00:00 2001 From: Moritz Date: Thu, 25 Jul 2024 15:39:44 +0200 Subject: [PATCH 24/26] Copy local file --- pkgs/intl4x/hook/build.dart | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/pkgs/intl4x/hook/build.dart b/pkgs/intl4x/hook/build.dart index 894436ce..8c13e0e9 100644 --- a/pkgs/intl4x/hook/build.dart +++ b/pkgs/intl4x/hook/build.dart @@ -21,7 +21,7 @@ void main(List args) async { await build(args, (config, output) async { final environmentBuildMode = Platform.environment[env]; final buildMode = switch (environmentBuildMode) { - 'local' => LocalMode(), + 'local' => LocalMode(config), 'checkout' => CheckoutMode(config), 'fetch' || null => FetchMode(config), String() => throw ArgumentError(''' @@ -58,15 +58,17 @@ Unknown build mode for icu4x. Set the `ICU4X_BUILD_MODE` environment variable wi } sealed class BuildMode { + final BuildConfig config; + + const BuildMode(this.config); + List get dependencies; Future build(); } -final class FetchMode implements BuildMode { - final BuildConfig config; - - FetchMode(this.config); +final class FetchMode extends BuildMode { + FetchMode(super.config); @override Future build() async { @@ -103,7 +105,9 @@ final class FetchMode implements BuildMode { List get dependencies => []; } -final class LocalMode implements BuildMode { +final class LocalMode extends BuildMode { + LocalMode(super.config); + String get _localBinaryPath { final localPath = Platform.environment['LOCAL_ICU4X_BINARY']; if (localPath != null) { @@ -116,16 +120,23 @@ final class LocalMode implements BuildMode { } @override - Future build() async => Uri.file(_localBinaryPath); + Future build() async { + final dylibFileName = config.targetOS.dylibFileName('icu4x'); + final dylibFileUri = config.outputDirectory.resolve(dylibFileName); + final file = File(_localBinaryPath); + if (!(await file.exists())) { + throw FileSystemException('Could not find binary.', _localBinaryPath); + } + await file.copy(dylibFileUri.toFilePath(windows: Platform.isWindows)); + return dylibFileUri; + } @override List get dependencies => [Uri.file(_localBinaryPath)]; } -final class CheckoutMode implements BuildMode { - final BuildConfig config; - - CheckoutMode(this.config); +final class CheckoutMode extends BuildMode { + CheckoutMode(super.config); String? get workingDirectory => Platform.environment['LOCAL_ICU4X_CHECKOUT']; From 97240b07b24878418a2e96225c5fab5fff8b754a Mon Sep 17 00:00:00 2001 From: Moritz Date: Thu, 25 Jul 2024 17:06:00 +0200 Subject: [PATCH 25/26] Add newline --- .gitattributes | 2 +- .github/workflows/intl4x.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitattributes b/.gitattributes index e856410e..f5ba2502 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1 @@ -pkgs/intl4x/lib/src/bindings linguist-generated=true +pkgs/intl4x/lib/src/bindings/ linguist-generated=true diff --git a/.github/workflows/intl4x.yml b/.github/workflows/intl4x.yml index 1f71a309..4aa4d942 100644 --- a/.github/workflows/intl4x.yml +++ b/.github/workflows/intl4x.yml @@ -164,4 +164,4 @@ jobs: - run: | cd pkgs/intl4x - dart --enable-experiment=native-assets test \ No newline at end of file + dart --enable-experiment=native-assets test From 228106cac8db377d772501ca2aa740061f4194f9 Mon Sep 17 00:00:00 2001 From: Moritz Date: Thu, 25 Jul 2024 17:06:42 +0200 Subject: [PATCH 26/26] Add wildcard --- .gitattributes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitattributes b/.gitattributes index f5ba2502..3c11f2a9 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1 @@ -pkgs/intl4x/lib/src/bindings/ linguist-generated=true +pkgs/intl4x/lib/src/bindings/* linguist-generated=true