From 7bbbe1c0ec03258c8ce311f45602317bfa1d615b Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Fri, 24 Jan 2025 20:56:55 -0800 Subject: [PATCH 01/33] Initial neo datetime FFI PoC --- ffi/capi/bindings/c/DateTimeAlignment.d.h | 23 +++ ffi/capi/bindings/c/DateTimeAlignment.h | 23 +++ ffi/capi/bindings/c/NeoDateTimeFormatter.d.h | 19 +++ ffi/capi/bindings/c/NeoDateTimeFormatter.h | 40 +++++ ffi/capi/bindings/c/NeoDateTimeLength.d.h | 24 +++ ffi/capi/bindings/c/NeoDateTimeLength.h | 23 +++ ffi/capi/bindings/c/TimePrecision.d.h | 34 +++++ ffi/capi/bindings/c/TimePrecision.h | 23 +++ .../cpp/icu4x/DateTimeAlignment.d.hpp | 46 ++++++ .../bindings/cpp/icu4x/DateTimeAlignment.hpp | 37 +++++ .../cpp/icu4x/NeoDateTimeFormatter.d.hpp | 59 ++++++++ .../cpp/icu4x/NeoDateTimeFormatter.hpp | 88 +++++++++++ .../cpp/icu4x/NeoDateTimeLength.d.hpp | 48 ++++++ .../bindings/cpp/icu4x/NeoDateTimeLength.hpp | 38 +++++ .../bindings/cpp/icu4x/TimePrecision.d.hpp | 68 +++++++++ ffi/capi/bindings/cpp/icu4x/TimePrecision.hpp | 48 ++++++ .../bindings/dart/DateTimeAlignment.g.dart | 10 ++ .../bindings/dart/NeoDateTimeFormatter.g.dart | 73 +++++++++ .../bindings/dart/NeoDateTimeLength.g.dart | 12 ++ ffi/capi/bindings/dart/TimePrecision.g.dart | 32 ++++ ffi/capi/bindings/dart/lib.g.dart | 4 + .../demo_gen/NeoDateTimeFormatter.d.ts | 5 + .../demo_gen/NeoDateTimeFormatter.mjs | 42 ++++++ ffi/capi/bindings/demo_gen/index.mjs | 77 ++++++++++ ffi/capi/bindings/js/DateTimeAlignment.d.ts | 22 +++ ffi/capi/bindings/js/DateTimeAlignment.mjs | 70 +++++++++ .../bindings/js/NeoDateTimeFormatter.d.ts | 25 +++ ffi/capi/bindings/js/NeoDateTimeFormatter.mjs | 100 ++++++++++++ ffi/capi/bindings/js/NeoDateTimeLength.d.ts | 23 +++ ffi/capi/bindings/js/NeoDateTimeLength.mjs | 73 +++++++++ ffi/capi/bindings/js/TimePrecision.d.ts | 33 ++++ ffi/capi/bindings/js/TimePrecision.mjs | 103 +++++++++++++ ffi/capi/bindings/js/index.d.ts | 8 + ffi/capi/bindings/js/index.mjs | 8 + ffi/capi/src/lib.rs | 2 + ffi/capi/src/neo_datetime.rs | 142 ++++++++++++++++++ tutorials/cpp/Cargo.lock | 25 ++- tutorials/cpp/datetime.cpp | 27 +++- 38 files changed, 1543 insertions(+), 14 deletions(-) create mode 100644 ffi/capi/bindings/c/DateTimeAlignment.d.h create mode 100644 ffi/capi/bindings/c/DateTimeAlignment.h create mode 100644 ffi/capi/bindings/c/NeoDateTimeFormatter.d.h create mode 100644 ffi/capi/bindings/c/NeoDateTimeFormatter.h create mode 100644 ffi/capi/bindings/c/NeoDateTimeLength.d.h create mode 100644 ffi/capi/bindings/c/NeoDateTimeLength.h create mode 100644 ffi/capi/bindings/c/TimePrecision.d.h create mode 100644 ffi/capi/bindings/c/TimePrecision.h create mode 100644 ffi/capi/bindings/cpp/icu4x/DateTimeAlignment.d.hpp create mode 100644 ffi/capi/bindings/cpp/icu4x/DateTimeAlignment.hpp create mode 100644 ffi/capi/bindings/cpp/icu4x/NeoDateTimeFormatter.d.hpp create mode 100644 ffi/capi/bindings/cpp/icu4x/NeoDateTimeFormatter.hpp create mode 100644 ffi/capi/bindings/cpp/icu4x/NeoDateTimeLength.d.hpp create mode 100644 ffi/capi/bindings/cpp/icu4x/NeoDateTimeLength.hpp create mode 100644 ffi/capi/bindings/cpp/icu4x/TimePrecision.d.hpp create mode 100644 ffi/capi/bindings/cpp/icu4x/TimePrecision.hpp create mode 100644 ffi/capi/bindings/dart/DateTimeAlignment.g.dart create mode 100644 ffi/capi/bindings/dart/NeoDateTimeFormatter.g.dart create mode 100644 ffi/capi/bindings/dart/NeoDateTimeLength.g.dart create mode 100644 ffi/capi/bindings/dart/TimePrecision.g.dart create mode 100644 ffi/capi/bindings/demo_gen/NeoDateTimeFormatter.d.ts create mode 100644 ffi/capi/bindings/demo_gen/NeoDateTimeFormatter.mjs create mode 100644 ffi/capi/bindings/js/DateTimeAlignment.d.ts create mode 100644 ffi/capi/bindings/js/DateTimeAlignment.mjs create mode 100644 ffi/capi/bindings/js/NeoDateTimeFormatter.d.ts create mode 100644 ffi/capi/bindings/js/NeoDateTimeFormatter.mjs create mode 100644 ffi/capi/bindings/js/NeoDateTimeLength.d.ts create mode 100644 ffi/capi/bindings/js/NeoDateTimeLength.mjs create mode 100644 ffi/capi/bindings/js/TimePrecision.d.ts create mode 100644 ffi/capi/bindings/js/TimePrecision.mjs create mode 100644 ffi/capi/src/neo_datetime.rs diff --git a/ffi/capi/bindings/c/DateTimeAlignment.d.h b/ffi/capi/bindings/c/DateTimeAlignment.d.h new file mode 100644 index 00000000000..41ce282be34 --- /dev/null +++ b/ffi/capi/bindings/c/DateTimeAlignment.d.h @@ -0,0 +1,23 @@ +#ifndef DateTimeAlignment_D_H +#define DateTimeAlignment_D_H + +#include +#include +#include +#include +#include "diplomat_runtime.h" + + + + + +typedef enum DateTimeAlignment { + DateTimeAlignment_Auto = 0, + DateTimeAlignment_Column = 1, +} DateTimeAlignment; + +typedef struct DateTimeAlignment_option {union { DateTimeAlignment ok; }; bool is_ok; } DateTimeAlignment_option; + + + +#endif // DateTimeAlignment_D_H diff --git a/ffi/capi/bindings/c/DateTimeAlignment.h b/ffi/capi/bindings/c/DateTimeAlignment.h new file mode 100644 index 00000000000..c718de92a30 --- /dev/null +++ b/ffi/capi/bindings/c/DateTimeAlignment.h @@ -0,0 +1,23 @@ +#ifndef DateTimeAlignment_H +#define DateTimeAlignment_H + +#include +#include +#include +#include +#include "diplomat_runtime.h" + + +#include "DateTimeAlignment.d.h" + + + + + + + + + + + +#endif // DateTimeAlignment_H diff --git a/ffi/capi/bindings/c/NeoDateTimeFormatter.d.h b/ffi/capi/bindings/c/NeoDateTimeFormatter.d.h new file mode 100644 index 00000000000..51254a4150d --- /dev/null +++ b/ffi/capi/bindings/c/NeoDateTimeFormatter.d.h @@ -0,0 +1,19 @@ +#ifndef NeoDateTimeFormatter_D_H +#define NeoDateTimeFormatter_D_H + +#include +#include +#include +#include +#include "diplomat_runtime.h" + + + + + +typedef struct NeoDateTimeFormatter NeoDateTimeFormatter; + + + + +#endif // NeoDateTimeFormatter_D_H diff --git a/ffi/capi/bindings/c/NeoDateTimeFormatter.h b/ffi/capi/bindings/c/NeoDateTimeFormatter.h new file mode 100644 index 00000000000..dd6046db66b --- /dev/null +++ b/ffi/capi/bindings/c/NeoDateTimeFormatter.h @@ -0,0 +1,40 @@ +#ifndef NeoDateTimeFormatter_H +#define NeoDateTimeFormatter_H + +#include +#include +#include +#include +#include "diplomat_runtime.h" + +#include "DateTimeAlignment.d.h" +#include "DateTimeFormatterLoadError.d.h" +#include "IsoDate.d.h" +#include "Locale.d.h" +#include "NeoDateTimeLength.d.h" +#include "Time.d.h" +#include "TimePrecision.d.h" + +#include "NeoDateTimeFormatter.d.h" + + + + + + +typedef struct icu4x_NeoDateTimeFormatter_create_dt_mv1_result {union {NeoDateTimeFormatter* ok; DateTimeFormatterLoadError err;}; bool is_ok;} icu4x_NeoDateTimeFormatter_create_dt_mv1_result; +icu4x_NeoDateTimeFormatter_create_dt_mv1_result icu4x_NeoDateTimeFormatter_create_dt_mv1(const Locale* locale, NeoDateTimeLength length, TimePrecision time_precision, DateTimeAlignment alignment); + +typedef struct icu4x_NeoDateTimeFormatter_create_mdt_mv1_result {union {NeoDateTimeFormatter* ok; DateTimeFormatterLoadError err;}; bool is_ok;} icu4x_NeoDateTimeFormatter_create_mdt_mv1_result; +icu4x_NeoDateTimeFormatter_create_mdt_mv1_result icu4x_NeoDateTimeFormatter_create_mdt_mv1(const Locale* locale, NeoDateTimeLength length, TimePrecision time_precision, DateTimeAlignment alignment); + +void icu4x_NeoDateTimeFormatter_format_iso_mv1(const NeoDateTimeFormatter* self, const IsoDate* date, const Time* time, DiplomatWrite* write); + + +void icu4x_NeoDateTimeFormatter_destroy_mv1(NeoDateTimeFormatter* self); + + + + + +#endif // NeoDateTimeFormatter_H diff --git a/ffi/capi/bindings/c/NeoDateTimeLength.d.h b/ffi/capi/bindings/c/NeoDateTimeLength.d.h new file mode 100644 index 00000000000..92915c70db5 --- /dev/null +++ b/ffi/capi/bindings/c/NeoDateTimeLength.d.h @@ -0,0 +1,24 @@ +#ifndef NeoDateTimeLength_D_H +#define NeoDateTimeLength_D_H + +#include +#include +#include +#include +#include "diplomat_runtime.h" + + + + + +typedef enum NeoDateTimeLength { + NeoDateTimeLength_Long = 0, + NeoDateTimeLength_Medium = 1, + NeoDateTimeLength_Short = 2, +} NeoDateTimeLength; + +typedef struct NeoDateTimeLength_option {union { NeoDateTimeLength ok; }; bool is_ok; } NeoDateTimeLength_option; + + + +#endif // NeoDateTimeLength_D_H diff --git a/ffi/capi/bindings/c/NeoDateTimeLength.h b/ffi/capi/bindings/c/NeoDateTimeLength.h new file mode 100644 index 00000000000..f8738b7cc65 --- /dev/null +++ b/ffi/capi/bindings/c/NeoDateTimeLength.h @@ -0,0 +1,23 @@ +#ifndef NeoDateTimeLength_H +#define NeoDateTimeLength_H + +#include +#include +#include +#include +#include "diplomat_runtime.h" + + +#include "NeoDateTimeLength.d.h" + + + + + + + + + + + +#endif // NeoDateTimeLength_H diff --git a/ffi/capi/bindings/c/TimePrecision.d.h b/ffi/capi/bindings/c/TimePrecision.d.h new file mode 100644 index 00000000000..4b2e8df74f6 --- /dev/null +++ b/ffi/capi/bindings/c/TimePrecision.d.h @@ -0,0 +1,34 @@ +#ifndef TimePrecision_D_H +#define TimePrecision_D_H + +#include +#include +#include +#include +#include "diplomat_runtime.h" + + + + + +typedef enum TimePrecision { + TimePrecision_Hour = 0, + TimePrecision_Minute = 1, + TimePrecision_MinuteOptional = 2, + TimePrecision_Second = 3, + TimePrecision_SecondF1 = 4, + TimePrecision_SecondF2 = 5, + TimePrecision_SecondF3 = 6, + TimePrecision_SecondF4 = 7, + TimePrecision_SecondF5 = 8, + TimePrecision_SecondF6 = 9, + TimePrecision_SecondF7 = 10, + TimePrecision_SecondF8 = 11, + TimePrecision_SecondF9 = 12, +} TimePrecision; + +typedef struct TimePrecision_option {union { TimePrecision ok; }; bool is_ok; } TimePrecision_option; + + + +#endif // TimePrecision_D_H diff --git a/ffi/capi/bindings/c/TimePrecision.h b/ffi/capi/bindings/c/TimePrecision.h new file mode 100644 index 00000000000..9cf06363755 --- /dev/null +++ b/ffi/capi/bindings/c/TimePrecision.h @@ -0,0 +1,23 @@ +#ifndef TimePrecision_H +#define TimePrecision_H + +#include +#include +#include +#include +#include "diplomat_runtime.h" + + +#include "TimePrecision.d.h" + + + + + + + + + + + +#endif // TimePrecision_H diff --git a/ffi/capi/bindings/cpp/icu4x/DateTimeAlignment.d.hpp b/ffi/capi/bindings/cpp/icu4x/DateTimeAlignment.d.hpp new file mode 100644 index 00000000000..b3251d190d5 --- /dev/null +++ b/ffi/capi/bindings/cpp/icu4x/DateTimeAlignment.d.hpp @@ -0,0 +1,46 @@ +#ifndef icu4x_DateTimeAlignment_D_HPP +#define icu4x_DateTimeAlignment_D_HPP + +#include +#include +#include +#include +#include +#include +#include "../diplomat_runtime.hpp" + + +namespace icu4x { +namespace capi { + enum DateTimeAlignment { + DateTimeAlignment_Auto = 0, + DateTimeAlignment_Column = 1, + }; + + typedef struct DateTimeAlignment_option {union { DateTimeAlignment ok; }; bool is_ok; } DateTimeAlignment_option; +} // namespace capi +} // namespace + +namespace icu4x { +class DateTimeAlignment { +public: + enum Value { + Auto = 0, + Column = 1, + }; + + DateTimeAlignment() = default; + // Implicit conversions between enum and ::Value + constexpr DateTimeAlignment(Value v) : value(v) {} + constexpr operator Value() const { return value; } + // Prevent usage as boolean value + explicit operator bool() const = delete; + + inline icu4x::capi::DateTimeAlignment AsFFI() const; + inline static icu4x::DateTimeAlignment FromFFI(icu4x::capi::DateTimeAlignment c_enum); +private: + Value value; +}; + +} // namespace +#endif // icu4x_DateTimeAlignment_D_HPP diff --git a/ffi/capi/bindings/cpp/icu4x/DateTimeAlignment.hpp b/ffi/capi/bindings/cpp/icu4x/DateTimeAlignment.hpp new file mode 100644 index 00000000000..f5362376f2e --- /dev/null +++ b/ffi/capi/bindings/cpp/icu4x/DateTimeAlignment.hpp @@ -0,0 +1,37 @@ +#ifndef icu4x_DateTimeAlignment_HPP +#define icu4x_DateTimeAlignment_HPP + +#include "DateTimeAlignment.d.hpp" + +#include +#include +#include +#include +#include +#include +#include "../diplomat_runtime.hpp" + + +namespace icu4x { +namespace capi { + extern "C" { + + + } // extern "C" +} // namespace capi +} // namespace + +inline icu4x::capi::DateTimeAlignment icu4x::DateTimeAlignment::AsFFI() const { + return static_cast(value); +} + +inline icu4x::DateTimeAlignment icu4x::DateTimeAlignment::FromFFI(icu4x::capi::DateTimeAlignment c_enum) { + switch (c_enum) { + case icu4x::capi::DateTimeAlignment_Auto: + case icu4x::capi::DateTimeAlignment_Column: + return static_cast(c_enum); + default: + abort(); + } +} +#endif // icu4x_DateTimeAlignment_HPP diff --git a/ffi/capi/bindings/cpp/icu4x/NeoDateTimeFormatter.d.hpp b/ffi/capi/bindings/cpp/icu4x/NeoDateTimeFormatter.d.hpp new file mode 100644 index 00000000000..f4e8d041f1d --- /dev/null +++ b/ffi/capi/bindings/cpp/icu4x/NeoDateTimeFormatter.d.hpp @@ -0,0 +1,59 @@ +#ifndef icu4x_NeoDateTimeFormatter_D_HPP +#define icu4x_NeoDateTimeFormatter_D_HPP + +#include +#include +#include +#include +#include +#include +#include "../diplomat_runtime.hpp" + +namespace icu4x { +namespace capi { struct IsoDate; } +class IsoDate; +namespace capi { struct Locale; } +class Locale; +namespace capi { struct NeoDateTimeFormatter; } +class NeoDateTimeFormatter; +namespace capi { struct Time; } +class Time; +class DateTimeAlignment; +class DateTimeFormatterLoadError; +class NeoDateTimeLength; +class TimePrecision; +} + + +namespace icu4x { +namespace capi { + struct NeoDateTimeFormatter; +} // namespace capi +} // namespace + +namespace icu4x { +class NeoDateTimeFormatter { +public: + + inline static diplomat::result, icu4x::DateTimeFormatterLoadError> create_dt(const icu4x::Locale& locale, icu4x::NeoDateTimeLength length, icu4x::TimePrecision time_precision, icu4x::DateTimeAlignment alignment); + + inline static diplomat::result, icu4x::DateTimeFormatterLoadError> create_mdt(const icu4x::Locale& locale, icu4x::NeoDateTimeLength length, icu4x::TimePrecision time_precision, icu4x::DateTimeAlignment alignment); + + inline std::string format_iso(const icu4x::IsoDate& date, const icu4x::Time& time) const; + + inline const icu4x::capi::NeoDateTimeFormatter* AsFFI() const; + inline icu4x::capi::NeoDateTimeFormatter* AsFFI(); + inline static const icu4x::NeoDateTimeFormatter* FromFFI(const icu4x::capi::NeoDateTimeFormatter* ptr); + inline static icu4x::NeoDateTimeFormatter* FromFFI(icu4x::capi::NeoDateTimeFormatter* ptr); + inline static void operator delete(void* ptr); +private: + NeoDateTimeFormatter() = delete; + NeoDateTimeFormatter(const icu4x::NeoDateTimeFormatter&) = delete; + NeoDateTimeFormatter(icu4x::NeoDateTimeFormatter&&) noexcept = delete; + NeoDateTimeFormatter operator=(const icu4x::NeoDateTimeFormatter&) = delete; + NeoDateTimeFormatter operator=(icu4x::NeoDateTimeFormatter&&) noexcept = delete; + static void operator delete[](void*, size_t) = delete; +}; + +} // namespace +#endif // icu4x_NeoDateTimeFormatter_D_HPP diff --git a/ffi/capi/bindings/cpp/icu4x/NeoDateTimeFormatter.hpp b/ffi/capi/bindings/cpp/icu4x/NeoDateTimeFormatter.hpp new file mode 100644 index 00000000000..a5b5ac66829 --- /dev/null +++ b/ffi/capi/bindings/cpp/icu4x/NeoDateTimeFormatter.hpp @@ -0,0 +1,88 @@ +#ifndef icu4x_NeoDateTimeFormatter_HPP +#define icu4x_NeoDateTimeFormatter_HPP + +#include "NeoDateTimeFormatter.d.hpp" + +#include +#include +#include +#include +#include +#include +#include "../diplomat_runtime.hpp" +#include "DateTimeAlignment.hpp" +#include "DateTimeFormatterLoadError.hpp" +#include "IsoDate.hpp" +#include "Locale.hpp" +#include "NeoDateTimeLength.hpp" +#include "Time.hpp" +#include "TimePrecision.hpp" + + +namespace icu4x { +namespace capi { + extern "C" { + + typedef struct icu4x_NeoDateTimeFormatter_create_dt_mv1_result {union {icu4x::capi::NeoDateTimeFormatter* ok; icu4x::capi::DateTimeFormatterLoadError err;}; bool is_ok;} icu4x_NeoDateTimeFormatter_create_dt_mv1_result; + icu4x_NeoDateTimeFormatter_create_dt_mv1_result icu4x_NeoDateTimeFormatter_create_dt_mv1(const icu4x::capi::Locale* locale, icu4x::capi::NeoDateTimeLength length, icu4x::capi::TimePrecision time_precision, icu4x::capi::DateTimeAlignment alignment); + + typedef struct icu4x_NeoDateTimeFormatter_create_mdt_mv1_result {union {icu4x::capi::NeoDateTimeFormatter* ok; icu4x::capi::DateTimeFormatterLoadError err;}; bool is_ok;} icu4x_NeoDateTimeFormatter_create_mdt_mv1_result; + icu4x_NeoDateTimeFormatter_create_mdt_mv1_result icu4x_NeoDateTimeFormatter_create_mdt_mv1(const icu4x::capi::Locale* locale, icu4x::capi::NeoDateTimeLength length, icu4x::capi::TimePrecision time_precision, icu4x::capi::DateTimeAlignment alignment); + + void icu4x_NeoDateTimeFormatter_format_iso_mv1(const icu4x::capi::NeoDateTimeFormatter* self, const icu4x::capi::IsoDate* date, const icu4x::capi::Time* time, diplomat::capi::DiplomatWrite* write); + + + void icu4x_NeoDateTimeFormatter_destroy_mv1(NeoDateTimeFormatter* self); + + } // extern "C" +} // namespace capi +} // namespace + +inline diplomat::result, icu4x::DateTimeFormatterLoadError> icu4x::NeoDateTimeFormatter::create_dt(const icu4x::Locale& locale, icu4x::NeoDateTimeLength length, icu4x::TimePrecision time_precision, icu4x::DateTimeAlignment alignment) { + auto result = icu4x::capi::icu4x_NeoDateTimeFormatter_create_dt_mv1(locale.AsFFI(), + length.AsFFI(), + time_precision.AsFFI(), + alignment.AsFFI()); + return result.is_ok ? diplomat::result, icu4x::DateTimeFormatterLoadError>(diplomat::Ok>(std::unique_ptr(icu4x::NeoDateTimeFormatter::FromFFI(result.ok)))) : diplomat::result, icu4x::DateTimeFormatterLoadError>(diplomat::Err(icu4x::DateTimeFormatterLoadError::FromFFI(result.err))); +} + +inline diplomat::result, icu4x::DateTimeFormatterLoadError> icu4x::NeoDateTimeFormatter::create_mdt(const icu4x::Locale& locale, icu4x::NeoDateTimeLength length, icu4x::TimePrecision time_precision, icu4x::DateTimeAlignment alignment) { + auto result = icu4x::capi::icu4x_NeoDateTimeFormatter_create_mdt_mv1(locale.AsFFI(), + length.AsFFI(), + time_precision.AsFFI(), + alignment.AsFFI()); + return result.is_ok ? diplomat::result, icu4x::DateTimeFormatterLoadError>(diplomat::Ok>(std::unique_ptr(icu4x::NeoDateTimeFormatter::FromFFI(result.ok)))) : diplomat::result, icu4x::DateTimeFormatterLoadError>(diplomat::Err(icu4x::DateTimeFormatterLoadError::FromFFI(result.err))); +} + +inline std::string icu4x::NeoDateTimeFormatter::format_iso(const icu4x::IsoDate& date, const icu4x::Time& time) const { + std::string output; + diplomat::capi::DiplomatWrite write = diplomat::WriteFromString(output); + icu4x::capi::icu4x_NeoDateTimeFormatter_format_iso_mv1(this->AsFFI(), + date.AsFFI(), + time.AsFFI(), + &write); + return output; +} + +inline const icu4x::capi::NeoDateTimeFormatter* icu4x::NeoDateTimeFormatter::AsFFI() const { + return reinterpret_cast(this); +} + +inline icu4x::capi::NeoDateTimeFormatter* icu4x::NeoDateTimeFormatter::AsFFI() { + return reinterpret_cast(this); +} + +inline const icu4x::NeoDateTimeFormatter* icu4x::NeoDateTimeFormatter::FromFFI(const icu4x::capi::NeoDateTimeFormatter* ptr) { + return reinterpret_cast(ptr); +} + +inline icu4x::NeoDateTimeFormatter* icu4x::NeoDateTimeFormatter::FromFFI(icu4x::capi::NeoDateTimeFormatter* ptr) { + return reinterpret_cast(ptr); +} + +inline void icu4x::NeoDateTimeFormatter::operator delete(void* ptr) { + icu4x::capi::icu4x_NeoDateTimeFormatter_destroy_mv1(reinterpret_cast(ptr)); +} + + +#endif // icu4x_NeoDateTimeFormatter_HPP diff --git a/ffi/capi/bindings/cpp/icu4x/NeoDateTimeLength.d.hpp b/ffi/capi/bindings/cpp/icu4x/NeoDateTimeLength.d.hpp new file mode 100644 index 00000000000..26fda837ad8 --- /dev/null +++ b/ffi/capi/bindings/cpp/icu4x/NeoDateTimeLength.d.hpp @@ -0,0 +1,48 @@ +#ifndef icu4x_NeoDateTimeLength_D_HPP +#define icu4x_NeoDateTimeLength_D_HPP + +#include +#include +#include +#include +#include +#include +#include "../diplomat_runtime.hpp" + + +namespace icu4x { +namespace capi { + enum NeoDateTimeLength { + NeoDateTimeLength_Long = 0, + NeoDateTimeLength_Medium = 1, + NeoDateTimeLength_Short = 2, + }; + + typedef struct NeoDateTimeLength_option {union { NeoDateTimeLength ok; }; bool is_ok; } NeoDateTimeLength_option; +} // namespace capi +} // namespace + +namespace icu4x { +class NeoDateTimeLength { +public: + enum Value { + Long = 0, + Medium = 1, + Short = 2, + }; + + NeoDateTimeLength() = default; + // Implicit conversions between enum and ::Value + constexpr NeoDateTimeLength(Value v) : value(v) {} + constexpr operator Value() const { return value; } + // Prevent usage as boolean value + explicit operator bool() const = delete; + + inline icu4x::capi::NeoDateTimeLength AsFFI() const; + inline static icu4x::NeoDateTimeLength FromFFI(icu4x::capi::NeoDateTimeLength c_enum); +private: + Value value; +}; + +} // namespace +#endif // icu4x_NeoDateTimeLength_D_HPP diff --git a/ffi/capi/bindings/cpp/icu4x/NeoDateTimeLength.hpp b/ffi/capi/bindings/cpp/icu4x/NeoDateTimeLength.hpp new file mode 100644 index 00000000000..abb544f6d26 --- /dev/null +++ b/ffi/capi/bindings/cpp/icu4x/NeoDateTimeLength.hpp @@ -0,0 +1,38 @@ +#ifndef icu4x_NeoDateTimeLength_HPP +#define icu4x_NeoDateTimeLength_HPP + +#include "NeoDateTimeLength.d.hpp" + +#include +#include +#include +#include +#include +#include +#include "../diplomat_runtime.hpp" + + +namespace icu4x { +namespace capi { + extern "C" { + + + } // extern "C" +} // namespace capi +} // namespace + +inline icu4x::capi::NeoDateTimeLength icu4x::NeoDateTimeLength::AsFFI() const { + return static_cast(value); +} + +inline icu4x::NeoDateTimeLength icu4x::NeoDateTimeLength::FromFFI(icu4x::capi::NeoDateTimeLength c_enum) { + switch (c_enum) { + case icu4x::capi::NeoDateTimeLength_Long: + case icu4x::capi::NeoDateTimeLength_Medium: + case icu4x::capi::NeoDateTimeLength_Short: + return static_cast(c_enum); + default: + abort(); + } +} +#endif // icu4x_NeoDateTimeLength_HPP diff --git a/ffi/capi/bindings/cpp/icu4x/TimePrecision.d.hpp b/ffi/capi/bindings/cpp/icu4x/TimePrecision.d.hpp new file mode 100644 index 00000000000..cfb8b021218 --- /dev/null +++ b/ffi/capi/bindings/cpp/icu4x/TimePrecision.d.hpp @@ -0,0 +1,68 @@ +#ifndef icu4x_TimePrecision_D_HPP +#define icu4x_TimePrecision_D_HPP + +#include +#include +#include +#include +#include +#include +#include "../diplomat_runtime.hpp" + + +namespace icu4x { +namespace capi { + enum TimePrecision { + TimePrecision_Hour = 0, + TimePrecision_Minute = 1, + TimePrecision_MinuteOptional = 2, + TimePrecision_Second = 3, + TimePrecision_SecondF1 = 4, + TimePrecision_SecondF2 = 5, + TimePrecision_SecondF3 = 6, + TimePrecision_SecondF4 = 7, + TimePrecision_SecondF5 = 8, + TimePrecision_SecondF6 = 9, + TimePrecision_SecondF7 = 10, + TimePrecision_SecondF8 = 11, + TimePrecision_SecondF9 = 12, + }; + + typedef struct TimePrecision_option {union { TimePrecision ok; }; bool is_ok; } TimePrecision_option; +} // namespace capi +} // namespace + +namespace icu4x { +class TimePrecision { +public: + enum Value { + Hour = 0, + Minute = 1, + MinuteOptional = 2, + Second = 3, + SecondF1 = 4, + SecondF2 = 5, + SecondF3 = 6, + SecondF4 = 7, + SecondF5 = 8, + SecondF6 = 9, + SecondF7 = 10, + SecondF8 = 11, + SecondF9 = 12, + }; + + TimePrecision() = default; + // Implicit conversions between enum and ::Value + constexpr TimePrecision(Value v) : value(v) {} + constexpr operator Value() const { return value; } + // Prevent usage as boolean value + explicit operator bool() const = delete; + + inline icu4x::capi::TimePrecision AsFFI() const; + inline static icu4x::TimePrecision FromFFI(icu4x::capi::TimePrecision c_enum); +private: + Value value; +}; + +} // namespace +#endif // icu4x_TimePrecision_D_HPP diff --git a/ffi/capi/bindings/cpp/icu4x/TimePrecision.hpp b/ffi/capi/bindings/cpp/icu4x/TimePrecision.hpp new file mode 100644 index 00000000000..17a6badb8cf --- /dev/null +++ b/ffi/capi/bindings/cpp/icu4x/TimePrecision.hpp @@ -0,0 +1,48 @@ +#ifndef icu4x_TimePrecision_HPP +#define icu4x_TimePrecision_HPP + +#include "TimePrecision.d.hpp" + +#include +#include +#include +#include +#include +#include +#include "../diplomat_runtime.hpp" + + +namespace icu4x { +namespace capi { + extern "C" { + + + } // extern "C" +} // namespace capi +} // namespace + +inline icu4x::capi::TimePrecision icu4x::TimePrecision::AsFFI() const { + return static_cast(value); +} + +inline icu4x::TimePrecision icu4x::TimePrecision::FromFFI(icu4x::capi::TimePrecision c_enum) { + switch (c_enum) { + case icu4x::capi::TimePrecision_Hour: + case icu4x::capi::TimePrecision_Minute: + case icu4x::capi::TimePrecision_MinuteOptional: + case icu4x::capi::TimePrecision_Second: + case icu4x::capi::TimePrecision_SecondF1: + case icu4x::capi::TimePrecision_SecondF2: + case icu4x::capi::TimePrecision_SecondF3: + case icu4x::capi::TimePrecision_SecondF4: + case icu4x::capi::TimePrecision_SecondF5: + case icu4x::capi::TimePrecision_SecondF6: + case icu4x::capi::TimePrecision_SecondF7: + case icu4x::capi::TimePrecision_SecondF8: + case icu4x::capi::TimePrecision_SecondF9: + return static_cast(c_enum); + default: + abort(); + } +} +#endif // icu4x_TimePrecision_HPP diff --git a/ffi/capi/bindings/dart/DateTimeAlignment.g.dart b/ffi/capi/bindings/dart/DateTimeAlignment.g.dart new file mode 100644 index 00000000000..26e333b1e47 --- /dev/null +++ b/ffi/capi/bindings/dart/DateTimeAlignment.g.dart @@ -0,0 +1,10 @@ +// generated by diplomat-tool + +part of 'lib.g.dart'; + +/// See the [Rust documentation for `Alignment`](https://docs.rs/icu/latest/icu/datetime/enum.Alignment.html) for more information. +enum DateTimeAlignment { + auto, + + column; +} diff --git a/ffi/capi/bindings/dart/NeoDateTimeFormatter.g.dart b/ffi/capi/bindings/dart/NeoDateTimeFormatter.g.dart new file mode 100644 index 00000000000..c78b74da828 --- /dev/null +++ b/ffi/capi/bindings/dart/NeoDateTimeFormatter.g.dart @@ -0,0 +1,73 @@ +// generated by diplomat-tool + +part of 'lib.g.dart'; + +/// See the [Rust documentation for `DateTimeFormatter`](https://docs.rs/icu/latest/icu/datetime/type.DateTimeFormatter.html) for more information. +final class NeoDateTimeFormatter 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. + NeoDateTimeFormatter._fromFfi(this._ffi, this._selfEdge) { + if (_selfEdge.isEmpty) { + _finalizer.attach(this, _ffi.cast()); + } + } + + static final _finalizer = ffi.NativeFinalizer(ffi.Native.addressOf(_icu4x_NeoDateTimeFormatter_destroy_mv1)); + + /// See the [Rust documentation for `DT`](https://docs.rs/icu/latest/icu/datetime/fieldsets/struct.DT.html) for more information. + /// + /// Throws [DateTimeFormatterLoadError] on failure. + factory NeoDateTimeFormatter.dt(Locale locale, NeoDateTimeLength length, TimePrecision timePrecision, DateTimeAlignment alignment) { + final result = _icu4x_NeoDateTimeFormatter_create_dt_mv1(locale._ffi, length.index, timePrecision.index, alignment.index); + if (!result.isOk) { + throw DateTimeFormatterLoadError.values.firstWhere((v) => v._ffi == result.union.err); + } + return NeoDateTimeFormatter._fromFfi(result.union.ok, []); + } + + /// See the [Rust documentation for `DT`](https://docs.rs/icu/latest/icu/datetime/fieldsets/struct.DT.html) for more information. + /// + /// Throws [DateTimeFormatterLoadError] on failure. + factory NeoDateTimeFormatter.mdt(Locale locale, NeoDateTimeLength length, TimePrecision timePrecision, DateTimeAlignment alignment) { + final result = _icu4x_NeoDateTimeFormatter_create_mdt_mv1(locale._ffi, length.index, timePrecision.index, alignment.index); + if (!result.isOk) { + throw DateTimeFormatterLoadError.values.firstWhere((v) => v._ffi == result.union.err); + } + return NeoDateTimeFormatter._fromFfi(result.union.ok, []); + } + + /// See the [Rust documentation for `format`](https://docs.rs/icu/latest/icu/datetime/struct.DateTimeFormatter.html#method.format) for more information. + String formatIso(IsoDate date, Time time) { + final write = _Write(); + _icu4x_NeoDateTimeFormatter_format_iso_mv1(_ffi, date._ffi, time._ffi, write._ffi); + return write.finalize(); + } +} + +@meta.RecordUse() +@ffi.Native)>(isLeaf: true, symbol: 'icu4x_NeoDateTimeFormatter_destroy_mv1') +// ignore: non_constant_identifier_names +external void _icu4x_NeoDateTimeFormatter_destroy_mv1(ffi.Pointer self); + +@meta.RecordUse() +@ffi.Native<_ResultOpaqueInt32 Function(ffi.Pointer, ffi.Int32, ffi.Int32, ffi.Int32)>(isLeaf: true, symbol: 'icu4x_NeoDateTimeFormatter_create_dt_mv1') +// ignore: non_constant_identifier_names +external _ResultOpaqueInt32 _icu4x_NeoDateTimeFormatter_create_dt_mv1(ffi.Pointer locale, int length, int timePrecision, int alignment); + +@meta.RecordUse() +@ffi.Native<_ResultOpaqueInt32 Function(ffi.Pointer, ffi.Int32, ffi.Int32, ffi.Int32)>(isLeaf: true, symbol: 'icu4x_NeoDateTimeFormatter_create_mdt_mv1') +// ignore: non_constant_identifier_names +external _ResultOpaqueInt32 _icu4x_NeoDateTimeFormatter_create_mdt_mv1(ffi.Pointer locale, int length, int timePrecision, int alignment); + +@meta.RecordUse() +@ffi.Native, ffi.Pointer, ffi.Pointer, ffi.Pointer)>(isLeaf: true, symbol: 'icu4x_NeoDateTimeFormatter_format_iso_mv1') +// ignore: non_constant_identifier_names +external void _icu4x_NeoDateTimeFormatter_format_iso_mv1(ffi.Pointer self, ffi.Pointer date, ffi.Pointer time, ffi.Pointer write); diff --git a/ffi/capi/bindings/dart/NeoDateTimeLength.g.dart b/ffi/capi/bindings/dart/NeoDateTimeLength.g.dart new file mode 100644 index 00000000000..18669489cd9 --- /dev/null +++ b/ffi/capi/bindings/dart/NeoDateTimeLength.g.dart @@ -0,0 +1,12 @@ +// generated by diplomat-tool + +part of 'lib.g.dart'; + +/// See the [Rust documentation for `Length`](https://docs.rs/icu/latest/icu/datetime/enum.Length.html) for more information. +enum NeoDateTimeLength { + long, + + medium, + + short; +} diff --git a/ffi/capi/bindings/dart/TimePrecision.g.dart b/ffi/capi/bindings/dart/TimePrecision.g.dart new file mode 100644 index 00000000000..ebd90443abc --- /dev/null +++ b/ffi/capi/bindings/dart/TimePrecision.g.dart @@ -0,0 +1,32 @@ +// generated by diplomat-tool + +part of 'lib.g.dart'; + +/// See the [Rust documentation for `TimePrecision`](https://docs.rs/icu/latest/icu/datetime/enum.TimePrecision.html) for more information. +enum TimePrecision { + hour, + + minute, + + minuteOptional, + + second, + + secondF1, + + secondF2, + + secondF3, + + secondF4, + + secondF5, + + secondF6, + + secondF7, + + secondF8, + + secondF9; +} diff --git a/ffi/capi/bindings/dart/lib.g.dart b/ffi/capi/bindings/dart/lib.g.dart index dc0e952d283..2d5602889a3 100644 --- a/ffi/capi/bindings/dart/lib.g.dart +++ b/ffi/capi/bindings/dart/lib.g.dart @@ -47,6 +47,7 @@ part 'DataProvider.g.dart'; part 'Date.g.dart'; part 'DateFormatter.g.dart'; part 'DateTime.g.dart'; +part 'DateTimeAlignment.g.dart'; part 'DateTimeFormatError.g.dart'; part 'DateTimeFormatter.g.dart'; part 'DateTimeFormatterLoadError.g.dart'; @@ -111,6 +112,8 @@ part 'LocaleParseError.g.dart'; part 'Logger.g.dart'; part 'MeasureUnit.g.dart'; part 'MeasureUnitParser.g.dart'; +part 'NeoDateTimeFormatter.g.dart'; +part 'NeoDateTimeLength.g.dart'; part 'PluralCategories.g.dart'; part 'PluralCategory.g.dart'; part 'PluralOperands.g.dart'; @@ -131,6 +134,7 @@ part 'SentenceSegmenter.g.dart'; part 'SignedFixedDecimal.g.dart'; part 'Time.g.dart'; part 'TimeFormatter.g.dart'; +part 'TimePrecision.g.dart'; part 'TimeZoneIdMapper.g.dart'; part 'TimeZoneIdMapperWithFastCanonicalization.g.dart'; part 'TimeZoneInfo.g.dart'; diff --git a/ffi/capi/bindings/demo_gen/NeoDateTimeFormatter.d.ts b/ffi/capi/bindings/demo_gen/NeoDateTimeFormatter.d.ts new file mode 100644 index 00000000000..a3a064bdac7 --- /dev/null +++ b/ffi/capi/bindings/demo_gen/NeoDateTimeFormatter.d.ts @@ -0,0 +1,5 @@ +import { IsoDate } from "icu4x" +import { Locale } from "icu4x" +import { NeoDateTimeFormatter } from "icu4x" +import { Time } from "icu4x" +export function formatIso(name: string, length: NeoDateTimeLength, timePrecision: TimePrecision, alignment: DateTimeAlignment, year: number, month: number, day: number, hour: number, minute: number, second: number, nanosecond: number); diff --git a/ffi/capi/bindings/demo_gen/NeoDateTimeFormatter.mjs b/ffi/capi/bindings/demo_gen/NeoDateTimeFormatter.mjs new file mode 100644 index 00000000000..c803185b68e --- /dev/null +++ b/ffi/capi/bindings/demo_gen/NeoDateTimeFormatter.mjs @@ -0,0 +1,42 @@ +import { IsoDate } from "icu4x" +import { Locale } from "icu4x" +import { NeoDateTimeFormatter } from "icu4x" +import { Time } from "icu4x" +export function formatIso(name, length, timePrecision, alignment, year, month, day, hour, minute, second, nanosecond) { + return (function (...args) { return args[0].formatIso(...args.slice(1)) }).apply( + null, + [ + NeoDateTimeFormatter.createMdt.apply( + null, + [ + Locale.fromString.apply( + null, + [ + name + ] + ), + length, + timePrecision, + alignment + ] + ), + (function (...args) { return new IsoDate(...args) } ).apply( + null, + [ + year, + month, + day + ] + ), + (function (...args) { return new Time(...args) } ).apply( + null, + [ + hour, + minute, + second, + nanosecond + ] + ) + ] + ); +} diff --git a/ffi/capi/bindings/demo_gen/index.mjs b/ffi/capi/bindings/demo_gen/index.mjs index 97bcdd16e81..4c39a4954e7 100644 --- a/ffi/capi/bindings/demo_gen/index.mjs +++ b/ffi/capi/bindings/demo_gen/index.mjs @@ -23,6 +23,8 @@ import * as ListFormatterDemo from "./ListFormatter.mjs"; export * as ListFormatterDemo from "./ListFormatter.mjs"; import * as LocaleDemo from "./Locale.mjs"; export * as LocaleDemo from "./Locale.mjs"; +import * as NeoDateTimeFormatterDemo from "./NeoDateTimeFormatter.mjs"; +export * as NeoDateTimeFormatterDemo from "./NeoDateTimeFormatter.mjs"; import * as ComposingNormalizerDemo from "./ComposingNormalizer.mjs"; export * as ComposingNormalizerDemo from "./ComposingNormalizer.mjs"; import * as DecomposingNormalizerDemo from "./DecomposingNormalizer.mjs"; @@ -803,6 +805,81 @@ let termini = Object.assign({ ] }, + "NeoDateTimeFormatter.formatIso": { + func: NeoDateTimeFormatterDemo.formatIso, + // For avoiding webpacking minifying issues: + funcName: "NeoDateTimeFormatter.formatIso", + parameters: [ + + { + name: "Self:Locale:Name", + type: "string", + typeUse: "string" + }, + + { + name: "Self:Length", + type: "NeoDateTimeLength", + typeUse: "enumerator" + }, + + { + name: "Self:TimePrecision", + type: "TimePrecision", + typeUse: "enumerator" + }, + + { + name: "Self:Alignment", + type: "DateTimeAlignment", + typeUse: "enumerator" + }, + + { + name: "Date:Year", + type: "number", + typeUse: "number" + }, + + { + name: "Date:Month", + type: "number", + typeUse: "number" + }, + + { + name: "Date:Day", + type: "number", + typeUse: "number" + }, + + { + name: "Time:Hour", + type: "number", + typeUse: "number" + }, + + { + name: "Time:Minute", + type: "number", + typeUse: "number" + }, + + { + name: "Time:Second", + type: "number", + typeUse: "number" + }, + + { + name: "Time:Nanosecond", + type: "number", + typeUse: "number" + } + + ] + }, + "ComposingNormalizer.normalize": { func: ComposingNormalizerDemo.normalize, // For avoiding webpacking minifying issues: diff --git a/ffi/capi/bindings/js/DateTimeAlignment.d.ts b/ffi/capi/bindings/js/DateTimeAlignment.d.ts new file mode 100644 index 00000000000..7a782e813ee --- /dev/null +++ b/ffi/capi/bindings/js/DateTimeAlignment.d.ts @@ -0,0 +1,22 @@ +// generated by diplomat-tool +import type { pointer, codepoint } from "./diplomat-runtime.d.ts"; + + +/** See the [Rust documentation for `Alignment`](https://docs.rs/icu/latest/icu/datetime/enum.Alignment.html) for more information. +*/ + + +export class DateTimeAlignment { + + + static fromValue(value : DateTimeAlignment | string) : DateTimeAlignment; + + get value() : string; + + get ffiValue() : number; + + static Auto : DateTimeAlignment; + static Column : DateTimeAlignment; + + constructor(value: DateTimeAlignment | string ); +} \ No newline at end of file diff --git a/ffi/capi/bindings/js/DateTimeAlignment.mjs b/ffi/capi/bindings/js/DateTimeAlignment.mjs new file mode 100644 index 00000000000..cc584453558 --- /dev/null +++ b/ffi/capi/bindings/js/DateTimeAlignment.mjs @@ -0,0 +1,70 @@ +// generated by diplomat-tool +import wasm from "./diplomat-wasm.mjs"; +import * as diplomatRuntime from "./diplomat-runtime.mjs"; + + +/** See the [Rust documentation for `Alignment`](https://docs.rs/icu/latest/icu/datetime/enum.Alignment.html) for more information. +*/ + + +export class DateTimeAlignment { + + #value = undefined; + + static #values = new Map([ + ["Auto", 0], + ["Column", 1] + ]); + + static getAllEntries() { + return DateTimeAlignment.#values.entries(); + } + + #internalConstructor(value) { + if (arguments.length > 1 && arguments[0] === diplomatRuntime.internalConstructor) { + // We pass in two internalConstructor arguments to create *new* + // instances of this type, otherwise the enums are treated as singletons. + if (arguments[1] === diplomatRuntime.internalConstructor ) { + this.#value = arguments[2]; + return this; + } + return DateTimeAlignment.#objectValues[arguments[1]]; + } + + if (value instanceof DateTimeAlignment) { + return value; + } + + let intVal = DateTimeAlignment.#values.get(value); + + // Nullish check, checks for null or undefined + if (intVal != null) { + return DateTimeAlignment.#objectValues[intVal]; + } + + throw TypeError(value + " is not a DateTimeAlignment and does not correspond to any of its enumerator values."); + } + + static fromValue(value) { + return new DateTimeAlignment(value); + } + + get value() { + return [...DateTimeAlignment.#values.keys()][this.#value]; + } + + get ffiValue() { + return this.#value; + } + static #objectValues = [ + new DateTimeAlignment(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 0), + new DateTimeAlignment(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 1), + ]; + + static Auto = DateTimeAlignment.#objectValues[0]; + static Column = DateTimeAlignment.#objectValues[1]; + + constructor(value) { + return this.#internalConstructor(...arguments) + } +} \ No newline at end of file diff --git a/ffi/capi/bindings/js/NeoDateTimeFormatter.d.ts b/ffi/capi/bindings/js/NeoDateTimeFormatter.d.ts new file mode 100644 index 00000000000..74e01fb3a46 --- /dev/null +++ b/ffi/capi/bindings/js/NeoDateTimeFormatter.d.ts @@ -0,0 +1,25 @@ +// generated by diplomat-tool +import type { DateTimeAlignment } from "./DateTimeAlignment" +import type { DateTimeFormatterLoadError } from "./DateTimeFormatterLoadError" +import type { IsoDate } from "./IsoDate" +import type { Locale } from "./Locale" +import type { NeoDateTimeLength } from "./NeoDateTimeLength" +import type { Time } from "./Time" +import type { TimePrecision } from "./TimePrecision" +import type { pointer, codepoint } from "./diplomat-runtime.d.ts"; + + +/** See the [Rust documentation for `DateTimeFormatter`](https://docs.rs/icu/latest/icu/datetime/type.DateTimeFormatter.html) for more information. +*/ + + +export class NeoDateTimeFormatter { + + get ffiValue(): pointer; + + static createDt(locale: Locale, length: NeoDateTimeLength, timePrecision: TimePrecision, alignment: DateTimeAlignment): NeoDateTimeFormatter; + + static createMdt(locale: Locale, length: NeoDateTimeLength, timePrecision: TimePrecision, alignment: DateTimeAlignment): NeoDateTimeFormatter; + + formatIso(date: IsoDate, time: Time): string; +} \ No newline at end of file diff --git a/ffi/capi/bindings/js/NeoDateTimeFormatter.mjs b/ffi/capi/bindings/js/NeoDateTimeFormatter.mjs new file mode 100644 index 00000000000..045cfb3e081 --- /dev/null +++ b/ffi/capi/bindings/js/NeoDateTimeFormatter.mjs @@ -0,0 +1,100 @@ +// generated by diplomat-tool +import { DateTimeAlignment } from "./DateTimeAlignment.mjs" +import { DateTimeFormatterLoadError } from "./DateTimeFormatterLoadError.mjs" +import { IsoDate } from "./IsoDate.mjs" +import { Locale } from "./Locale.mjs" +import { NeoDateTimeLength } from "./NeoDateTimeLength.mjs" +import { Time } from "./Time.mjs" +import { TimePrecision } from "./TimePrecision.mjs" +import wasm from "./diplomat-wasm.mjs"; +import * as diplomatRuntime from "./diplomat-runtime.mjs"; + + +/** See the [Rust documentation for `DateTimeFormatter`](https://docs.rs/icu/latest/icu/datetime/type.DateTimeFormatter.html) for more information. +*/ +const NeoDateTimeFormatter_box_destroy_registry = new FinalizationRegistry((ptr) => { + wasm.icu4x_NeoDateTimeFormatter_destroy_mv1(ptr); +}); + +export class NeoDateTimeFormatter { + + // Internal ptr reference: + #ptr = null; + + // Lifetimes are only to keep dependencies alive. + // Since JS won't garbage collect until there are no incoming edges. + #selfEdge = []; + + #internalConstructor(symbol, ptr, selfEdge) { + if (symbol !== diplomatRuntime.internalConstructor) { + console.error("NeoDateTimeFormatter is an Opaque type. You cannot call its constructor."); + return; + } + + this.#ptr = ptr; + this.#selfEdge = selfEdge; + + // Are we being borrowed? If not, we can register. + if (this.#selfEdge.length === 0) { + NeoDateTimeFormatter_box_destroy_registry.register(this, this.#ptr); + } + + return this; + } + get ffiValue() { + return this.#ptr; + } + + static createDt(locale, length, timePrecision, alignment) { + const diplomatReceive = new diplomatRuntime.DiplomatReceiveBuf(wasm, 5, 4, true); + + const result = wasm.icu4x_NeoDateTimeFormatter_create_dt_mv1(diplomatReceive.buffer, locale.ffiValue, length.ffiValue, timePrecision.ffiValue, alignment.ffiValue); + + try { + if (!diplomatReceive.resultFlag) { + const cause = new DateTimeFormatterLoadError(diplomatRuntime.internalConstructor, diplomatRuntime.enumDiscriminant(wasm, diplomatReceive.buffer)); + throw new globalThis.Error('DateTimeFormatterLoadError: ' + cause.value, { cause }); + } + return new NeoDateTimeFormatter(diplomatRuntime.internalConstructor, diplomatRuntime.ptrRead(wasm, diplomatReceive.buffer), []); + } + + finally { + diplomatReceive.free(); + } + } + + static createMdt(locale, length, timePrecision, alignment) { + const diplomatReceive = new diplomatRuntime.DiplomatReceiveBuf(wasm, 5, 4, true); + + const result = wasm.icu4x_NeoDateTimeFormatter_create_mdt_mv1(diplomatReceive.buffer, locale.ffiValue, length.ffiValue, timePrecision.ffiValue, alignment.ffiValue); + + try { + if (!diplomatReceive.resultFlag) { + const cause = new DateTimeFormatterLoadError(diplomatRuntime.internalConstructor, diplomatRuntime.enumDiscriminant(wasm, diplomatReceive.buffer)); + throw new globalThis.Error('DateTimeFormatterLoadError: ' + cause.value, { cause }); + } + return new NeoDateTimeFormatter(diplomatRuntime.internalConstructor, diplomatRuntime.ptrRead(wasm, diplomatReceive.buffer), []); + } + + finally { + diplomatReceive.free(); + } + } + + formatIso(date, time) { + const write = new diplomatRuntime.DiplomatWriteBuf(wasm); + wasm.icu4x_NeoDateTimeFormatter_format_iso_mv1(this.ffiValue, date.ffiValue, time.ffiValue, write.buffer); + + try { + return write.readString8(); + } + + finally { + write.free(); + } + } + + constructor(symbol, ptr, selfEdge) { + return this.#internalConstructor(...arguments) + } +} \ No newline at end of file diff --git a/ffi/capi/bindings/js/NeoDateTimeLength.d.ts b/ffi/capi/bindings/js/NeoDateTimeLength.d.ts new file mode 100644 index 00000000000..e9b8264d899 --- /dev/null +++ b/ffi/capi/bindings/js/NeoDateTimeLength.d.ts @@ -0,0 +1,23 @@ +// generated by diplomat-tool +import type { pointer, codepoint } from "./diplomat-runtime.d.ts"; + + +/** See the [Rust documentation for `Length`](https://docs.rs/icu/latest/icu/datetime/enum.Length.html) for more information. +*/ + + +export class NeoDateTimeLength { + + + static fromValue(value : NeoDateTimeLength | string) : NeoDateTimeLength; + + get value() : string; + + get ffiValue() : number; + + static Long : NeoDateTimeLength; + static Medium : NeoDateTimeLength; + static Short : NeoDateTimeLength; + + constructor(value: NeoDateTimeLength | string ); +} \ No newline at end of file diff --git a/ffi/capi/bindings/js/NeoDateTimeLength.mjs b/ffi/capi/bindings/js/NeoDateTimeLength.mjs new file mode 100644 index 00000000000..067576a5636 --- /dev/null +++ b/ffi/capi/bindings/js/NeoDateTimeLength.mjs @@ -0,0 +1,73 @@ +// generated by diplomat-tool +import wasm from "./diplomat-wasm.mjs"; +import * as diplomatRuntime from "./diplomat-runtime.mjs"; + + +/** See the [Rust documentation for `Length`](https://docs.rs/icu/latest/icu/datetime/enum.Length.html) for more information. +*/ + + +export class NeoDateTimeLength { + + #value = undefined; + + static #values = new Map([ + ["Long", 0], + ["Medium", 1], + ["Short", 2] + ]); + + static getAllEntries() { + return NeoDateTimeLength.#values.entries(); + } + + #internalConstructor(value) { + if (arguments.length > 1 && arguments[0] === diplomatRuntime.internalConstructor) { + // We pass in two internalConstructor arguments to create *new* + // instances of this type, otherwise the enums are treated as singletons. + if (arguments[1] === diplomatRuntime.internalConstructor ) { + this.#value = arguments[2]; + return this; + } + return NeoDateTimeLength.#objectValues[arguments[1]]; + } + + if (value instanceof NeoDateTimeLength) { + return value; + } + + let intVal = NeoDateTimeLength.#values.get(value); + + // Nullish check, checks for null or undefined + if (intVal != null) { + return NeoDateTimeLength.#objectValues[intVal]; + } + + throw TypeError(value + " is not a NeoDateTimeLength and does not correspond to any of its enumerator values."); + } + + static fromValue(value) { + return new NeoDateTimeLength(value); + } + + get value() { + return [...NeoDateTimeLength.#values.keys()][this.#value]; + } + + get ffiValue() { + return this.#value; + } + static #objectValues = [ + new NeoDateTimeLength(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 0), + new NeoDateTimeLength(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 1), + new NeoDateTimeLength(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 2), + ]; + + static Long = NeoDateTimeLength.#objectValues[0]; + static Medium = NeoDateTimeLength.#objectValues[1]; + static Short = NeoDateTimeLength.#objectValues[2]; + + constructor(value) { + return this.#internalConstructor(...arguments) + } +} \ No newline at end of file diff --git a/ffi/capi/bindings/js/TimePrecision.d.ts b/ffi/capi/bindings/js/TimePrecision.d.ts new file mode 100644 index 00000000000..11792dc1429 --- /dev/null +++ b/ffi/capi/bindings/js/TimePrecision.d.ts @@ -0,0 +1,33 @@ +// generated by diplomat-tool +import type { pointer, codepoint } from "./diplomat-runtime.d.ts"; + + +/** See the [Rust documentation for `TimePrecision`](https://docs.rs/icu/latest/icu/datetime/enum.TimePrecision.html) for more information. +*/ + + +export class TimePrecision { + + + static fromValue(value : TimePrecision | string) : TimePrecision; + + get value() : string; + + get ffiValue() : number; + + static Hour : TimePrecision; + static Minute : TimePrecision; + static MinuteOptional : TimePrecision; + static Second : TimePrecision; + static SecondF1 : TimePrecision; + static SecondF2 : TimePrecision; + static SecondF3 : TimePrecision; + static SecondF4 : TimePrecision; + static SecondF5 : TimePrecision; + static SecondF6 : TimePrecision; + static SecondF7 : TimePrecision; + static SecondF8 : TimePrecision; + static SecondF9 : TimePrecision; + + constructor(value: TimePrecision | string ); +} \ No newline at end of file diff --git a/ffi/capi/bindings/js/TimePrecision.mjs b/ffi/capi/bindings/js/TimePrecision.mjs new file mode 100644 index 00000000000..6d6e7418e48 --- /dev/null +++ b/ffi/capi/bindings/js/TimePrecision.mjs @@ -0,0 +1,103 @@ +// generated by diplomat-tool +import wasm from "./diplomat-wasm.mjs"; +import * as diplomatRuntime from "./diplomat-runtime.mjs"; + + +/** See the [Rust documentation for `TimePrecision`](https://docs.rs/icu/latest/icu/datetime/enum.TimePrecision.html) for more information. +*/ + + +export class TimePrecision { + + #value = undefined; + + static #values = new Map([ + ["Hour", 0], + ["Minute", 1], + ["MinuteOptional", 2], + ["Second", 3], + ["SecondF1", 4], + ["SecondF2", 5], + ["SecondF3", 6], + ["SecondF4", 7], + ["SecondF5", 8], + ["SecondF6", 9], + ["SecondF7", 10], + ["SecondF8", 11], + ["SecondF9", 12] + ]); + + static getAllEntries() { + return TimePrecision.#values.entries(); + } + + #internalConstructor(value) { + if (arguments.length > 1 && arguments[0] === diplomatRuntime.internalConstructor) { + // We pass in two internalConstructor arguments to create *new* + // instances of this type, otherwise the enums are treated as singletons. + if (arguments[1] === diplomatRuntime.internalConstructor ) { + this.#value = arguments[2]; + return this; + } + return TimePrecision.#objectValues[arguments[1]]; + } + + if (value instanceof TimePrecision) { + return value; + } + + let intVal = TimePrecision.#values.get(value); + + // Nullish check, checks for null or undefined + if (intVal != null) { + return TimePrecision.#objectValues[intVal]; + } + + throw TypeError(value + " is not a TimePrecision and does not correspond to any of its enumerator values."); + } + + static fromValue(value) { + return new TimePrecision(value); + } + + get value() { + return [...TimePrecision.#values.keys()][this.#value]; + } + + get ffiValue() { + return this.#value; + } + static #objectValues = [ + new TimePrecision(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 0), + new TimePrecision(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 1), + new TimePrecision(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 2), + new TimePrecision(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 3), + new TimePrecision(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 4), + new TimePrecision(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 5), + new TimePrecision(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 6), + new TimePrecision(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 7), + new TimePrecision(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 8), + new TimePrecision(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 9), + new TimePrecision(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 10), + new TimePrecision(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 11), + new TimePrecision(diplomatRuntime.internalConstructor, diplomatRuntime.internalConstructor, 12), + ]; + + static Hour = TimePrecision.#objectValues[0]; + static Minute = TimePrecision.#objectValues[1]; + static MinuteOptional = TimePrecision.#objectValues[2]; + static Second = TimePrecision.#objectValues[3]; + static SecondF1 = TimePrecision.#objectValues[4]; + static SecondF2 = TimePrecision.#objectValues[5]; + static SecondF3 = TimePrecision.#objectValues[6]; + static SecondF4 = TimePrecision.#objectValues[7]; + static SecondF5 = TimePrecision.#objectValues[8]; + static SecondF6 = TimePrecision.#objectValues[9]; + static SecondF7 = TimePrecision.#objectValues[10]; + static SecondF8 = TimePrecision.#objectValues[11]; + static SecondF9 = TimePrecision.#objectValues[12]; + + constructor(value) { + return this.#internalConstructor(...arguments) + } +} \ No newline at end of file diff --git a/ffi/capi/bindings/js/index.d.ts b/ffi/capi/bindings/js/index.d.ts index 7eca3d7037d..b082406de81 100644 --- a/ffi/capi/bindings/js/index.d.ts +++ b/ffi/capi/bindings/js/index.d.ts @@ -100,6 +100,8 @@ export { LocaleDirectionality } from "./LocaleDirectionality" export { Logger } from "./Logger" +export { NeoDateTimeFormatter } from "./NeoDateTimeFormatter" + export { ComposingNormalizer } from "./ComposingNormalizer" export { DecomposingNormalizer } from "./DecomposingNormalizer" @@ -256,6 +258,12 @@ export { TransformResult } from "./TransformResult" export { LocaleDirection } from "./LocaleDirection" +export { DateTimeAlignment } from "./DateTimeAlignment" + +export { NeoDateTimeLength } from "./NeoDateTimeLength" + +export { TimePrecision } from "./TimePrecision" + export { PluralCategory } from "./PluralCategory" export { BidiClass } from "./BidiClass" diff --git a/ffi/capi/bindings/js/index.mjs b/ffi/capi/bindings/js/index.mjs index 2014d72a028..920c4607684 100644 --- a/ffi/capi/bindings/js/index.mjs +++ b/ffi/capi/bindings/js/index.mjs @@ -98,6 +98,8 @@ export { LocaleDirectionality } from "./LocaleDirectionality.mjs" export { Logger } from "./Logger.mjs" +export { NeoDateTimeFormatter } from "./NeoDateTimeFormatter.mjs" + export { ComposingNormalizer } from "./ComposingNormalizer.mjs" export { DecomposingNormalizer } from "./DecomposingNormalizer.mjs" @@ -254,6 +256,12 @@ export { TransformResult } from "./TransformResult.mjs" export { LocaleDirection } from "./LocaleDirection.mjs" +export { DateTimeAlignment } from "./DateTimeAlignment.mjs" + +export { NeoDateTimeLength } from "./NeoDateTimeLength.mjs" + +export { TimePrecision } from "./TimePrecision.mjs" + export { PluralCategory } from "./PluralCategory.mjs" export { BidiClass } from "./BidiClass.mjs" diff --git a/ffi/capi/src/lib.rs b/ffi/capi/src/lib.rs index 063bac8aaae..346ff7f7ee8 100644 --- a/ffi/capi/src/lib.rs +++ b/ffi/capi/src/lib.rs @@ -98,6 +98,8 @@ pub mod list; pub mod locale; #[cfg(feature = "locale")] pub mod locale_directionality; +#[cfg(feature = "datetime")] +pub mod neo_datetime; #[cfg(feature = "normalizer")] pub mod normalizer; #[cfg(feature = "normalizer")] diff --git a/ffi/capi/src/neo_datetime.rs b/ffi/capi/src/neo_datetime.rs new file mode 100644 index 00000000000..369102aebf4 --- /dev/null +++ b/ffi/capi/src/neo_datetime.rs @@ -0,0 +1,142 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use icu_datetime::options::FractionalSecondDigits; + +#[diplomat::bridge] +#[diplomat::abi_rename = "icu4x_{0}_mv1"] +#[diplomat::attr(auto, namespace = "icu4x")] +pub mod ffi { + use icu_datetime::fieldsets::enums::CompositeDateTimeFieldSet; + use writeable::Writeable; + + use crate::{date::ffi::IsoDate, time::ffi::Time}; + + #[cfg(any(feature = "compiled_data", feature = "buffer_provider"))] + use crate::{errors::ffi::DateTimeFormatterLoadError, locale_core::ffi::Locale}; + + #[diplomat::enum_convert(icu_datetime::options::Length, needs_wildcard)] + #[diplomat::rust_link(icu::datetime::Length, Enum)] + pub enum NeoDateTimeLength { + Long, + Medium, + Short, + } + + #[diplomat::enum_convert(icu_datetime::options::Alignment, needs_wildcard)] + #[diplomat::rust_link(icu::datetime::Alignment, Enum)] + pub enum DateTimeAlignment { + Auto, + Column, + } + + #[diplomat::rust_link(icu::datetime::TimePrecision, Enum)] + pub enum TimePrecision { + Hour, + Minute, + MinuteOptional, + Second, + SecondF1, + SecondF2, + SecondF3, + SecondF4, + SecondF5, + SecondF6, + SecondF7, + SecondF8, + SecondF9, + } + + #[diplomat::opaque] + #[diplomat::rust_link(icu::datetime::DateTimeFormatter, Typedef)] + pub struct NeoDateTimeFormatter(pub icu_datetime::DateTimeFormatter); + + impl NeoDateTimeFormatter { + #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor = "dt")] + #[diplomat::rust_link(icu::datetime::fieldsets::DT, Struct)] + #[cfg(feature = "compiled_data")] + pub fn create_dt( + locale: &Locale, + length: NeoDateTimeLength, + time_precision: TimePrecision, + alignment: DateTimeAlignment, + ) -> Result, DateTimeFormatterLoadError> { + let prefs = (&locale.0).into(); + let options = icu_datetime::fieldsets::DT::with_length(length.into()) + .with_alignment(alignment.into()) + .with_time_precision(time_precision.into()); + Ok(Box::new(NeoDateTimeFormatter( + icu_datetime::DateTimeFormatter::try_new(prefs, options)?.with_fset(), + ))) + } + + #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor = "mdt")] + #[diplomat::rust_link(icu::datetime::fieldsets::DT, Struct)] + #[diplomat::demo(default_constructor)] + #[cfg(feature = "compiled_data")] + pub fn create_mdt( + locale: &Locale, + length: NeoDateTimeLength, + time_precision: TimePrecision, + alignment: DateTimeAlignment, + ) -> Result, DateTimeFormatterLoadError> { + let prefs = (&locale.0).into(); + let options = icu_datetime::fieldsets::MDT::with_length(length.into()) + .with_alignment(alignment.into()) + .with_time_precision(time_precision.into()); + Ok(Box::new(NeoDateTimeFormatter( + icu_datetime::DateTimeFormatter::try_new(prefs, options)?.with_fset(), + ))) + } + + #[diplomat::rust_link(icu::datetime::DateTimeFormatter::format, FnInStruct)] + #[diplomat::rust_link(icu::datetime::FormattedDateTime, Struct, hidden)] + pub fn format_iso(&self, date: &IsoDate, time: &Time, write: &mut diplomat_runtime::DiplomatWrite) { + let value = icu_timezone::DateTime { + date: date.0, + time: time.0 + }; + let _infallible = self.0.format(&value).write_to(write); + } + } +} + +impl From for icu_datetime::options::TimePrecision { + fn from(time_precision: ffi::TimePrecision) -> Self { + use icu_datetime::options::TimePrecision; + match time_precision { + ffi::TimePrecision::Hour => TimePrecision::Hour, + ffi::TimePrecision::Minute => TimePrecision::Minute, + ffi::TimePrecision::MinuteOptional => TimePrecision::MinuteOptional, + ffi::TimePrecision::Second => TimePrecision::Second, + ffi::TimePrecision::SecondF1 => { + TimePrecision::FractionalSecond(FractionalSecondDigits::F1) + } + ffi::TimePrecision::SecondF2 => { + TimePrecision::FractionalSecond(FractionalSecondDigits::F2) + } + ffi::TimePrecision::SecondF3 => { + TimePrecision::FractionalSecond(FractionalSecondDigits::F3) + } + ffi::TimePrecision::SecondF4 => { + TimePrecision::FractionalSecond(FractionalSecondDigits::F4) + } + ffi::TimePrecision::SecondF5 => { + TimePrecision::FractionalSecond(FractionalSecondDigits::F5) + } + ffi::TimePrecision::SecondF6 => { + TimePrecision::FractionalSecond(FractionalSecondDigits::F6) + } + ffi::TimePrecision::SecondF7 => { + TimePrecision::FractionalSecond(FractionalSecondDigits::F7) + } + ffi::TimePrecision::SecondF8 => { + TimePrecision::FractionalSecond(FractionalSecondDigits::F8) + } + ffi::TimePrecision::SecondF9 => { + TimePrecision::FractionalSecond(FractionalSecondDigits::F9) + } + } + } +} diff --git a/tutorials/cpp/Cargo.lock b/tutorials/cpp/Cargo.lock index b99c97a74b3..9a34ec938a9 100644 --- a/tutorials/cpp/Cargo.lock +++ b/tutorials/cpp/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "autocfg" @@ -53,8 +53,7 @@ dependencies = [ [[package]] name = "diplomat" version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef0c3a613b09df83bdd42393cd532830a795053102f87461fca1726999829c60" +source = "git+https://github.com/rust-diplomat/diplomat?rev=22aa0436637544f78f8ce0f3e6300aec8dd40a0e#22aa0436637544f78f8ce0f3e6300aec8dd40a0e" dependencies = [ "diplomat_core", "proc-macro2", @@ -65,8 +64,7 @@ dependencies = [ [[package]] name = "diplomat-runtime" version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc1708f176e12755d6d6571ad9b0ebbd3b428223b5cdf63a38eecf1479c13e70" +source = "git+https://github.com/rust-diplomat/diplomat?rev=22aa0436637544f78f8ce0f3e6300aec8dd40a0e#22aa0436637544f78f8ce0f3e6300aec8dd40a0e" dependencies = [ "log", ] @@ -74,8 +72,7 @@ dependencies = [ [[package]] name = "diplomat_core" version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58e5ba87fee6b8b9dcc575cfbc84ae97b8b9f891fa27f670996a4684e20bd178" +source = "git+https://github.com/rust-diplomat/diplomat?rev=22aa0436637544f78f8ce0f3e6300aec8dd40a0e#22aa0436637544f78f8ce0f3e6300aec8dd40a0e" dependencies = [ "proc-macro2", "quote", @@ -529,6 +526,7 @@ version = "2.0.0-beta1" dependencies = [ "displaydoc", "icu_provider", + "icu_provider_registry", "serde", "serde-json-core", ] @@ -542,6 +540,10 @@ dependencies = [ "syn", ] +[[package]] +name = "icu_provider_registry" +version = "2.0.0-beta1" + [[package]] name = "icu_segmenter" version = "2.0.0-beta1" @@ -575,6 +577,7 @@ dependencies = [ "icu_calendar", "icu_provider", "icu_timezone_data", + "ixdtf", "serde", "tinystr", "writeable", @@ -708,7 +711,7 @@ dependencies = [ [[package]] name = "potential_utf" -version = "0.1.0" +version = "0.1.1-dev" dependencies = [ "serde", "writeable", @@ -1055,7 +1058,7 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.0" +version = "0.11.1-dev" dependencies = [ "serde", "yoke", @@ -1124,10 +1127,6 @@ version = "0.2.0" name = "icu_provider_export" version = "2.0.0-beta1" -[[patch.unused]] -name = "icu_provider_registry" -version = "2.0.0-beta1" - [[patch.unused]] name = "icu_provider_source" version = "2.0.0-beta1" diff --git a/tutorials/cpp/datetime.cpp b/tutorials/cpp/datetime.cpp index 7036d01b072..2ef6eb75014 100644 --- a/tutorials/cpp/datetime.cpp +++ b/tutorials/cpp/datetime.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -24,11 +25,35 @@ int main() { std::unique_ptr locale = Locale::from_string("es").ok().value(); std::cout << "Running test for locale " << locale->to_string() << std::endl; + bool saw_unexpected_output = false; + std::unique_ptr date = IsoDate::create(2022, 07, 11).ok().value(); std::unique_ptr