Add support for explicit utf8 strings, minor cleanup, begin zoo example.

This commit is contained in:
Vivianne 2023-07-17 18:54:59 -07:00
parent 901cfaea48
commit e023636b5e
3 changed files with 150 additions and 17 deletions

View file

@ -34,6 +34,7 @@ pub fn build(b: *std.Build) void {
.optimize = optimize,
});
main_tests.addModule("getty", getty_mod);
main_tests.addAnonymousModule("zoo.bin", .{ .source_file = std.Build.FileSource.relative("test-data/zoo.bin") });
const run_main_tests = b.addRunArtifact(main_tests);

View file

@ -4,7 +4,31 @@ const getty = @import("getty");
const builtin = @import("builtin");
const native_endian = builtin.target.cpu.arch.endian();
const SyrupSerializer = struct {
const Utf8String = struct {
bytes: []const u8,
pub const Error = error{InvalidEncoding};
fn init(bytes: []const u8) Error!@This() {
if (!std.unicode.utf8ValidateSlice(bytes)) {
return error.InvalidEncoding;
}
return initAssumeEncoding(bytes);
}
fn initAssumeEncoding(bytes: []const u8) @This() {
return .{
.bytes = bytes,
};
}
};
test "test invalid utf8" {
try testing.expectError(Utf8String.Error.InvalidEncoding, Utf8String.init("abc\xc0"));
}
const Serializer = struct {
usingnamespace getty.Serializer(
Self,
Ok,
@ -13,13 +37,14 @@ const SyrupSerializer = struct {
null,
null,
null,
null,
Struct,
.{
.serializeBool = serializeBool,
.serializeInt = serializeInt,
.serializeFloat = serializeFloat,
.serializeString = serializeString,
.serializeEnum = serializeEnum,
.serializeStruct = serializeStruct,
},
);
@ -29,6 +54,11 @@ const SyrupSerializer = struct {
const Ok = void;
const Error = getty.ser.Error || std.mem.Allocator.Error;
pub fn serializeGenericString(comptime joiner: []const u8, writer: std.ArrayList(u8).Writer, value: anytype) Error!Ok {
try writer.print("{d}" ++ joiner, .{value.len});
try writer.print("{s}", .{value});
}
fn serializeBool(self: Self, value: bool) Error!Ok {
try self.writer.writeByte(if (value) 't' else 'f');
}
@ -53,20 +83,52 @@ const SyrupSerializer = struct {
}
fn serializeString(self: Self, value: anytype) Error!Ok {
try self.writer.print("{d}\"", .{value.len});
try self.writer.print("{s}", .{value});
try serializeGenericString(":", self.writer, value);
}
fn serializeEnum(self: Self, _: anytype, name: []const u8) Error!Ok {
try self.writer.print("{d}\'", .{name.len});
try self.writer.print("{s}", .{name});
try serializeGenericString("\'", self.writer, name);
}
fn serializeStruct(self: Self, comptime name: []const u8, _: usize) Error!Struct {
return Struct{
.isWrappedString = std.mem.eql(u8, name, @typeName(Utf8String)),
.writer = self.writer,
};
}
};
const Struct = struct {
pub usingnamespace getty.ser.Structure(
Self,
Ok,
Error,
.{
.serializeField = serializeField,
.end = end,
},
);
isWrappedString: bool = false,
writer: std.ArrayList(u8).Writer,
const Self = @This();
const Ok = Serializer.Ok;
const Error = Serializer.Error;
fn serializeField(self: Self, comptime _: []const u8, value: anytype) Error!void {
if (self.isWrappedString) {
try Serializer.serializeGenericString("\"", self.writer, value);
}
}
fn end(_: Self) Error!Ok {}
};
test "serialize bool" {
var arr = std.ArrayList(u8).init(std.testing.allocator);
defer arr.deinit();
var s = (SyrupSerializer{ .writer = arr.writer() }).serializer();
var s = (Serializer{ .writer = arr.writer() }).serializer();
try getty.serialize(null, true, s);
try getty.serialize(null, false, s);
@ -78,7 +140,7 @@ test "serialize bool" {
test "serialize ints" {
var arr = std.ArrayList(u8).init(std.testing.allocator);
defer arr.deinit();
var s = (SyrupSerializer{ .writer = arr.writer() }).serializer();
var s = (Serializer{ .writer = arr.writer() }).serializer();
try getty.serialize(null, 42, s);
try getty.serialize(null, 86, s);
@ -90,22 +152,33 @@ test "serialize ints" {
test "serialize floats" {
var arr = std.ArrayList(u8).init(std.testing.allocator);
defer arr.deinit();
var s = (SyrupSerializer{ .writer = arr.writer() }).serializer();
var s = (Serializer{ .writer = arr.writer() }).serializer();
try getty.serialize(null, @as(f64, 42.42), s);
try getty.serialize(null, @as(f32, 42.42), s);
try testing.expectEqualStrings(arr.items, &[_]u8{ 'D', 64, 69, 53, 194, 143, 92, 40, 246, 'F', 66, 41, 174, 20 });
}
test "serialize bytestrs" {
var arr = std.ArrayList(u8).init(std.testing.allocator);
defer arr.deinit();
var s = (Serializer{ .writer = arr.writer() }).serializer();
try getty.serialize(null, "hello", s);
try getty.serialize(null, "my name is vivi 💖", s);
try testing.expectEqualStrings(arr.items, "5:hello20:my name is vivi 💖");
}
test "serialize strs" {
var arr = std.ArrayList(u8).init(std.testing.allocator);
defer arr.deinit();
var s = (SyrupSerializer{ .writer = arr.writer() }).serializer();
var s = (Serializer{ .writer = arr.writer() }).serializer();
try getty.serialize(null, "hello", s);
try getty.serialize(null, "my name is vivi", s);
try getty.serialize(null, try Utf8String.init("hello"), s);
try getty.serialize(null, try Utf8String.init("my name is vivi 💖"), s);
try testing.expectEqualStrings(arr.items, "5\"hello15\"my name is vivi");
try testing.expectEqualStrings(arr.items, "5\"hello20\"my name is vivi 💖");
}
test "serialize enum, aka symbol" {
@ -117,7 +190,7 @@ test "serialize enum, aka symbol" {
var arr = std.ArrayList(u8).init(std.testing.allocator);
defer arr.deinit();
var s = (SyrupSerializer{ .writer = arr.writer() }).serializer();
var s = (Serializer{ .writer = arr.writer() }).serializer();
try getty.serialize(null, Testing.cool, s);
@ -133,13 +206,72 @@ test "serialize mixed" {
var arr = std.ArrayList(u8).init(std.testing.allocator);
defer arr.deinit();
var s = (SyrupSerializer{ .writer = arr.writer() }).serializer();
var s = (Serializer{ .writer = arr.writer() }).serializer();
try getty.serialize(null, 42, s);
try getty.serialize(null, "my name is vivi", s);
try getty.serialize(null, "my name is vivi 💖", s);
try getty.serialize(null, true, s);
try getty.serialize(null, Testing.enumeration, s);
try getty.serialize(null, @as(f32, 69.420), s);
try testing.expectEqualStrings(arr.items, "42+15\"my name is vivit11'enumerationF" ++ [_]u8{ 66, 138, 215, 10 });
try testing.expectEqualStrings(arr.items, "42+20:my name is vivi 💖t11'enumerationF" ++ [_]u8{ 66, 138, 215, 10 });
}
//test "zoo" {
// const zooFile = @embedFile("zoo.bin");
//
// const Animal = struct {
// species: []const u8,
// name: Utf8String,
// age: i32,
// weight: f64,
// @"alive?": bool,
// eats: std.StringArrayHashMap(void),
// };
//
// var mapCat = std.StringArrayHashMap(void).init(std.testing.allocator);
// defer mapCat.deinit();
// try mapCat.put("fish", {});
// try mapCat.put("mice", {});
// try mapCat.put("kibble", {});
//
// var mapMonkey = std.StringArrayHashMap(void).init(std.testing.allocator);
// defer mapMonkey.deinit();
// try mapMonkey.put("insects", {});
// try mapMonkey.put("bananas", {});
//
// var mapGhost = std.StringArrayHashMap(void).init(std.testing.allocator);
// defer mapGhost.deinit();
//
// const zoo = .{
// Utf8String.initAssumeEncoding("The Grand Menagerie"),
// [_]Animal{
// .{
// .species = "cat",
// .name = Utf8String.initAssumeEncoding("Tabatha"),
// .age = 12,
// .weight = 8.2,
// .@"alive?" = true,
// .eats = mapCat,
// },
// .{
// .species = "monkey",
// .name = Utf8String.initAssumeEncoding("George"),
// .age = 6,
// .weight = 17.24,
// .@"alive?" = false,
// .eats = mapMonkey,
// },
// .{
// .species = "ghost",
// .name = Utf8String.initAssumeEncoding("Casper"),
// .age = -12,
// .weight = -34.5,
// .@"alive?" = false,
// .eats = mapGhost,
// },
// },
// };
//
// std.debug.print("File: {s}\nZig struct:{any}", .{ zooFile, zoo });
//}

BIN
test-data/zoo.bin Normal file

Binary file not shown.