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).
|
||||
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());
|
||||
return abi.success(res) orelse return error.TemporalError;
|
||||
return try abi.extractResult(res);
|
||||
}
|
||||
|
||||
/// Compare two durations with an explicit provider.
|
||||
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);
|
||||
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).
|
||||
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 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.
|
||||
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 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.
|
||||
|
|
@ -272,12 +272,12 @@ pub fn deinit(self: Duration) void {
|
|||
|
||||
// --- Helpers -----------------------------------------------------------------
|
||||
|
||||
fn handleVoidResult(res: anytype) !void {
|
||||
_ = abi.success(res) orelse return error.TemporalError;
|
||||
inline fn handleVoidResult(res: anytype) !void {
|
||||
_ = try abi.extractResult(res);
|
||||
}
|
||||
|
||||
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 };
|
||||
}
|
||||
|
||||
|
|
@ -431,3 +431,28 @@ test clone {
|
|||
|
||||
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 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 };
|
||||
}
|
||||
|
||||
|
|
@ -285,12 +278,6 @@ pub fn deinit(self: PlainDate) void {
|
|||
fn wrapPlainDate(res: anytype) !PlainDate {
|
||||
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 };
|
||||
}
|
||||
|
||||
|
|
|
|||
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;
|
||||
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