build: update to zig-0.15.1

This commit is contained in:
CJ van den Berg 2025-09-30 14:07:35 +02:00
parent f1074c46d9
commit ab60648d40
Signed by: neurocyte
GPG key ID: 8EB1E1BB660E3FB9
7 changed files with 36 additions and 939 deletions

View file

@ -3,7 +3,7 @@ Themes compiler for Flow-Control, the text editor
## Requirements
- zig 0.13
- zig 0.15.1
- hjson (installed in your PATH)
## Build

View file

@ -3,12 +3,15 @@ const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const cbor_mod = b.createModule(.{ .root_source_file = b.path("src/cbor.zig") });
const cbor_dep = b.dependency("cbor", .{ .target = target });
const cbor_mod = cbor_dep.module("cbor");
const theme_mod = b.createModule(.{ .root_source_file = b.path("src/theme.zig") });
const themes_compile = b.addExecutable(.{
.name = "themes_compile",
.target = target,
.root_module = b.createModule(.{
.root_source_file = b.path("src/compile.zig"),
.target = target,
}),
});
add_themes(b, themes_compile);
themes_compile.root_module.addImport("cbor", cbor_mod);

View file

@ -1 +1 @@
0.13.0
0.15.1

View file

@ -1,6 +1,8 @@
.{
.name = "flow-themes",
.name = .flow_themes,
.version = "0.0.1",
.minimum_zig_version = "0.15.1",
.fingerprint = 0x4c6fd5b6412e42ff,
.dependencies = .{
@ -89,6 +91,10 @@
.url = "https://github.com/pzinovkin/base16-vscode/archive/f25f8495f50ef4481920ff3db7efec3f28b9fb2f.tar.gz",
.hash = "1220a66a6ef581de3f480883b11bf049956ca0b2130b14a84a7f1b8ca05123088794",
},
.cbor = .{
.url = "git+https://github.com/neurocyte/cbor?ref=master#7d2eeb68c8a2fb3f4d6baad6cc04c521b92974c0",
.hash = "cbor-1.0.0-RcQE_AswAQAPlqBCZXYQf9DZXn-0Ubt8Mk03ZcJWcsAG",
},
},
.paths = .{
"build.zig",

View file

@ -1,914 +0,0 @@
const std = @import("std");
const eql = std.mem.eql;
const bufPrint = std.fmt.bufPrint;
const fixedBufferStream = std.io.fixedBufferStream;
const maxInt = std.math.maxInt;
const minInt = std.math.minInt;
const json = std.json;
const fba = std.heap.FixedBufferAllocator;
pub const CborError = error{
CborIntegerTooLarge,
CborIntegerTooSmall,
CborInvalidType,
CborTooShort,
OutOfMemory,
};
pub const CborJsonError = error{
BufferUnderrun,
CborIntegerTooLarge,
CborIntegerTooSmall,
CborInvalidType,
CborTooShort,
CborUnsupportedType,
NoSpaceLeft,
OutOfMemory,
Overflow,
SyntaxError,
UnexpectedEndOfInput,
};
const cbor_magic_null: u8 = 0xf6;
const cbor_magic_true: u8 = 0xf5;
const cbor_magic_false: u8 = 0xf4;
const cbor_magic_type_array: u8 = 4;
const cbor_magic_type_map: u8 = 5;
const value_type = enum(u8) {
number,
bytes,
string,
array,
map,
tag,
boolean,
null,
any,
more,
unknown,
};
pub const number = value_type.number;
pub const bytes = value_type.bytes;
pub const string = value_type.string;
pub const array = value_type.array;
pub const map = value_type.map;
pub const tag = value_type.tag;
pub const boolean = value_type.boolean;
pub const null_ = value_type.null;
pub const any = value_type.any;
pub const more = value_type.more;
const null_value_buf = [_]u8{0xF6};
pub const null_value: []const u8 = &null_value_buf;
pub fn isNull(val: []const u8) bool {
return eql(u8, val, null_value);
}
fn isAny(value: anytype) bool {
return if (comptime @TypeOf(value) == value_type) value == value_type.any else false;
}
fn isMore(value: anytype) bool {
return if (comptime @TypeOf(value) == value_type) value == value_type.more else false;
}
fn write(writer: anytype, value: u8) @TypeOf(writer).Error!void {
_ = try writer.write(&[_]u8{value});
}
fn writeTypedVal(writer: anytype, type_: u8, value: u64) @TypeOf(writer).Error!void {
const t: u8 = type_ << 5;
if (value < 24) {
try write(writer, t | @as(u8, @truncate(value)));
} else if (value < 256) {
try write(writer, t | 24);
try write(writer, @as(u8, @truncate(value)));
} else if (value < 65536) {
try write(writer, t | 25);
try write(writer, @as(u8, @truncate(value >> 8)));
try write(writer, @as(u8, @truncate(value)));
} else if (value < 4294967296) {
try write(writer, t | 26);
try write(writer, @as(u8, @truncate(value >> 24)));
try write(writer, @as(u8, @truncate(value >> 16)));
try write(writer, @as(u8, @truncate(value >> 8)));
try write(writer, @as(u8, @truncate(value)));
} else {
try write(writer, t | 27);
try write(writer, @as(u8, @truncate(value >> 56)));
try write(writer, @as(u8, @truncate(value >> 48)));
try write(writer, @as(u8, @truncate(value >> 40)));
try write(writer, @as(u8, @truncate(value >> 32)));
try write(writer, @as(u8, @truncate(value >> 24)));
try write(writer, @as(u8, @truncate(value >> 16)));
try write(writer, @as(u8, @truncate(value >> 8)));
try write(writer, @as(u8, @truncate(value)));
}
}
pub fn writeArrayHeader(writer: anytype, sz: usize) @TypeOf(writer).Error!void {
return writeTypedVal(writer, cbor_magic_type_array, sz);
}
pub fn writeMapHeader(writer: anytype, sz: usize) @TypeOf(writer).Error!void {
return writeTypedVal(writer, cbor_magic_type_map, sz);
}
pub fn writeArray(writer: anytype, args: anytype) @TypeOf(writer).Error!void {
const args_type_info = @typeInfo(@TypeOf(args));
if (args_type_info != .Struct) @compileError("expected tuple or struct argument");
const fields_info = args_type_info.Struct.fields;
try writeArrayHeader(writer, fields_info.len);
inline for (fields_info) |field_info|
try writeValue(writer, @field(args, field_info.name));
}
fn writeI64(writer: anytype, value: i64) @TypeOf(writer).Error!void {
return if (value < 0)
writeTypedVal(writer, 1, @as(u64, @bitCast(-(value + 1))))
else
writeTypedVal(writer, 0, @as(u64, @bitCast(value)));
}
fn writeU64(writer: anytype, value: u64) @TypeOf(writer).Error!void {
return writeTypedVal(writer, 0, value);
}
fn writeString(writer: anytype, s: []const u8) @TypeOf(writer).Error!void {
try writeTypedVal(writer, 3, s.len);
_ = try writer.write(s);
}
fn writeBool(writer: anytype, value: bool) @TypeOf(writer).Error!void {
return write(writer, if (value) cbor_magic_true else cbor_magic_false);
}
fn writeNull(writer: anytype) @TypeOf(writer).Error!void {
return write(writer, cbor_magic_null);
}
fn writeErrorset(writer: anytype, err: anyerror) @TypeOf(writer).Error!void {
var buf: [256]u8 = undefined;
const errmsg = try bufPrint(&buf, "error.{s}", .{@errorName(err)});
return writeString(writer, errmsg);
}
pub fn writeValue(writer: anytype, value: anytype) @TypeOf(writer).Error!void {
const T = @TypeOf(value);
switch (@typeInfo(T)) {
.Int, .ComptimeInt => return if (T == u64) writeU64(writer, value) else writeI64(writer, @intCast(value)),
.Bool => return writeBool(writer, value),
.Optional => return if (value) |v| writeValue(writer, v) else writeNull(writer),
.ErrorUnion => return if (value) |v| writeValue(writer, v) else |err| writeValue(writer, err),
.ErrorSet => return writeErrorset(writer, value),
.Union => |info| {
if (info.tag_type) |TagType| {
comptime var v = void;
inline for (info.fields) |u_field| {
if (value == @field(TagType, u_field.name))
v = @field(value, u_field.name);
}
try writeArray(writer, .{
@typeName(T),
@tagName(@as(TagType, value)),
v,
});
} else {
try writeArray(writer, .{@typeName(T)});
}
},
.Struct => |info| {
if (info.is_tuple) {
if (info.fields.len == 0) return writeNull(writer);
try writeArrayHeader(writer, info.fields.len);
inline for (info.fields) |f|
try writeValue(writer, @field(value, f.name));
} else {
if (info.fields.len == 0) return writeNull(writer);
try writeMapHeader(writer, info.fields.len);
inline for (info.fields) |f| {
try writeString(writer, f.name);
try writeValue(writer, @field(value, f.name));
}
}
},
.Pointer => |ptr_info| switch (ptr_info.size) {
.One => return writeValue(writer, value.*),
.Many, .C => @compileError("cannot write type '" ++ @typeName(T) ++ "' to cbor stream"),
.Slice => {
if (ptr_info.child == u8) return writeString(writer, value);
if (value.len == 0) return writeNull(writer);
try writeArrayHeader(writer, value.len);
for (value) |elem|
try writeValue(writer, elem);
},
},
.Array => |info| {
if (info.child == u8) return writeString(writer, &value);
if (value.len == 0) return writeNull(writer);
try writeArrayHeader(writer, value.len);
for (value) |elem|
try writeValue(writer, elem);
},
.Vector => |info| {
try writeArrayHeader(writer, info.len);
var i: usize = 0;
while (i < info.len) : (i += 1) {
try writeValue(writer, value[i]);
}
},
.Null => try writeNull(writer),
else => @compileError("cannot write type '" ++ @typeName(T) ++ "' to cbor stream"),
}
}
pub fn fmt(buf: []u8, value: anytype) []const u8 {
var stream = fixedBufferStream(buf);
writeValue(stream.writer(), value) catch unreachable;
return stream.getWritten();
}
const CborType = struct { type: u8, minor: u5, major: u3 };
pub fn decodeType(iter: *[]const u8) error{CborTooShort}!CborType {
if (iter.len < 1)
return error.CborTooShort;
const type_: u8 = iter.*[0];
const bits: packed struct { minor: u5, major: u3 } = @bitCast(type_);
iter.* = iter.*[1..];
return .{ .type = type_, .minor = bits.minor, .major = bits.major };
}
fn decodeUIntLengthRecurse(iter: *[]const u8, length: usize, acc: u64) !u64 {
if (iter.len < 1)
return error.CborTooShort;
const v: u8 = iter.*[0];
iter.* = iter.*[1..];
var i = acc | v;
if (length == 1)
return i;
i <<= 8;
// return @call(.always_tail, decodeUIntLengthRecurse, .{ iter, length - 1, i }); FIXME: @call(.always_tail) seems broken as of 0.11.0-dev.2964+e9cbdb2cf
return decodeUIntLengthRecurse(iter, length - 1, i);
}
fn decodeUIntLength(iter: *[]const u8, length: usize) !u64 {
return decodeUIntLengthRecurse(iter, length, 0);
}
fn decodePInt(iter: *[]const u8, minor: u5) !u64 {
if (minor < 24) return minor;
return switch (minor) {
24 => decodeUIntLength(iter, 1), // 1 byte
25 => decodeUIntLength(iter, 2), // 2 byte
26 => decodeUIntLength(iter, 4), // 4 byte
27 => decodeUIntLength(iter, 8), // 8 byte
else => error.CborInvalidType,
};
}
fn decodeNInt(iter: *[]const u8, minor: u5) CborError!i64 {
return -@as(i64, @intCast(try decodePInt(iter, minor) + 1));
}
pub fn decodeMapHeader(iter: *[]const u8) CborError!usize {
const t = try decodeType(iter);
if (t.type == cbor_magic_null)
return 0;
if (t.major != 5)
return error.CborInvalidType;
return decodePInt(iter, t.minor);
}
pub fn decodeArrayHeader(iter: *[]const u8) CborError!usize {
const t = try decodeType(iter);
if (t.type == cbor_magic_null)
return 0;
if (t.major != 4)
return error.CborInvalidType;
return decodePInt(iter, t.minor);
}
fn decodeString(iter_: *[]const u8, minor: u5) CborError![]const u8 {
var iter = iter_.*;
const len = try decodePInt(&iter, minor);
if (iter.len < len)
return error.CborTooShort;
const s = iter[0..len];
iter = iter[len..];
iter_.* = iter;
return s;
}
fn decodeBytes(iter: *[]const u8, minor: u5) CborError![]const u8 {
return decodeString(iter, minor);
}
fn decodeJsonArray(iter_: *[]const u8, minor: u5, arr: *json.Array) CborError!bool {
var iter = iter_.*;
var n = try decodePInt(&iter, minor);
while (n > 0) {
const value = try arr.addOne();
if (!try matchJsonValue(&iter, value, arr.allocator))
return false;
n -= 1;
}
iter_.* = iter;
return true;
}
fn decodeJsonObject(iter_: *[]const u8, minor: u5, obj: *json.ObjectMap) CborError!bool {
var iter = iter_.*;
var n = try decodePInt(&iter, minor);
while (n > 0) {
var key: []u8 = undefined;
var value: json.Value = .null;
if (!try matchString(&iter, &key))
return false;
if (!try matchJsonValue(&iter, &value, obj.allocator))
return false;
_ = try obj.getOrPutValue(key, value);
n -= 1;
}
iter_.* = iter;
return true;
}
pub fn matchInt(comptime T: type, iter_: *[]const u8, val: *T) CborError!bool {
var iter = iter_.*;
const t = try decodeType(&iter);
val.* = switch (t.major) {
0 => blk: { // positive integer
const v = try decodePInt(&iter, t.minor);
if (v > maxInt(T))
return error.CborIntegerTooLarge;
break :blk @intCast(v);
},
1 => blk: { // negative integer
const v = try decodeNInt(&iter, t.minor);
if (v < minInt(T))
return error.CborIntegerTooSmall;
break :blk @intCast(v);
},
else => return false,
};
iter_.* = iter;
return true;
}
pub fn matchIntValue(comptime T: type, iter: *[]const u8, val: T) CborError!bool {
var v: T = 0;
return if (try matchInt(T, iter, &v)) v == val else false;
}
pub fn matchBool(iter_: *[]const u8, v: *bool) CborError!bool {
var iter = iter_.*;
const t = try decodeType(&iter);
if (t.major == 7) { // special
if (t.type == cbor_magic_false) {
v.* = false;
iter_.* = iter;
return true;
}
if (t.type == cbor_magic_true) {
v.* = true;
iter_.* = iter;
return true;
}
}
return false;
}
fn matchBoolValue(iter: *[]const u8, val: bool) CborError!bool {
var v: bool = false;
return if (try matchBool(iter, &v)) v == val else false;
}
fn skipString(iter: *[]const u8, minor: u5) CborError!void {
const len = try decodePInt(iter, minor);
if (iter.len < len)
return error.CborTooShort;
iter.* = iter.*[len..];
}
fn skipBytes(iter: *[]const u8, minor: u5) CborError!void {
return skipString(iter, minor);
}
fn skipArray(iter: *[]const u8, minor: u5) CborError!void {
var len = try decodePInt(iter, minor);
while (len > 0) {
try skipValue(iter);
len -= 1;
}
}
fn skipMap(iter: *[]const u8, minor: u5) CborError!void {
var len = try decodePInt(iter, minor);
len *= 2;
while (len > 0) {
try skipValue(iter);
len -= 1;
}
}
pub fn skipValue(iter: *[]const u8) CborError!void {
const t = try decodeType(iter);
try skipValueType(iter, t.major, t.minor);
}
fn skipValueType(iter: *[]const u8, major: u3, minor: u5) CborError!void {
switch (major) {
0 => { // positive integer
_ = try decodePInt(iter, minor);
},
1 => { // negative integer
_ = try decodeNInt(iter, minor);
},
2 => { // bytes
try skipBytes(iter, minor);
},
3 => { // string
try skipString(iter, minor);
},
4 => { // array
try skipArray(iter, minor);
},
5 => { // map
try skipMap(iter, minor);
},
6 => { // tag
return error.CborInvalidType;
},
7 => { // special
return;
},
}
}
fn matchType(iter_: *[]const u8, v: *value_type) CborError!bool {
var iter = iter_.*;
const t = try decodeType(&iter);
try skipValueType(&iter, t.major, t.minor);
switch (t.major) {
0, 1 => v.* = value_type.number, // positive integer or negative integer
2 => v.* = value_type.bytes, // bytes
3 => v.* = value_type.string, // string
4 => v.* = value_type.array, // array
5 => v.* = value_type.map, // map
7 => { // special
if (t.type == cbor_magic_null) {
v.* = value_type.null;
} else {
if (t.type == cbor_magic_false or t.type == cbor_magic_true) {
v.* = value_type.boolean;
} else {
return false;
}
}
},
else => return false,
}
iter_.* = iter;
return true;
}
fn matchValueType(iter: *[]const u8, t: value_type) CborError!bool {
var v: value_type = value_type.unknown;
return if (try matchType(iter, &v)) (t == value_type.any or t == v) else false;
}
pub fn matchString(iter_: *[]const u8, val: *[]const u8) CborError!bool {
var iter = iter_.*;
const t = try decodeType(&iter);
val.* = switch (t.major) {
2 => try decodeBytes(&iter, t.minor), // bytes
3 => try decodeString(&iter, t.minor), // string
else => return false,
};
iter_.* = iter;
return true;
}
fn matchStringValue(iter: *[]const u8, lit: []const u8) CborError!bool {
var val: []const u8 = undefined;
return if (try matchString(iter, &val)) eql(u8, val, lit) else false;
}
fn matchError(comptime T: type) noreturn {
@compileError("cannot match type '" ++ @typeName(T) ++ "' to cbor stream");
}
pub fn matchValue(iter: *[]const u8, value: anytype) CborError!bool {
if (@TypeOf(value) == value_type)
return matchValueType(iter, value);
const T = comptime @TypeOf(value);
if (comptime isExtractor(T))
return value.extract(iter);
return switch (comptime @typeInfo(T)) {
.Int => return matchIntValue(T, iter, value),
.ComptimeInt => return matchIntValue(i64, iter, value),
.Bool => matchBoolValue(iter, value),
.Pointer => |info| switch (info.size) {
.One => matchValue(iter, value.*),
.Many, .C => matchError(T),
.Slice => if (info.child == u8) matchStringValue(iter, value) else matchArray(iter, value, info),
},
.Struct => |info| if (info.is_tuple)
matchArray(iter, value, info)
else
matchError(T),
.Array => |info| if (info.child == u8) matchStringValue(iter, &value) else matchArray(iter, value, info),
else => @compileError("cannot match value type '" ++ @typeName(T) ++ "' to cbor stream"),
};
}
fn matchJsonValue(iter_: *[]const u8, v: *json.Value, a: std.mem.Allocator) CborError!bool {
var iter = iter_.*;
const t = try decodeType(&iter);
const ret = switch (t.major) {
0 => ret: { // positive integer
v.* = json.Value{ .integer = @intCast(try decodePInt(&iter, t.minor)) };
break :ret true;
},
1 => ret: { // negative integer
v.* = json.Value{ .integer = try decodeNInt(&iter, t.minor) };
break :ret true;
},
2 => ret: { // bytes
break :ret false;
},
3 => ret: { // string
v.* = json.Value{ .string = try decodeString(&iter, t.minor) };
break :ret true;
},
4 => ret: { // array
v.* = json.Value{ .array = json.Array.init(a) };
break :ret try decodeJsonArray(&iter, t.minor, &v.array);
},
5 => ret: { // map
v.* = json.Value{ .object = json.ObjectMap.init(a) };
break :ret try decodeJsonObject(&iter, t.minor, &v.object);
},
6 => ret: { // tag
break :ret false;
},
7 => ret: { // special
switch (t.type) {
cbor_magic_false => {
v.* = json.Value{ .bool = false };
break :ret true;
},
cbor_magic_true => {
v.* = json.Value{ .bool = true };
break :ret true;
},
cbor_magic_null => {
v.* = json.Value{ .null = {} };
break :ret true;
},
else => break :ret false,
}
},
};
if (ret) iter_.* = iter;
return ret;
}
fn matchArrayMore(iter_: *[]const u8, n_: u64) CborError!bool {
var iter = iter_.*;
var n = n_;
while (n > 0) {
if (!try matchValue(&iter, value_type.any))
return false;
n -= 1;
}
iter_.* = iter;
return true;
}
fn matchArray(iter_: *[]const u8, arr: anytype, info: anytype) CborError!bool {
var iter = iter_.*;
var n = try decodeArrayHeader(&iter);
inline for (info.fields) |f| {
const value = @field(arr, f.name);
if (isMore(value))
break;
} else if (info.fields.len != n)
return false;
inline for (info.fields) |f| {
const value = @field(arr, f.name);
if (isMore(value))
return matchArrayMore(&iter, n);
if (n == 0) return false;
const matched = try matchValue(&iter, @field(arr, f.name));
if (!matched) return false;
n -= 1;
}
if (n == 0) iter_.* = iter;
return n == 0;
}
fn matchJsonObject(iter_: *[]const u8, obj: *json.ObjectMap) !bool {
var iter = iter_.*;
const t = try decodeType(&iter);
if (t.type == cbor_magic_null)
return true;
if (t.major != 5)
return error.CborInvalidType;
const ret = try decodeJsonObject(&iter, t.minor, obj);
if (ret) iter_.* = iter;
return ret;
}
pub fn match(buf: []const u8, pattern: anytype) CborError!bool {
var iter: []const u8 = buf;
return matchValue(&iter, pattern);
}
fn extractError(comptime T: type) noreturn {
@compileError("cannot extract type '" ++ @typeName(T) ++ "' from cbor stream");
}
fn hasExtractorTag(info: anytype) bool {
if (info.is_tuple) return false;
inline for (info.decls) |decl| {
if (comptime eql(u8, decl.name, "EXTRACTOR_TAG"))
return true;
}
return false;
}
fn isExtractor(comptime T: type) bool {
return comptime switch (@typeInfo(T)) {
.Struct => |info| hasExtractorTag(info),
else => false,
};
}
const JsonValueExtractor = struct {
dest: *T,
const Self = @This();
pub const EXTRACTOR_TAG = struct {};
const T = json.Value;
pub fn init(dest: *T) Self {
return .{ .dest = dest };
}
pub fn extract(self: Self, iter: *[]const u8) CborError!bool {
var null_heap_: [0]u8 = undefined;
var heap = fba.init(&null_heap_);
return matchJsonValue(iter, self.dest, heap.allocator());
}
};
const JsonObjectExtractor = struct {
dest: *T,
const Self = @This();
pub const EXTRACTOR_TAG = struct {};
const T = json.ObjectMap;
pub fn init(dest: *T) Self {
return .{ .dest = dest };
}
pub fn extract(self: Self, iter: *[]const u8) CborError!bool {
return matchJsonObject(iter, self.dest);
}
};
fn Extractor(comptime T: type) type {
if (T == json.Value)
return JsonValueExtractor;
if (T == json.ObjectMap)
return JsonObjectExtractor;
return struct {
dest: *T,
const Self = @This();
pub const EXTRACTOR_TAG = struct {};
pub fn init(dest: *T) Self {
return .{ .dest = dest };
}
pub fn extract(self: Self, iter: *[]const u8) CborError!bool {
switch (comptime @typeInfo(T)) {
.Int, .ComptimeInt => return matchInt(T, iter, self.dest),
.Bool => return matchBool(iter, self.dest),
.Pointer => |ptr_info| switch (ptr_info.size) {
.Slice => {
if (ptr_info.child == u8) return matchString(iter, self.dest) else extractError(T);
},
else => extractError(T),
},
else => extractError(T),
}
}
};
}
fn ExtractorType(comptime T: type) type {
const T_type_info = @typeInfo(T);
if (T_type_info != .Pointer) @compileError("extract requires a pointer argument");
return Extractor(T_type_info.Pointer.child);
}
pub fn extract(dest: anytype) ExtractorType(@TypeOf(dest)) {
comptime {
if (!isExtractor(ExtractorType(@TypeOf(dest))))
@compileError("isExtractor self check failed for " ++ @typeName(ExtractorType(@TypeOf(dest))));
}
return ExtractorType(@TypeOf(dest)).init(dest);
}
const CborExtractor = struct {
dest: *[]const u8,
const Self = @This();
pub const EXTRACTOR_TAG = struct {};
pub fn init(dest: *[]const u8) Self {
return .{ .dest = dest };
}
pub fn extract(self: Self, iter: *[]const u8) CborError!bool {
const b = iter.*;
try skipValue(iter);
self.dest.* = b[0..(b.len - iter.len)];
return true;
}
};
pub fn extract_cbor(dest: *[]const u8) CborExtractor {
return CborExtractor.init(dest);
}
pub fn JsonStream(comptime T: type) type {
return struct {
const Writer = T.Writer;
const JsonWriter = json.WriteStream(Writer, .{ .checked_to_fixed_depth = 256 });
fn jsonWriteArray(w: *JsonWriter, iter: *[]const u8, minor: u5) !void {
var count = try decodePInt(iter, minor);
try w.beginArray();
while (count > 0) : (count -= 1) {
try jsonWriteValue(w, iter);
}
try w.endArray();
}
fn jsonWriteMap(w: *JsonWriter, iter: *[]const u8, minor: u5) !void {
var count = try decodePInt(iter, minor);
try w.beginObject();
while (count > 0) : (count -= 1) {
const t = try decodeType(iter);
if (t.major != 3) return error.CborInvalidType;
try w.objectField(try decodeString(iter, t.minor));
try jsonWriteValue(w, iter);
}
try w.endObject();
}
pub fn jsonWriteValue(w: *JsonWriter, iter: *[]const u8) (CborJsonError || Writer.Error)!void {
const t = try decodeType(iter);
if (t.type == cbor_magic_false)
return w.write(false);
if (t.type == cbor_magic_true)
return w.write(true);
if (t.type == cbor_magic_null)
return w.write(null);
return switch (t.major) {
0 => w.write(try decodePInt(iter, t.minor)), // positive integer
1 => w.write(try decodeNInt(iter, t.minor)), // negative integer
2 => error.CborUnsupportedType, // bytes
3 => w.write(try decodeString(iter, t.minor)), // string
4 => jsonWriteArray(w, iter, t.minor), // array
5 => jsonWriteMap(w, iter, t.minor), // map
else => error.CborInvalidType,
};
}
};
}
pub fn toJson(cbor_buf: []const u8, json_buf: []u8) CborJsonError![]const u8 {
var fbs = fixedBufferStream(json_buf);
var s = json.writeStream(fbs.writer(), .{});
var iter: []const u8 = cbor_buf;
try JsonStream(@TypeOf(fbs)).jsonWriteValue(&s, &iter);
return fbs.getWritten();
}
pub fn toJsonPretty(cbor_buf: []const u8, json_buf: []u8) CborJsonError![]const u8 {
var fbs = fixedBufferStream(json_buf);
var s = json.writeStream(fbs.writer(), .{ .whitespace = .indent_1 });
var iter: []const u8 = cbor_buf;
try JsonStream(@TypeOf(fbs)).jsonWriteValue(&s, &iter);
return fbs.getWritten();
}
fn writeJsonValue(writer: anytype, value: json.Value) !void {
try switch (value) {
.array => |_| unreachable,
.object => |_| unreachable,
.null => writeNull(writer),
.float => |_| error.CborUnsupportedType,
inline else => |v| writeValue(writer, v),
};
}
fn jsonScanUntil(writer: anytype, scanner: *json.Scanner, end_token: anytype) CborJsonError!usize {
var partial = try std.BoundedArray(u8, 4096).init(0);
var count: usize = 0;
var token = try scanner.next();
while (token != end_token) : (token = try scanner.next()) {
count += 1;
switch (token) {
.object_begin => try writeJsonObject(writer, scanner),
.array_begin => try writeJsonArray(writer, scanner),
.true => try writeBool(writer, true),
.false => try writeBool(writer, false),
.null => try writeNull(writer),
.number => |v| {
try partial.appendSlice(v);
try writeJsonValue(writer, json.Value.parseFromNumberSlice(partial.slice()));
try partial.resize(0);
},
.partial_number => |v| {
try partial.appendSlice(v);
count -= 1;
},
.string => |v| {
try partial.appendSlice(v);
try writeString(writer, partial.slice());
try partial.resize(0);
},
.partial_string => |v| {
try partial.appendSlice(v);
count -= 1;
},
.partial_string_escaped_1 => |v| {
try partial.appendSlice(&v);
count -= 1;
},
.partial_string_escaped_2 => |v| {
try partial.appendSlice(&v);
count -= 1;
},
.partial_string_escaped_3 => |v| {
try partial.appendSlice(&v);
count -= 1;
},
.partial_string_escaped_4 => |v| {
try partial.appendSlice(&v);
count -= 1;
},
else => return error.SyntaxError,
}
}
return count;
}
pub const local_heap_size = 4096 * 16;
fn writeJsonArray(writer_: anytype, scanner: *json.Scanner) CborJsonError!void {
var buf: [local_heap_size]u8 = undefined;
var stream = fixedBufferStream(&buf);
const writer = stream.writer();
const count = try jsonScanUntil(writer, scanner, .array_end);
try writeArrayHeader(writer_, count);
try writer_.writeAll(stream.getWritten());
}
fn writeJsonObject(writer_: anytype, scanner: *json.Scanner) CborJsonError!void {
var buf: [local_heap_size]u8 = undefined;
var stream = fixedBufferStream(&buf);
const writer = stream.writer();
const count = try jsonScanUntil(writer, scanner, .object_end);
try writeMapHeader(writer_, count / 2);
try writer_.writeAll(stream.getWritten());
}
pub fn fromJson(json_buf: []const u8, cbor_buf: []u8) ![]const u8 {
var local_heap_: [local_heap_size]u8 = undefined;
var heap = fba.init(&local_heap_);
var stream = fixedBufferStream(cbor_buf);
const writer = stream.writer();
var scanner = json.Scanner.initCompleteInput(heap.allocator(), json_buf);
defer scanner.deinit();
_ = try jsonScanUntil(writer, &scanner, .end_of_document);
return stream.getWritten();
}

View file

@ -271,17 +271,17 @@ fn load_scopes_string(tokens: *TokenMap, style: Style, scopes_: []const u8) void
fn to_token_array(tokens: TokenMap) []Token {
var iter = tokens.iterator();
var arr = std.ArrayList(Token).init(allocator);
var arr: std.ArrayList(Token) = .empty;
while (iter.next()) |token|
(arr.addOne() catch unreachable).* = Token{ .id = to_scope_id(token.key_ptr.*), .style = token.value_ptr.* };
const result = arr.toOwnedSlice() catch unreachable;
(arr.addOne(allocator) catch unreachable).* = Token{ .id = to_scope_id(token.key_ptr.*), .style = token.value_ptr.* };
const result = arr.toOwnedSlice(allocator) catch unreachable;
std.sort.pdq(Token, result, {}, compare_tokens);
return result;
}
fn to_scope_id(scope: []const u8) usize {
if (scopes.get(scope)) |id| return id;
(scopes_vec.addOne() catch unreachable).* = scope;
(scopes_vec.addOne(allocator) catch unreachable).* = scope;
const id = scopes_vec.items.len - 1;
scopes.put(scope, id) catch unreachable;
return id;
@ -926,11 +926,11 @@ const defaults = struct {
const Writer = std.fs.File.Writer;
fn write_field_string(writer: Writer, name: []const u8, value: []const u8) !void {
fn write_field_string(writer: *std.Io.Writer, name: []const u8, value: []const u8) !void {
_ = try writer.print(" .@\"{s}\" = \"{s}\",\n", .{ name, value });
}
fn write_Style(writer: Writer, value: Style) !void {
fn write_Style(writer: *std.Io.Writer, value: Style) !void {
_ = try writer.print(".{{ ", .{});
if (value.fg) |fg| _ = try writer.print(".fg = .{{ .color = 0x{x}, .alpha = 0x{x} }},", .{ fg.color, fg.alpha });
if (value.bg) |bg| _ = try writer.print(".bg = .{{ .color = 0x{x}, .alpha = 0x{x} }},", .{ bg.color, bg.alpha });
@ -945,13 +945,13 @@ fn write_Style(writer: Writer, value: Style) !void {
_ = try writer.print("}}", .{});
}
fn write_field_Style(writer: Writer, name: []const u8, value: Style) !void {
fn write_field_Style(writer: *std.Io.Writer, name: []const u8, value: Style) !void {
_ = try writer.print(" .@\"{s}\" = ", .{name});
try write_Style(writer, value);
_ = try writer.print(",\n", .{});
}
fn write_field_token_array(writer: Writer, name: []const u8, values: Tokens) !void {
fn write_field_token_array(writer: *std.Io.Writer, name: []const u8, values: Tokens) !void {
_ = try writer.print(" .@\"{s}\" = &[_]theme.Token{{ \n", .{name});
for (values) |value| {
_ = try writer.print(" .{{ .id = {d}, .style = ", .{value.id});
@ -961,7 +961,7 @@ fn write_field_token_array(writer: Writer, name: []const u8, values: Tokens) !vo
_ = try writer.print(" }},\n", .{});
}
fn write_field(writer: Writer, name: []const u8, value: anytype) !void {
fn write_field(writer: *std.Io.Writer, name: []const u8, value: anytype) !void {
return if (@TypeOf(value) == Style)
write_field_Style(writer, name, value)
else if (@TypeOf(value) == Tokens)
@ -970,16 +970,16 @@ fn write_field(writer: Writer, name: []const u8, value: anytype) !void {
write_field_string(writer, name, value);
}
fn write_theme(writer: Writer, item: theme) !void {
fn write_theme(writer: *std.Io.Writer, item: theme) !void {
_ = try writer.write(" .{\n");
inline for (@typeInfo(theme).Struct.fields) |field_info|
inline for (@typeInfo(theme).@"struct".fields) |field_info|
try write_field(writer, field_info.name, @field(item, field_info.name));
_ = try writer.write(" },\n");
}
fn write_all_themes(writer: Writer) !void {
fn write_all_themes(writer: *std.Io.Writer) !void {
_ = try writer.write("const theme = @import(\"theme\");\n");
_ = try writer.write("pub const themes = [_]theme{\n");
for (&theme_files) |*file| {
@ -1008,7 +1008,7 @@ pub fn main() !void {
const arena = arena_state.allocator();
allocator = arena;
scopes = ScopeMap.init(allocator);
scopes_vec = std.ArrayList([]const u8).init(allocator);
scopes_vec = .empty;
const args = try std.process.argsAlloc(arena);
@ -1020,7 +1020,10 @@ pub fn main() !void {
fatal("unable to open '{s}': {s}", .{ output_file_path, @errorName(err) });
};
defer output_file.close();
try write_all_themes(output_file.writer());
var buf: [4096]u8 = undefined;
var writer = output_file.writer(&buf);
defer writer.interface.flush() catch @panic("flush failed");
try write_all_themes(&writer.interface);
return std.process.cleanExit();
}
@ -1039,13 +1042,12 @@ fn hjson(data: []const u8) ![]const u8 {
try child.stdin.?.writeAll(data);
child.stdin.?.close();
child.stdin = null;
var out = std.ArrayList(u8).init(allocator);
var writer = out.writer();
var out: std.Io.Writer.Allocating = .init(allocator);
var buffer: [256]u8 = undefined;
while (true) {
const bytesRead = try child.stdout.?.read(&buffer);
if (bytesRead == 0) break;
try writer.writeAll(buffer[0..bytesRead]);
try out.writer.writeAll(buffer[0..bytesRead]);
}
const term = child.wait() catch |e| std.debug.panic("error running hjson: {any}", .{e});
switch (term) {

2
zig
View file

@ -24,7 +24,7 @@ if [ "$ARCH" == "arm64" ]; then
ARCH=aarch64
fi
ZIGVER="zig-$OS-$ARCH-$VERSION"
ZIGVER="zig-$ARCH-$OS-$VERSION"
ZIG=$ZIGDIR/$ZIGVER/zig
if [ "$1" == "update" ]; then