chore: remove old stringify code
This commit is contained in:
parent
60f1863557
commit
e43b827576
2 changed files with 1 additions and 560 deletions
|
@ -1653,34 +1653,6 @@ fn generateComplexTypeFor(shape_id: []const u8, members: []smithy.TypeMember, ty
|
||||||
_ = try writer.write("return @field(mappings, field_name);\n");
|
_ = try writer.write("return @field(mappings, field_name);\n");
|
||||||
try outputIndent(child_state, writer);
|
try outputIndent(child_state, writer);
|
||||||
_ = try writer.write("}\n");
|
_ = try writer.write("}\n");
|
||||||
try writeStringify(child_state, map_fields.items, writer);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn writeStringify(state: GenerationState, fields: [][]const u8, writer: anytype) !void {
|
|
||||||
if (fields.len > 0) {
|
|
||||||
// pub fn jsonStringifyField(self: @This(), comptime field_name: []const u8, options: anytype, out_stream: anytype) !bool {
|
|
||||||
// if (std.mem.eql(u8, "tags", field_name))
|
|
||||||
// return try serializeMap(self.tags, self.jsonFieldNameFor("tags"), options, out_stream);
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
var child_state = state;
|
|
||||||
child_state.indent_level += 1;
|
|
||||||
try writer.writeByte('\n');
|
|
||||||
try outputIndent(state, writer);
|
|
||||||
_ = try writer.write("pub fn jsonStringifyField(self: @This(), comptime field_name: []const u8, options: anytype, out_stream: anytype) !bool {\n");
|
|
||||||
var return_state = child_state;
|
|
||||||
return_state.indent_level += 1;
|
|
||||||
for (fields) |field| {
|
|
||||||
try outputIndent(child_state, writer);
|
|
||||||
try writer.print("if (std.mem.eql(u8, \"{s}\", field_name))\n", .{field});
|
|
||||||
try outputIndent(return_state, writer);
|
|
||||||
try writer.print("return try serializeMap(self.{s}, self.fieldNameFor(\"{s}\"), options, out_stream);\n", .{ field, field });
|
|
||||||
}
|
|
||||||
try outputIndent(child_state, writer);
|
|
||||||
_ = try writer.write("return false;\n");
|
|
||||||
try outputIndent(state, writer);
|
|
||||||
_ = try writer.write("}\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writeMappings(state: GenerationState, @"pub": []const u8, mapping_name: []const u8, mappings: anytype, force_output: bool, writer: anytype) !void {
|
fn writeMappings(state: GenerationState, @"pub": []const u8, mapping_name: []const u8, mappings: anytype, force_output: bool, writer: anytype) !void {
|
||||||
|
|
|
@ -37,7 +37,7 @@ fn serializeMapKey(key: []const u8, options: anytype, out_stream: anytype) !void
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn serializeMapAsObject(map: anytype, options: anytype, out_stream: anytype) !void {
|
fn serializeMapAsObject(map: anytype, options: anytype, out_stream: anytype) !void {
|
||||||
if (map.len == 0) {
|
if (map.len == 0) {
|
||||||
try out_stream.writeByte('{');
|
try out_stream.writeByte('{');
|
||||||
try out_stream.writeByte('}');
|
try out_stream.writeByte('}');
|
||||||
|
@ -1371,137 +1371,8 @@ pub const Value = union(enum) {
|
||||||
String: []const u8,
|
String: []const u8,
|
||||||
Array: Array,
|
Array: Array,
|
||||||
Object: ObjectMap,
|
Object: ObjectMap,
|
||||||
|
|
||||||
pub fn jsonStringify(
|
|
||||||
value: @This(),
|
|
||||||
options: StringifyOptions,
|
|
||||||
out_stream: anytype,
|
|
||||||
) @TypeOf(out_stream).Error!void {
|
|
||||||
switch (value) {
|
|
||||||
.Null => try stringify(null, options, out_stream),
|
|
||||||
.Bool => |inner| try stringify(inner, options, out_stream),
|
|
||||||
.Integer => |inner| try stringify(inner, options, out_stream),
|
|
||||||
.Float => |inner| try stringify(inner, options, out_stream),
|
|
||||||
.NumberString => |inner| try out_stream.writeAll(inner),
|
|
||||||
.String => |inner| try stringify(inner, options, out_stream),
|
|
||||||
.Array => |inner| try stringify(inner.items, options, out_stream),
|
|
||||||
.Object => |inner| {
|
|
||||||
try out_stream.writeByte('{');
|
|
||||||
var field_output = false;
|
|
||||||
var child_options = options;
|
|
||||||
if (child_options.whitespace) |*child_whitespace| {
|
|
||||||
child_whitespace.indent_level += 1;
|
|
||||||
}
|
|
||||||
var it = inner.iterator();
|
|
||||||
while (it.next()) |entry| {
|
|
||||||
if (!field_output) {
|
|
||||||
field_output = true;
|
|
||||||
} else {
|
|
||||||
try out_stream.writeByte(',');
|
|
||||||
}
|
|
||||||
if (child_options.whitespace) |child_whitespace| {
|
|
||||||
try out_stream.writeByte('\n');
|
|
||||||
try child_whitespace.outputIndent(out_stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
try stringify(entry.key_ptr, options, out_stream);
|
|
||||||
try out_stream.writeByte(':');
|
|
||||||
if (child_options.whitespace) |child_whitespace| {
|
|
||||||
if (child_whitespace.separator) {
|
|
||||||
try out_stream.writeByte(' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try stringify(entry.value_ptr, child_options, out_stream);
|
|
||||||
}
|
|
||||||
if (field_output) {
|
|
||||||
if (options.whitespace) |whitespace| {
|
|
||||||
try out_stream.writeByte('\n');
|
|
||||||
try whitespace.outputIndent(out_stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try out_stream.writeByte('}');
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn dump(self: Value) void {
|
|
||||||
std.debug.lockStdErr();
|
|
||||||
defer std.debug.unlockStdErr();
|
|
||||||
|
|
||||||
const stderr = std.io.getStdErr().writer();
|
|
||||||
stringify(self, StringifyOptions{ .whitespace = null }, stderr) catch return;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn dump(value: anytype) void {
|
|
||||||
var held = std.debug.getStderrMutex().acquire();
|
|
||||||
defer held.release();
|
|
||||||
|
|
||||||
const stderr = std.io.getStdErr().writer();
|
|
||||||
stringify(value, StringifyOptions{ .whitespace = null }, stderr) catch return;
|
|
||||||
}
|
|
||||||
|
|
||||||
test "Value.jsonStringify" {
|
|
||||||
{
|
|
||||||
var buffer: [10]u8 = undefined;
|
|
||||||
var fbs = std.io.fixedBufferStream(&buffer);
|
|
||||||
try @as(Value, .Null).jsonStringify(.{}, fbs.writer());
|
|
||||||
try testing.expectEqualSlices(u8, fbs.getWritten(), "null");
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var buffer: [10]u8 = undefined;
|
|
||||||
var fbs = std.io.fixedBufferStream(&buffer);
|
|
||||||
try (Value{ .Bool = true }).jsonStringify(.{}, fbs.writer());
|
|
||||||
try testing.expectEqualSlices(u8, fbs.getWritten(), "true");
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var buffer: [10]u8 = undefined;
|
|
||||||
var fbs = std.io.fixedBufferStream(&buffer);
|
|
||||||
try (Value{ .Integer = 42 }).jsonStringify(.{}, fbs.writer());
|
|
||||||
try testing.expectEqualSlices(u8, fbs.getWritten(), "42");
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var buffer: [10]u8 = undefined;
|
|
||||||
var fbs = std.io.fixedBufferStream(&buffer);
|
|
||||||
try (Value{ .NumberString = "43" }).jsonStringify(.{}, fbs.writer());
|
|
||||||
try testing.expectEqualSlices(u8, fbs.getWritten(), "43");
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var buffer: [10]u8 = undefined;
|
|
||||||
var fbs = std.io.fixedBufferStream(&buffer);
|
|
||||||
try (Value{ .Float = 42 }).jsonStringify(.{}, fbs.writer());
|
|
||||||
try testing.expectEqualSlices(u8, fbs.getWritten(), "4.2e1");
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var buffer: [10]u8 = undefined;
|
|
||||||
var fbs = std.io.fixedBufferStream(&buffer);
|
|
||||||
try (Value{ .String = "weeee" }).jsonStringify(.{}, fbs.writer());
|
|
||||||
try testing.expectEqualSlices(u8, fbs.getWritten(), "\"weeee\"");
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var buffer: [10]u8 = undefined;
|
|
||||||
var fbs = std.io.fixedBufferStream(&buffer);
|
|
||||||
var vals = [_]Value{
|
|
||||||
.{ .Integer = 1 },
|
|
||||||
.{ .Integer = 2 },
|
|
||||||
.{ .NumberString = "3" },
|
|
||||||
};
|
|
||||||
try (Value{
|
|
||||||
.Array = Array.fromOwnedSlice(undefined, &vals),
|
|
||||||
}).jsonStringify(.{}, fbs.writer());
|
|
||||||
try testing.expectEqualSlices(u8, fbs.getWritten(), "[1,2,3]");
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var buffer: [10]u8 = undefined;
|
|
||||||
var fbs = std.io.fixedBufferStream(&buffer);
|
|
||||||
var obj = ObjectMap.init(testing.allocator);
|
|
||||||
defer obj.deinit();
|
|
||||||
try obj.putNoClobber("a", .{ .String = "b" });
|
|
||||||
try (Value{ .Object = obj }).jsonStringify(.{}, fbs.writer());
|
|
||||||
try testing.expectEqualSlices(u8, fbs.getWritten(), "{\"a\":\"b\"}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// parse tokens from a stream, returning `false` if they do not decode to `value`
|
/// parse tokens from a stream, returning `false` if they do not decode to `value`
|
||||||
fn parsesTo(comptime T: type, value: T, tokens: *TokenStream, options: ParseOptions) !bool {
|
fn parsesTo(comptime T: type, value: T, tokens: *TokenStream, options: ParseOptions) !bool {
|
||||||
// TODO: should be able to write this function to not require an allocator
|
// TODO: should be able to write this function to not require an allocator
|
||||||
|
@ -2923,405 +2794,3 @@ fn outputUnicodeEscape(
|
||||||
try std.fmt.formatIntValue(low, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
|
try std.fmt.formatIntValue(low, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stringify(
|
|
||||||
value: anytype,
|
|
||||||
options: StringifyOptions,
|
|
||||||
out_stream: anytype,
|
|
||||||
) !void {
|
|
||||||
const T = @TypeOf(value);
|
|
||||||
switch (@typeInfo(T)) {
|
|
||||||
.float, .comptime_float => {
|
|
||||||
return std.fmt.format(out_stream, "{e}", .{value});
|
|
||||||
},
|
|
||||||
.int, .comptime_int => {
|
|
||||||
return std.fmt.formatIntValue(value, "", std.fmt.FormatOptions{}, out_stream);
|
|
||||||
},
|
|
||||||
.bool => {
|
|
||||||
return out_stream.writeAll(if (value) "true" else "false");
|
|
||||||
},
|
|
||||||
.null => {
|
|
||||||
return out_stream.writeAll("null");
|
|
||||||
},
|
|
||||||
.optional => {
|
|
||||||
if (value) |payload| {
|
|
||||||
return try stringify(payload, options, out_stream);
|
|
||||||
} else {
|
|
||||||
return try stringify(null, options, out_stream);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.@"enum" => {
|
|
||||||
if (comptime std.meta.hasFn(T, "jsonStringify")) {
|
|
||||||
return value.jsonStringify(options, out_stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
@compileError("Unable to stringify enum '" ++ @typeName(T) ++ "'");
|
|
||||||
},
|
|
||||||
.@"union" => {
|
|
||||||
if (comptime std.meta.hasFn(T, "jsonStringify")) {
|
|
||||||
return value.jsonStringify(options, out_stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
const info = @typeInfo(T).@"union";
|
|
||||||
if (info.tag_type) |UnionTagType| {
|
|
||||||
inline for (info.fields) |u_field| {
|
|
||||||
if (value == @field(UnionTagType, u_field.name)) {
|
|
||||||
return try stringify(@field(value, u_field.name), options, out_stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
@compileError("Unable to stringify untagged union '" ++ @typeName(T) ++ "'");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.@"struct" => |S| {
|
|
||||||
if (comptime std.meta.hasFn(T, "jsonStringify")) {
|
|
||||||
return value.jsonStringify(options, out_stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
try out_stream.writeByte('{');
|
|
||||||
var field_output = false;
|
|
||||||
var child_options = options;
|
|
||||||
if (child_options.whitespace) |*child_whitespace| {
|
|
||||||
child_whitespace.indent_level += 1;
|
|
||||||
}
|
|
||||||
inline for (S.fields) |field| {
|
|
||||||
// don't include void fields
|
|
||||||
if (field.type == void) continue;
|
|
||||||
|
|
||||||
var output_this_field = true;
|
|
||||||
if (!options.emit_null and @typeInfo(field.type) == .optional and @field(value, field.name) == null) output_this_field = false;
|
|
||||||
|
|
||||||
const final_name = if (comptime std.meta.hasFn(T, "fieldNameFor"))
|
|
||||||
value.fieldNameFor(field.name)
|
|
||||||
else
|
|
||||||
field.name;
|
|
||||||
if (options.exclude_fields) |exclude_fields| {
|
|
||||||
for (exclude_fields) |exclude_field| {
|
|
||||||
if (std.mem.eql(u8, final_name, exclude_field)) {
|
|
||||||
output_this_field = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!field_output) {
|
|
||||||
field_output = output_this_field;
|
|
||||||
} else {
|
|
||||||
if (output_this_field) try out_stream.writeByte(',');
|
|
||||||
}
|
|
||||||
if (child_options.whitespace) |child_whitespace| {
|
|
||||||
if (output_this_field) try out_stream.writeByte('\n');
|
|
||||||
if (output_this_field) try child_whitespace.outputIndent(out_stream);
|
|
||||||
}
|
|
||||||
var field_written = false;
|
|
||||||
if (comptime std.meta.hasFn(T, "jsonStringifyField")) {
|
|
||||||
if (output_this_field) field_written = try value.jsonStringifyField(field.name, child_options, out_stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!field_written) {
|
|
||||||
if (output_this_field) {
|
|
||||||
try stringify(final_name, options, out_stream);
|
|
||||||
try out_stream.writeByte(':');
|
|
||||||
}
|
|
||||||
if (child_options.whitespace) |child_whitespace| {
|
|
||||||
if (child_whitespace.separator) {
|
|
||||||
if (output_this_field) try out_stream.writeByte(' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (output_this_field) {
|
|
||||||
try stringify(@field(value, field.name), child_options, out_stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (field_output) {
|
|
||||||
if (options.whitespace) |whitespace| {
|
|
||||||
try out_stream.writeByte('\n');
|
|
||||||
try whitespace.outputIndent(out_stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try out_stream.writeByte('}');
|
|
||||||
return;
|
|
||||||
},
|
|
||||||
.error_set => return stringify(@as([]const u8, @errorName(value)), options, out_stream),
|
|
||||||
.pointer => |ptr_info| switch (ptr_info.size) {
|
|
||||||
.one => switch (@typeInfo(ptr_info.child)) {
|
|
||||||
.array => {
|
|
||||||
const Slice = []const std.meta.Elem(ptr_info.child);
|
|
||||||
return stringify(@as(Slice, value), options, out_stream);
|
|
||||||
},
|
|
||||||
else => {
|
|
||||||
// TODO: avoid loops?
|
|
||||||
return stringify(value.*, options, out_stream);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// TODO: .Many when there is a sentinel (waiting for https://github.com/ziglang/zig/pull/3972)
|
|
||||||
.slice => {
|
|
||||||
if (ptr_info.child == u8 and options.string == .String and std.unicode.utf8ValidateSlice(value)) {
|
|
||||||
try out_stream.writeByte('\"');
|
|
||||||
var i: usize = 0;
|
|
||||||
while (i < value.len) : (i += 1) {
|
|
||||||
switch (value[i]) {
|
|
||||||
// normal ascii character
|
|
||||||
0x20...0x21, 0x23...0x2E, 0x30...0x5B, 0x5D...0x7F => |c| try out_stream.writeByte(c),
|
|
||||||
// only 2 characters that *must* be escaped
|
|
||||||
'\\' => try out_stream.writeAll("\\\\"),
|
|
||||||
'\"' => try out_stream.writeAll("\\\""),
|
|
||||||
// solidus is optional to escape
|
|
||||||
'/' => {
|
|
||||||
if (options.string.String.escape_solidus) {
|
|
||||||
try out_stream.writeAll("\\/");
|
|
||||||
} else {
|
|
||||||
try out_stream.writeByte('/');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// control characters with short escapes
|
|
||||||
// TODO: option to switch between unicode and 'short' forms?
|
|
||||||
0x8 => try out_stream.writeAll("\\b"),
|
|
||||||
0xC => try out_stream.writeAll("\\f"),
|
|
||||||
'\n' => try out_stream.writeAll("\\n"),
|
|
||||||
'\r' => try out_stream.writeAll("\\r"),
|
|
||||||
'\t' => try out_stream.writeAll("\\t"),
|
|
||||||
else => {
|
|
||||||
const ulen = std.unicode.utf8ByteSequenceLength(value[i]) catch unreachable;
|
|
||||||
// control characters (only things left with 1 byte length) should always be printed as unicode escapes
|
|
||||||
if (ulen == 1 or options.string.String.escape_unicode) {
|
|
||||||
const codepoint = std.unicode.utf8Decode(value[i .. i + ulen]) catch unreachable;
|
|
||||||
try outputUnicodeEscape(codepoint, out_stream);
|
|
||||||
} else {
|
|
||||||
try out_stream.writeAll(value[i .. i + ulen]);
|
|
||||||
}
|
|
||||||
i += ulen - 1;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try out_stream.writeByte('\"');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (@typeInfo(ptr_info.child) == .@"struct" and @hasDecl(ptr_info.child, "is_map_type")) {
|
|
||||||
try serializeMapAsObject(value, options, out_stream);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var child_options = options;
|
|
||||||
if (child_options.whitespace) |*whitespace| {
|
|
||||||
whitespace.indent_level += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
try out_stream.writeByte('[');
|
|
||||||
for (value, 0..) |x, i| {
|
|
||||||
if (i != 0) {
|
|
||||||
try out_stream.writeByte(',');
|
|
||||||
}
|
|
||||||
if (child_options.whitespace) |child_whitespace| {
|
|
||||||
try out_stream.writeByte('\n');
|
|
||||||
try child_whitespace.outputIndent(out_stream);
|
|
||||||
}
|
|
||||||
try stringify(x, child_options, out_stream);
|
|
||||||
}
|
|
||||||
if (value.len != 0) {
|
|
||||||
if (options.whitespace) |whitespace| {
|
|
||||||
try out_stream.writeByte('\n');
|
|
||||||
try whitespace.outputIndent(out_stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try out_stream.writeByte(']');
|
|
||||||
return;
|
|
||||||
},
|
|
||||||
else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"),
|
|
||||||
},
|
|
||||||
.array => return stringify(&value, options, out_stream),
|
|
||||||
.vector => |info| {
|
|
||||||
const array: [info.len]info.child = value;
|
|
||||||
return stringify(&array, options, out_stream);
|
|
||||||
},
|
|
||||||
else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"),
|
|
||||||
}
|
|
||||||
unreachable;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn teststringify(expected: []const u8, value: anytype, options: StringifyOptions) !void {
|
|
||||||
const ValidationWriter = struct {
|
|
||||||
const Self = @This();
|
|
||||||
pub const Writer = std.io.Writer(*Self, Error, write);
|
|
||||||
pub const Error = error{
|
|
||||||
TooMuchData,
|
|
||||||
DifferentData,
|
|
||||||
};
|
|
||||||
|
|
||||||
expected_remaining: []const u8,
|
|
||||||
|
|
||||||
fn init(exp: []const u8) Self {
|
|
||||||
return .{ .expected_remaining = exp };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn writer(self: *Self) Writer {
|
|
||||||
return .{ .context = self };
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write(self: *Self, bytes: []const u8) Error!usize {
|
|
||||||
if (self.expected_remaining.len < bytes.len) {
|
|
||||||
std.log.warn(
|
|
||||||
\\====== expected this output: =========
|
|
||||||
\\{s}
|
|
||||||
\\======== instead found this: =========
|
|
||||||
\\{s}
|
|
||||||
\\======================================
|
|
||||||
, .{
|
|
||||||
self.expected_remaining,
|
|
||||||
bytes,
|
|
||||||
});
|
|
||||||
return error.TooMuchData;
|
|
||||||
}
|
|
||||||
if (!mem.eql(u8, self.expected_remaining[0..bytes.len], bytes)) {
|
|
||||||
std.log.warn(
|
|
||||||
\\====== expected this output: =========
|
|
||||||
\\{s}
|
|
||||||
\\======== instead found this: =========
|
|
||||||
\\{s}
|
|
||||||
\\======================================
|
|
||||||
, .{
|
|
||||||
self.expected_remaining[0..bytes.len],
|
|
||||||
bytes,
|
|
||||||
});
|
|
||||||
return error.DifferentData;
|
|
||||||
}
|
|
||||||
self.expected_remaining = self.expected_remaining[bytes.len..];
|
|
||||||
return bytes.len;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var vos = ValidationWriter.init(expected);
|
|
||||||
try stringify(value, options, vos.writer());
|
|
||||||
if (vos.expected_remaining.len > 0) return error.NotEnoughData;
|
|
||||||
}
|
|
||||||
|
|
||||||
test "stringify basic types" {
|
|
||||||
try teststringify("false", false, StringifyOptions{});
|
|
||||||
try teststringify("true", true, StringifyOptions{});
|
|
||||||
try teststringify("null", @as(?u8, null), StringifyOptions{});
|
|
||||||
try teststringify("null", @as(?*u32, null), StringifyOptions{});
|
|
||||||
try teststringify("42", 42, StringifyOptions{});
|
|
||||||
try teststringify("4.2e1", 42.0, StringifyOptions{});
|
|
||||||
try teststringify("42", @as(u8, 42), StringifyOptions{});
|
|
||||||
try teststringify("42", @as(u128, 42), StringifyOptions{});
|
|
||||||
try teststringify("4.2e1", @as(f32, 42), StringifyOptions{});
|
|
||||||
try teststringify("4.2e1", @as(f64, 42), StringifyOptions{});
|
|
||||||
try teststringify("\"ItBroke\"", @as(anyerror, error.ItBroke), StringifyOptions{});
|
|
||||||
}
|
|
||||||
|
|
||||||
test "stringify string" {
|
|
||||||
try teststringify("\"hello\"", "hello", StringifyOptions{});
|
|
||||||
try teststringify("\"with\\nescapes\\r\"", "with\nescapes\r", StringifyOptions{});
|
|
||||||
try teststringify("\"with\\nescapes\\r\"", "with\nescapes\r", StringifyOptions{ .string = .{ .String = .{ .escape_unicode = true } } });
|
|
||||||
try teststringify("\"with unicode\\u0001\"", "with unicode\u{1}", StringifyOptions{});
|
|
||||||
try teststringify("\"with unicode\\u0001\"", "with unicode\u{1}", StringifyOptions{ .string = .{ .String = .{ .escape_unicode = true } } });
|
|
||||||
try teststringify("\"with unicode\u{80}\"", "with unicode\u{80}", StringifyOptions{});
|
|
||||||
try teststringify("\"with unicode\\u0080\"", "with unicode\u{80}", StringifyOptions{ .string = .{ .String = .{ .escape_unicode = true } } });
|
|
||||||
try teststringify("\"with unicode\u{FF}\"", "with unicode\u{FF}", StringifyOptions{});
|
|
||||||
try teststringify("\"with unicode\\u00ff\"", "with unicode\u{FF}", StringifyOptions{ .string = .{ .String = .{ .escape_unicode = true } } });
|
|
||||||
try teststringify("\"with unicode\u{100}\"", "with unicode\u{100}", StringifyOptions{});
|
|
||||||
try teststringify("\"with unicode\\u0100\"", "with unicode\u{100}", StringifyOptions{ .string = .{ .String = .{ .escape_unicode = true } } });
|
|
||||||
try teststringify("\"with unicode\u{800}\"", "with unicode\u{800}", StringifyOptions{});
|
|
||||||
try teststringify("\"with unicode\\u0800\"", "with unicode\u{800}", StringifyOptions{ .string = .{ .String = .{ .escape_unicode = true } } });
|
|
||||||
try teststringify("\"with unicode\u{8000}\"", "with unicode\u{8000}", StringifyOptions{});
|
|
||||||
try teststringify("\"with unicode\\u8000\"", "with unicode\u{8000}", StringifyOptions{ .string = .{ .String = .{ .escape_unicode = true } } });
|
|
||||||
try teststringify("\"with unicode\u{D799}\"", "with unicode\u{D799}", StringifyOptions{});
|
|
||||||
try teststringify("\"with unicode\\ud799\"", "with unicode\u{D799}", StringifyOptions{ .string = .{ .String = .{ .escape_unicode = true } } });
|
|
||||||
try teststringify("\"with unicode\u{10000}\"", "with unicode\u{10000}", StringifyOptions{});
|
|
||||||
try teststringify("\"with unicode\\ud800\\udc00\"", "with unicode\u{10000}", StringifyOptions{ .string = .{ .String = .{ .escape_unicode = true } } });
|
|
||||||
try teststringify("\"with unicode\u{10FFFF}\"", "with unicode\u{10FFFF}", StringifyOptions{});
|
|
||||||
try teststringify("\"with unicode\\udbff\\udfff\"", "with unicode\u{10FFFF}", StringifyOptions{ .string = .{ .String = .{ .escape_unicode = true } } });
|
|
||||||
try teststringify("\"/\"", "/", StringifyOptions{});
|
|
||||||
try teststringify("\"\\/\"", "/", StringifyOptions{ .string = .{ .String = .{ .escape_solidus = true } } });
|
|
||||||
}
|
|
||||||
|
|
||||||
test "stringify tagged unions" {
|
|
||||||
try teststringify("42", union(enum) {
|
|
||||||
Foo: u32,
|
|
||||||
Bar: bool,
|
|
||||||
}{ .Foo = 42 }, StringifyOptions{});
|
|
||||||
}
|
|
||||||
|
|
||||||
test "stringify struct" {
|
|
||||||
try teststringify("{\"foo\":42}", struct {
|
|
||||||
foo: u32,
|
|
||||||
}{ .foo = 42 }, StringifyOptions{});
|
|
||||||
}
|
|
||||||
|
|
||||||
test "stringify struct with indentation" {
|
|
||||||
try teststringify(
|
|
||||||
\\{
|
|
||||||
\\ "foo": 42,
|
|
||||||
\\ "bar": [
|
|
||||||
\\ 1,
|
|
||||||
\\ 2,
|
|
||||||
\\ 3
|
|
||||||
\\ ]
|
|
||||||
\\}
|
|
||||||
,
|
|
||||||
struct {
|
|
||||||
foo: u32,
|
|
||||||
bar: [3]u32,
|
|
||||||
}{
|
|
||||||
.foo = 42,
|
|
||||||
.bar = .{ 1, 2, 3 },
|
|
||||||
},
|
|
||||||
StringifyOptions{
|
|
||||||
.whitespace = .{},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
try teststringify(
|
|
||||||
"{\n\t\"foo\":42,\n\t\"bar\":[\n\t\t1,\n\t\t2,\n\t\t3\n\t]\n}",
|
|
||||||
struct {
|
|
||||||
foo: u32,
|
|
||||||
bar: [3]u32,
|
|
||||||
}{
|
|
||||||
.foo = 42,
|
|
||||||
.bar = .{ 1, 2, 3 },
|
|
||||||
},
|
|
||||||
StringifyOptions{
|
|
||||||
.whitespace = .{
|
|
||||||
.indent = .Tab,
|
|
||||||
.separator = false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "stringify struct with void field" {
|
|
||||||
try teststringify("{\"foo\":42}", struct {
|
|
||||||
foo: u32,
|
|
||||||
bar: void = {},
|
|
||||||
}{ .foo = 42 }, StringifyOptions{});
|
|
||||||
}
|
|
||||||
|
|
||||||
test "stringify array of structs" {
|
|
||||||
const MyStruct = struct {
|
|
||||||
foo: u32,
|
|
||||||
};
|
|
||||||
try teststringify("[{\"foo\":42},{\"foo\":100},{\"foo\":1000}]", [_]MyStruct{
|
|
||||||
MyStruct{ .foo = 42 },
|
|
||||||
MyStruct{ .foo = 100 },
|
|
||||||
MyStruct{ .foo = 1000 },
|
|
||||||
}, StringifyOptions{});
|
|
||||||
}
|
|
||||||
|
|
||||||
test "stringify struct with custom stringifier" {
|
|
||||||
try teststringify("[\"something special\",42]", struct {
|
|
||||||
foo: u32,
|
|
||||||
const Self = @This();
|
|
||||||
pub fn jsonStringify(
|
|
||||||
_: Self,
|
|
||||||
options: StringifyOptions,
|
|
||||||
out_stream: anytype,
|
|
||||||
) !void {
|
|
||||||
try out_stream.writeAll("[\"something special\",");
|
|
||||||
try stringify(42, options, out_stream);
|
|
||||||
try out_stream.writeByte(']');
|
|
||||||
}
|
|
||||||
}{ .foo = 42 }, StringifyOptions{});
|
|
||||||
}
|
|
||||||
|
|
||||||
test "stringify vector" {
|
|
||||||
try teststringify("[1,1]", @as(@Vector(2, u32), @splat(@as(u32, 1))), StringifyOptions{});
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue