test: check props
This commit is contained in:
parent
cffa94146e
commit
e42982deda
2 changed files with 58 additions and 23 deletions
|
|
@ -2,7 +2,7 @@ const std = @import("std");
|
||||||
|
|
||||||
const Instant = @This();
|
const Instant = @This();
|
||||||
|
|
||||||
inner: *CInstant,
|
_inner: *CInstant,
|
||||||
epochMilliseconds: i64,
|
epochMilliseconds: i64,
|
||||||
epochNanoseconds: i128,
|
epochNanoseconds: i128,
|
||||||
|
|
||||||
|
|
@ -36,37 +36,37 @@ fn fromUtf16(text: []const u16) !Instant {
|
||||||
|
|
||||||
/// Add a Duration to this instant (Temporal.Instant.prototype.add).
|
/// Add a Duration to this instant (Temporal.Instant.prototype.add).
|
||||||
pub fn add(self: Instant, duration: *const Duration) !Instant {
|
pub fn add(self: Instant, duration: *const Duration) !Instant {
|
||||||
return wrapInstant(temporal_rs_Instant_add(self.inner, duration));
|
return wrapInstant(temporal_rs_Instant_add(self._inner, duration));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Subtract a Duration from this instant (Temporal.Instant.prototype.subtract).
|
/// Subtract a Duration from this instant (Temporal.Instant.prototype.subtract).
|
||||||
pub fn subtract(self: Instant, duration: *const Duration) !Instant {
|
pub fn subtract(self: Instant, duration: *const Duration) !Instant {
|
||||||
return wrapInstant(temporal_rs_Instant_subtract(self.inner, duration));
|
return wrapInstant(temporal_rs_Instant_subtract(self._inner, duration));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Difference until another instant (Temporal.Instant.prototype.until).
|
/// Difference until another instant (Temporal.Instant.prototype.until).
|
||||||
pub fn until(self: Instant, other: Instant, settings: DifferenceSettings) !DurationHandle {
|
pub fn until(self: Instant, other: Instant, settings: DifferenceSettings) !DurationHandle {
|
||||||
return wrapDuration(temporal_rs_Instant_until(self.inner, other.inner, settings));
|
return wrapDuration(temporal_rs_Instant_until(self._inner, other._inner, settings));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Difference since another instant (Temporal.Instant.prototype.since).
|
/// Difference since another instant (Temporal.Instant.prototype.since).
|
||||||
pub fn since(self: Instant, other: Instant, settings: DifferenceSettings) !DurationHandle {
|
pub fn since(self: Instant, other: Instant, settings: DifferenceSettings) !DurationHandle {
|
||||||
return wrapDuration(temporal_rs_Instant_since(self.inner, other.inner, settings));
|
return wrapDuration(temporal_rs_Instant_since(self._inner, other._inner, settings));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Round this instant (Temporal.Instant.prototype.round).
|
/// Round this instant (Temporal.Instant.prototype.round).
|
||||||
pub fn round(self: Instant, options: RoundingOptions) !Instant {
|
pub fn round(self: Instant, options: RoundingOptions) !Instant {
|
||||||
return wrapInstant(temporal_rs_Instant_round(self.inner, options));
|
return wrapInstant(temporal_rs_Instant_round(self._inner, options));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compare two instants (Temporal.Instant.compare).
|
/// Compare two instants (Temporal.Instant.compare).
|
||||||
pub fn compare(a: Instant, b: Instant) i8 {
|
pub fn compare(a: Instant, b: Instant) i8 {
|
||||||
return temporal_rs_Instant_compare(a.inner, b.inner);
|
return temporal_rs_Instant_compare(a._inner, b._inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Equality check (Temporal.Instant.prototype.equals).
|
/// Equality check (Temporal.Instant.prototype.equals).
|
||||||
pub fn equals(a: Instant, b: Instant) bool {
|
pub fn equals(a: Instant, b: Instant) bool {
|
||||||
return temporal_rs_Instant_equals(a.inner, b.inner);
|
return temporal_rs_Instant_equals(a._inner, b._inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Epoch milliseconds accessor (Temporal.Instant.prototype.epochMilliseconds).
|
/// Epoch milliseconds accessor (Temporal.Instant.prototype.epochMilliseconds).
|
||||||
|
|
@ -92,7 +92,7 @@ pub fn toString(self: Instant, allocator: std.mem.Allocator, opts: ToStringOptio
|
||||||
const writer = diplomat_buffer_write_create(128);
|
const writer = diplomat_buffer_write_create(128);
|
||||||
defer diplomat_buffer_write_destroy(writer);
|
defer diplomat_buffer_write_destroy(writer);
|
||||||
|
|
||||||
const res = temporal_rs_Instant_to_ixdtf_string_with_compiled_data(self.inner, zone_opt, rounding, writer);
|
const res = temporal_rs_Instant_to_ixdtf_string_with_compiled_data(self._inner, zone_opt, rounding, writer);
|
||||||
try handleVoidResult(res);
|
try handleVoidResult(res);
|
||||||
|
|
||||||
const len = diplomat_buffer_write_len(writer);
|
const len = diplomat_buffer_write_len(writer);
|
||||||
|
|
@ -115,7 +115,7 @@ fn toStringWithProvider(self: Instant, allocator: std.mem.Allocator, provider: *
|
||||||
const writer = diplomat_buffer_write_create(128);
|
const writer = diplomat_buffer_write_create(128);
|
||||||
defer diplomat_buffer_write_destroy(writer);
|
defer diplomat_buffer_write_destroy(writer);
|
||||||
|
|
||||||
const res = temporal_rs_Instant_to_ixdtf_string_with_provider(self.inner, zone_opt, rounding, provider, writer);
|
const res = temporal_rs_Instant_to_ixdtf_string_with_provider(self._inner, zone_opt, rounding, provider, writer);
|
||||||
try handleVoidResult(res);
|
try handleVoidResult(res);
|
||||||
|
|
||||||
const len = diplomat_buffer_write_len(writer);
|
const len = diplomat_buffer_write_len(writer);
|
||||||
|
|
@ -140,22 +140,22 @@ pub fn toLocaleString(self: Instant, allocator: std.mem.Allocator) ![]u8 {
|
||||||
|
|
||||||
/// Convert to ZonedDateTime using built-in provider (Temporal.Instant.prototype.toZonedDateTimeISO).
|
/// Convert to ZonedDateTime using built-in provider (Temporal.Instant.prototype.toZonedDateTimeISO).
|
||||||
pub fn toZonedDateTimeISO(self: Instant, zone: TimeZone) !ZonedDateTimeHandle {
|
pub fn toZonedDateTimeISO(self: Instant, zone: TimeZone) !ZonedDateTimeHandle {
|
||||||
return wrapZonedDateTime(temporal_rs_Instant_to_zoned_date_time_iso(self.inner, zone));
|
return wrapZonedDateTime(temporal_rs_Instant_to_zoned_date_time_iso(self._inner, zone));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert to ZonedDateTime using an explicit provider.
|
/// Convert to ZonedDateTime using an explicit provider.
|
||||||
fn toZonedDateTimeIsoWithProvider(self: Instant, zone: TimeZone, provider: *const Provider) !ZonedDateTimeHandle {
|
fn toZonedDateTimeIsoWithProvider(self: Instant, zone: TimeZone, provider: *const Provider) !ZonedDateTimeHandle {
|
||||||
return wrapZonedDateTime(temporal_rs_Instant_to_zoned_date_time_iso_with_provider(self.inner, zone, provider));
|
return wrapZonedDateTime(temporal_rs_Instant_to_zoned_date_time_iso_with_provider(self._inner, zone, provider));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clone the underlying instant.
|
/// Clone the underlying instant.
|
||||||
fn clone(self: Instant) Instant {
|
fn clone(self: Instant) Instant {
|
||||||
const ptr = temporal_rs_Instant_clone(self.inner);
|
const ptr = temporal_rs_Instant_clone(self._inner);
|
||||||
return .{ .inner = ptr, .epochMilliseconds = temporal_rs_Instant_epoch_milliseconds(ptr), .epochNanoseconds = partsToI128(temporal_rs_Instant_epoch_nanoseconds(ptr)) };
|
return .{ ._inner = ptr, .epochMilliseconds = temporal_rs_Instant_epoch_milliseconds(ptr), .epochNanoseconds = partsToI128(temporal_rs_Instant_epoch_nanoseconds(ptr)) };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: Instant) void {
|
pub fn deinit(self: Instant) void {
|
||||||
temporal_rs_Instant_destroy(self.inner);
|
temporal_rs_Instant_destroy(self._inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Helpers -----------------------------------------------------------------
|
// --- Helpers -----------------------------------------------------------------
|
||||||
|
|
@ -163,7 +163,7 @@ pub fn deinit(self: Instant) void {
|
||||||
fn wrapInstant(res: InstantResult) !Instant {
|
fn wrapInstant(res: InstantResult) !Instant {
|
||||||
if (!res.is_ok) return error.TemporalError;
|
if (!res.is_ok) return error.TemporalError;
|
||||||
const ptr = res.result.ok orelse return error.TemporalError;
|
const ptr = res.result.ok orelse return error.TemporalError;
|
||||||
return .{ .inner = ptr, .epochMilliseconds = temporal_rs_Instant_epoch_milliseconds(ptr), .epochNanoseconds = partsToI128(temporal_rs_Instant_epoch_nanoseconds(ptr)) };
|
return .{ ._inner = ptr, .epochMilliseconds = temporal_rs_Instant_epoch_milliseconds(ptr), .epochNanoseconds = partsToI128(temporal_rs_Instant_epoch_nanoseconds(ptr)) };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wrapDuration(res: DurationResult) !DurationHandle {
|
fn wrapDuration(res: DurationResult) !DurationHandle {
|
||||||
|
|
|
||||||
49
src/root.zig
49
src/root.zig
|
|
@ -93,13 +93,13 @@ test "Temporal.Instant" {
|
||||||
"toJSON",
|
"toJSON",
|
||||||
"toLocaleString",
|
"toLocaleString",
|
||||||
"toString",
|
"toString",
|
||||||
"toZonedDateTimeISO", // Temporal.Instant.toZonedDateTimeISO
|
"toZonedDateTimeISO",
|
||||||
"until",
|
"until",
|
||||||
"valueOf",
|
"valueOf",
|
||||||
|
|
||||||
// Properties
|
// Properties
|
||||||
// "epochMilliseconds",
|
"epochMilliseconds",
|
||||||
// "epochNanoseconds",
|
"epochNanoseconds",
|
||||||
};
|
};
|
||||||
|
|
||||||
try assertDecls(Instant, checks);
|
try assertDecls(Instant, checks);
|
||||||
|
|
@ -403,22 +403,38 @@ fn assertDecls(comptime T: type, checks: anytype) !void {
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const typeInfo = @typeInfo(T);
|
const typeInfo = @typeInfo(T);
|
||||||
|
|
||||||
// Check: all items in checks exist
|
// Check: all items in checks exist (either as decls or as fields)
|
||||||
inline for (checks) |check| {
|
inline for (checks) |check| {
|
||||||
const should_ignore =
|
const should_ignore =
|
||||||
std.mem.eql(u8, check, "deinit") or
|
std.mem.eql(u8, check, "deinit") or
|
||||||
std.mem.eql(u8, check, "valueOf");
|
std.mem.eql(u8, check, "valueOf");
|
||||||
|
|
||||||
const has = @hasDecl(T, check);
|
|
||||||
if (!should_ignore) {
|
if (!should_ignore) {
|
||||||
if (!has) std.log.err("Missing {s} decl: {s}", .{ @typeName(T), check });
|
const hasDecl = @hasDecl(T, check);
|
||||||
|
|
||||||
|
// Also check if it's a field (property)
|
||||||
|
var hasField = false;
|
||||||
|
if (typeInfo == .@"struct") {
|
||||||
|
const struct_info = typeInfo.@"struct";
|
||||||
|
inline for (struct_info.fields) |field| {
|
||||||
|
if (std.mem.eql(u8, field.name, check)) {
|
||||||
|
hasField = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const has = hasDecl or hasField;
|
||||||
|
if (!has) std.log.err("Missing {s} decl or field: {s}", .{ @typeName(T), check });
|
||||||
try std.testing.expect(has);
|
try std.testing.expect(has);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check: no extraneous declarations beyond checks
|
// Check: no extraneous declarations or fields beyond checks
|
||||||
if (typeInfo == .@"struct") {
|
if (typeInfo == .@"struct") {
|
||||||
const struct_info = typeInfo.@"struct";
|
const struct_info = typeInfo.@"struct";
|
||||||
|
|
||||||
|
// Check declarations
|
||||||
inline for (struct_info.decls) |decl| {
|
inline for (struct_info.decls) |decl| {
|
||||||
// Allow deinit as extraneous
|
// Allow deinit as extraneous
|
||||||
if (comptime std.mem.eql(u8, decl.name, "deinit")) continue;
|
if (comptime std.mem.eql(u8, decl.name, "deinit")) continue;
|
||||||
|
|
@ -436,5 +452,24 @@ fn assertDecls(comptime T: type, checks: anytype) !void {
|
||||||
try std.testing.expect(false);
|
try std.testing.expect(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check fields (properties)
|
||||||
|
inline for (struct_info.fields) |field| {
|
||||||
|
// Allow internal fields (starting with underscore)
|
||||||
|
if (comptime std.mem.startsWith(u8, field.name, "_")) continue;
|
||||||
|
|
||||||
|
var found = false;
|
||||||
|
inline for (checks) |check| {
|
||||||
|
if (std.mem.eql(u8, field.name, check)) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
std.log.err("Extraneous {s} field: {s}", .{ @typeName(T), field.name });
|
||||||
|
try std.testing.expect(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue