fix: create zig errror wrapper
This commit is contained in:
parent
49eb1f4901
commit
9283912529
3 changed files with 68 additions and 20 deletions
|
|
@ -216,27 +216,27 @@ fn roundWithProvider(self: Duration, options: RoundingOptions, relative_to: Rela
|
||||||
/// Compare two durations (Temporal.Duration.compare).
|
/// Compare two durations (Temporal.Duration.compare).
|
||||||
pub fn compare(self: Duration, other: Duration, relative_to: RelativeTo) !i8 {
|
pub fn compare(self: Duration, other: Duration, relative_to: RelativeTo) !i8 {
|
||||||
const res = abi.c.temporal_rs_Duration_compare(self._inner, other._inner, relative_to.toCApi());
|
const res = abi.c.temporal_rs_Duration_compare(self._inner, other._inner, relative_to.toCApi());
|
||||||
return abi.success(res) orelse return error.TemporalError;
|
return try abi.extractResult(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compare two durations with an explicit provider.
|
/// Compare two durations with an explicit provider.
|
||||||
fn compareWithProvider(self: Duration, other: Duration, relative_to: RelativeTo, provider: *const abi.c.Provider) !i8 {
|
fn compareWithProvider(self: Duration, other: Duration, relative_to: RelativeTo, provider: *const abi.c.Provider) !i8 {
|
||||||
const res = abi.c.temporal_rs_Duration_compare_with_provider(self._inner, other._inner, relative_to.toCApi(), provider);
|
const res = abi.c.temporal_rs_Duration_compare_with_provider(self._inner, other._inner, relative_to.toCApi(), provider);
|
||||||
return abi.success(res) orelse return error.TemporalError;
|
return try abi.extractResult(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the total value of the duration in the specified unit (Temporal.Duration.prototype.total).
|
/// Get the total value of the duration in the specified unit (Temporal.Duration.prototype.total).
|
||||||
pub fn total(self: Duration, options: TotalOptions) !f64 {
|
pub fn total(self: Duration, options: TotalOptions) !f64 {
|
||||||
const rel = if (options.relative_to) |r| r.toCApi() else abi.c.RelativeTo{ .date = null, .zoned = null };
|
const rel = if (options.relative_to) |r| r.toCApi() else abi.c.RelativeTo{ .date = null, .zoned = null };
|
||||||
const res = abi.c.temporal_rs_Duration_total(self._inner, options.unit.toCApi(), rel);
|
const res = abi.c.temporal_rs_Duration_total(self._inner, options.unit.toCApi(), rel);
|
||||||
return abi.success(res) orelse return error.TemporalError;
|
return try abi.extractResult(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the total value of the duration with an explicit provider.
|
/// Get the total value of the duration with an explicit provider.
|
||||||
fn totalWithProvider(self: Duration, options: TotalOptions, provider: *const abi.c.Provider) !f64 {
|
fn totalWithProvider(self: Duration, options: TotalOptions, provider: *const abi.c.Provider) !f64 {
|
||||||
const rel = if (options.relative_to) |r| r.toCApi() else abi.c.RelativeTo{ .date = null, .zoned = null };
|
const rel = if (options.relative_to) |r| r.toCApi() else abi.c.RelativeTo{ .date = null, .zoned = null };
|
||||||
const res = abi.c.temporal_rs_Duration_total_with_provider(self._inner, options.unit.toCApi(), rel, provider);
|
const res = abi.c.temporal_rs_Duration_total_with_provider(self._inner, options.unit.toCApi(), rel, provider);
|
||||||
return abi.success(res) orelse return error.TemporalError;
|
return try abi.extractResult(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert to string (Temporal.Duration.prototype.toString); caller owns returned slice.
|
/// Convert to string (Temporal.Duration.prototype.toString); caller owns returned slice.
|
||||||
|
|
@ -272,12 +272,12 @@ pub fn deinit(self: Duration) void {
|
||||||
|
|
||||||
// --- Helpers -----------------------------------------------------------------
|
// --- Helpers -----------------------------------------------------------------
|
||||||
|
|
||||||
fn handleVoidResult(res: anytype) !void {
|
inline fn handleVoidResult(res: anytype) !void {
|
||||||
_ = abi.success(res) orelse return error.TemporalError;
|
_ = try abi.extractResult(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wrapDuration(res: anytype) !Duration {
|
fn wrapDuration(res: anytype) !Duration {
|
||||||
const ptr = (abi.success(res) orelse return error.TemporalError) orelse return error.TemporalError;
|
const ptr = (try abi.extractResult(res)) orelse return abi.TemporalError.Generic;
|
||||||
return .{ ._inner = ptr };
|
return .{ ._inner = ptr };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -431,3 +431,28 @@ test clone {
|
||||||
|
|
||||||
try std.testing.expectEqual(dur.hours(), cloned.hours());
|
try std.testing.expectEqual(dur.hours(), cloned.hours());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test total {
|
||||||
|
{
|
||||||
|
const dur = try Duration.init(0, 0, 0, 0, 1, 30, 0, 0, 0, 0);
|
||||||
|
defer dur.deinit();
|
||||||
|
|
||||||
|
const t = try dur.total(.{ .unit = .hour });
|
||||||
|
try std.testing.expectEqual(1.5, t);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const dur = try Duration.from("PT4H5M6S");
|
||||||
|
defer dur.deinit();
|
||||||
|
|
||||||
|
const t = try dur.total(.{ .unit = .hour });
|
||||||
|
try std.testing.expectEqual(4.085, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Calendar units require relative_to; the C API will return RangeError.
|
||||||
|
const dur = try Duration.from("P1Y");
|
||||||
|
defer dur.deinit();
|
||||||
|
|
||||||
|
try std.testing.expectError(error.RangeError, dur.total(.{ .unit = .day }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -152,13 +152,6 @@ pub fn toZonedDateTime(self: PlainDate, options: ToZonedDateTimeOptions) !ZonedD
|
||||||
const time_ptr = if (options.plain_time) |t| t._inner else null;
|
const time_ptr = if (options.plain_time) |t| t._inner else null;
|
||||||
const ptr = (abi.success(abi.c.temporal_rs_PlainDate_to_zoned_date_time(self._inner, time_zone, time_ptr)) orelse return error.TemporalError) orelse return error.TemporalError;
|
const ptr = (abi.success(abi.c.temporal_rs_PlainDate_to_zoned_date_time(self._inner, time_zone, time_ptr)) orelse return error.TemporalError) orelse return error.TemporalError;
|
||||||
|
|
||||||
// Get time zone identifier for ZonedDateTime
|
|
||||||
// const allocator = std.heap.page_allocator;
|
|
||||||
// var write = abi.DiplomatWrite.init(allocator);
|
|
||||||
// defer write.deinit();
|
|
||||||
// abi.c.temporal_rs_TimeZone_identifier(time_zone, &write.inner);
|
|
||||||
// const tz_id = try write.toOwnedSlice();
|
|
||||||
|
|
||||||
return .{ ._inner = ptr };
|
return .{ ._inner = ptr };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -285,12 +278,6 @@ pub fn deinit(self: PlainDate) void {
|
||||||
fn wrapPlainDate(res: anytype) !PlainDate {
|
fn wrapPlainDate(res: anytype) !PlainDate {
|
||||||
const ptr = (abi.success(res) orelse return error.TemporalError) orelse return error.TemporalError;
|
const ptr = (abi.success(res) orelse return error.TemporalError) orelse return error.TemporalError;
|
||||||
|
|
||||||
// const calendar_ptr = abi.c.temporal_rs_PlainDate_calendar(ptr) orelse return error.TemporalError;
|
|
||||||
// const cal_id_view = abi.c.temporal_rs_Calendar_identifier(calendar_ptr);
|
|
||||||
|
|
||||||
// const allocator = std.heap.page_allocator;
|
|
||||||
// const cal_id = allocator.dupe(u8, cal_id_view.data[0..cal_id_view.len]) catch "iso8601";
|
|
||||||
|
|
||||||
return .{ ._inner = ptr };
|
return .{ ._inner = ptr };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
36
src/abi.zig
36
src/abi.zig
|
|
@ -261,3 +261,39 @@ pub fn Success(comptime Result: type) type {
|
||||||
if (!@hasField(Union, "ok")) return void;
|
if (!@hasField(Union, "ok")) return void;
|
||||||
return @FieldType(Union, "ok");
|
return @FieldType(Union, "ok");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Temporal error set mapping to C API error kinds
|
||||||
|
pub const TemporalError = error{
|
||||||
|
/// Generic temporal error
|
||||||
|
Generic,
|
||||||
|
/// Type error (invalid type or conversion)
|
||||||
|
TypeError,
|
||||||
|
/// Range error (value out of valid range)
|
||||||
|
RangeError,
|
||||||
|
/// Syntax error (invalid format or parsing)
|
||||||
|
SyntaxError,
|
||||||
|
/// Assertion failed (should not happen)
|
||||||
|
AssertionFailed,
|
||||||
|
/// Other unspecified error
|
||||||
|
Unknown,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Extract result from C API, mapping errors to specific Zig error types.
|
||||||
|
pub inline fn extractResult(result: anytype) TemporalError!Success(@TypeOf(result)) {
|
||||||
|
if (success(result)) |value| return value;
|
||||||
|
|
||||||
|
const err = result.unnamed_0.err;
|
||||||
|
// const message = if (fromOption(err.msg)) |sv|
|
||||||
|
// fromDiplomatStringView(sv)
|
||||||
|
// else
|
||||||
|
// "(no error message)";
|
||||||
|
|
||||||
|
return switch (err.kind) {
|
||||||
|
c.ErrorKind_Generic => TemporalError.Generic,
|
||||||
|
c.ErrorKind_Type => TemporalError.TypeError,
|
||||||
|
c.ErrorKind_Range => TemporalError.RangeError,
|
||||||
|
c.ErrorKind_Syntax => TemporalError.SyntaxError,
|
||||||
|
c.ErrorKind_Assert => @panic("temporal_rs assertion failed"),
|
||||||
|
else => TemporalError.Unknown,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue