From 1a68504c217dec169646d5ae73e8cae31e65842d Mon Sep 17 00:00:00 2001 From: Vivianne Langdon Date: Mon, 17 Jul 2023 03:08:08 -0700 Subject: [PATCH] Initial code, all in one file for now. Readme forthcoming. --- .gitignore | 2 + build.zig | 45 +++++++++++++++ build.zig.zon | 10 ++++ src/main.zig | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 208 insertions(+) create mode 100644 .gitignore create mode 100644 build.zig create mode 100644 build.zig.zon create mode 100644 src/main.zig diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4a0641e --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +zig-cache/ +zig-out/ \ No newline at end of file diff --git a/build.zig b/build.zig new file mode 100644 index 0000000..3776b62 --- /dev/null +++ b/build.zig @@ -0,0 +1,45 @@ +const std = @import("std"); + +// Although this function looks imperative, note that its job is to +// declaratively construct a build graph that will be executed by an external +// runner. +pub fn build(b: *std.Build) void { + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); + + const opts = .{ .target = target, .optimize = optimize }; + const getty_mod = b.dependency("getty", opts).module("getty"); + + const lib = b.addStaticLibrary(.{ + .name = "zyrup", + // In this case the main source file is merely a path, however, in more + // complicated build scripts, this could be a generated file. + .root_source_file = .{ .path = "src/main.zig" }, + .target = target, + .optimize = optimize, + }); + + lib.addModule("getty", getty_mod); + + // This declares intent for the library to be installed into the standard + // location when the user invokes the "install" step (the default step when + // running `zig build`). + b.installArtifact(lib); + + // Creates a step for unit testing. This only builds the test executable + // but does not run it. + const main_tests = b.addTest(.{ + .root_source_file = .{ .path = "src/main.zig" }, + .target = target, + .optimize = optimize, + }); + main_tests.addModule("getty", getty_mod); + + const run_main_tests = b.addRunArtifact(main_tests); + + // This creates a build step. It will be visible in the `zig build --help` menu, + // and can be selected like this: `zig build test` + // This will evaluate the `test` step rather than the default, which is "install". + const test_step = b.step("test", "Run library tests"); + test_step.dependOn(&run_main_tests.step); +} diff --git a/build.zig.zon b/build.zig.zon new file mode 100644 index 0000000..77fc025 --- /dev/null +++ b/build.zig.zon @@ -0,0 +1,10 @@ +.{ + .name = "zyrup", + .version = "0.1.0", + .dependencies = .{ + .getty = .{ + .url = "https://github.com/getty-zig/getty/archive/fa6770526647e8e24537ae14dcbcb591a5784885.tar.gz", + .hash = "12205aae2ea6dcaa3efcf3751c40dbd3946e539794688bad62e79c86635762204a3d", + } + } +} \ No newline at end of file diff --git a/src/main.zig b/src/main.zig new file mode 100644 index 0000000..c0d311b --- /dev/null +++ b/src/main.zig @@ -0,0 +1,151 @@ +const std = @import("std"); +const testing = std.testing; +const getty = @import("getty"); +const builtin = @import("builtin"); +const native_endian = builtin.target.cpu.arch.endian(); + +const SyrupSerializer = struct { + usingnamespace getty.Serializer( + Self, + Ok, + Error, + null, + null, + null, + null, + null, + .{ + .serializeBool = serializeBool, + .serializeInt = serializeInt, + .serializeFloat = serializeFloat, + .serializeString = serializeString, + .serializeEnum = serializeEnum, + }, + ); + + writer: std.ArrayList(u8).Writer, + + const Self = @This(); + const Ok = void; + const Error = getty.ser.Error || std.mem.Allocator.Error; + + fn serializeBool(self: Self, value: bool) Error!Ok { + try self.writer.writeByte(if (value) 't' else 'f'); + } + + fn serializeInt(self: Self, value: anytype) Error!Ok { + try self.writer.print("{d}", .{std.math.absCast(value)}); + try self.writer.writeByte(if (value >= 0) '+' else '-'); + } + + fn serializeFloat(self: Self, value: anytype) Error!Ok { + switch (@TypeOf(value)) { + f32 => { + try self.writer.writeByte('F'); + try self.writer.writeInt(u32, @as(u32, @bitCast(value)), .Big); + }, + f64 => { + try self.writer.writeByte('D'); + try self.writer.writeInt(u64, @as(u64, @bitCast(value)), .Big); + }, + else => @compileError("Can't serialize a float that isn't f32 or f64"), + } + } + + fn serializeString(self: Self, value: anytype) Error!Ok { + try self.writer.print("{d}\"", .{value.len}); + try self.writer.print("{s}", .{value}); + } + + fn serializeEnum(self: Self, _: anytype, name: []const u8) Error!Ok { + try self.writer.print("{d}\'", .{name.len}); + try self.writer.print("{s}", .{name}); + } +}; + +test "serialize bool" { + var arr = std.ArrayList(u8).init(std.testing.allocator); + defer arr.deinit(); + + var s = (SyrupSerializer{ .writer = arr.writer() }).serializer(); + + try getty.serialize(null, true, s); + try getty.serialize(null, false, s); + try getty.serialize(null, true, s); + + try testing.expectEqualStrings(arr.items, "tft"); +} + +test "serialize ints" { + var arr = std.ArrayList(u8).init(std.testing.allocator); + defer arr.deinit(); + + var s = (SyrupSerializer{ .writer = arr.writer() }).serializer(); + + try getty.serialize(null, 42, s); + try getty.serialize(null, 86, s); + try getty.serialize(null, -356, s); + + try testing.expectEqualStrings(arr.items, "42+86+356-"); +} + +test "serialize floats" { + var arr = std.ArrayList(u8).init(std.testing.allocator); + defer arr.deinit(); + + var s = (SyrupSerializer{ .writer = arr.writer() }).serializer(); + + try getty.serialize(null, @as(f64, 42.42), s); + try getty.serialize(null, @as(f32, 42.42), s); + try testing.expectEqualSlices(u8, arr.items, &[_]u8{ 'D', 64, 69, 53, 194, 143, 92, 40, 246, 'F', 66, 41, 174, 20 }); +} + +test "serialize strs" { + var arr = std.ArrayList(u8).init(std.testing.allocator); + defer arr.deinit(); + + var s = (SyrupSerializer{ .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\"hello15\"my name is vivi"); +} + +test "serialize enum, aka symbol" { + const Testing = enum { + cool, + bad, + shitty, + }; + + var arr = std.ArrayList(u8).init(std.testing.allocator); + defer arr.deinit(); + + var s = (SyrupSerializer{ .writer = arr.writer() }).serializer(); + + try getty.serialize(null, Testing.cool, s); + + try testing.expectEqualStrings(arr.items, "4'cool"); +} + +test "serialize mixed" { + const Testing = enum { + a, + testing, + enumeration, + }; + + var arr = std.ArrayList(u8).init(std.testing.allocator); + defer arr.deinit(); + + var s = (SyrupSerializer{ .writer = arr.writer() }).serializer(); + + try getty.serialize(null, 42, 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 }); +}