:D
This commit is contained in:
parent
6c68c4cb33
commit
e87e08e964
10
language.zig
10
language.zig
@ -103,20 +103,12 @@ pub const Flags = packed struct {
|
|||||||
allow_comments: bool = false,
|
allow_comments: bool = false,
|
||||||
/// Not to error on trailing comma, default is `false` for obvious reasons
|
/// Not to error on trailing comma, default is `false` for obvious reasons
|
||||||
allow_trailing_comma: bool = false,
|
allow_trailing_comma: bool = false,
|
||||||
/// Allows parsing `packed struct` as an `int`, size is the backing int
|
|
||||||
bitfields: bool = false,
|
|
||||||
/// Allows parsing `enum` as an `int`, size is the backing int
|
|
||||||
real_enums: bool = false,
|
|
||||||
/// Allows parsing unions, default behaviour is yet to be concluded
|
|
||||||
unions: bool = false,
|
|
||||||
/// To cast numbers always as f64, as the name says
|
|
||||||
numbersf64: bool = false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Options = struct {
|
pub const Options = struct {
|
||||||
comptime indent_len: usize = 4,
|
comptime indent_len: usize = 4,
|
||||||
comptime max_depth: usize = 256,
|
comptime max_depth: usize = 256,
|
||||||
comptime flags: Flags = .{},
|
flags: Flags = .{},
|
||||||
};
|
};
|
||||||
|
|
||||||
index: std.MultiArrayList(JsonValue) = .{},
|
index: std.MultiArrayList(JsonValue) = .{},
|
||||||
|
@ -33,35 +33,59 @@ pub fn deinit(self: *Self, allocator: mem.Allocator) void {
|
|||||||
allocator.destroy(self.tokenizer);
|
allocator.destroy(self.tokenizer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// always returns 0 (root)
|
/// needs an index but useful otherwise
|
||||||
/// needs an index
|
/// root starting from idx
|
||||||
/// const idx: usize = try self.language.parse(allocator, self.tokenizer);
|
|
||||||
pub fn reflectT(self: *Self, comptime T: type, allocator: mem.Allocator, idx: usize) !T {
|
pub fn reflectT(self: *Self, comptime T: type, allocator: mem.Allocator, idx: usize) !T {
|
||||||
const Schema = @typeInfo(T);
|
const Schema = @typeInfo(T);
|
||||||
|
const flags = self.language.options.flags;
|
||||||
|
|
||||||
switch (self.language.index.get(idx)) {
|
switch (self.language.index.get(idx)) {
|
||||||
.null => {
|
.null => {
|
||||||
if (Schema == .null) return null;
|
if (Schema == .null) return null;
|
||||||
return error.TypeError;
|
return error.TypeError;
|
||||||
},
|
},
|
||||||
.bool => |b| {
|
.bool => |b| switch (Schema) {
|
||||||
if (Schema == .bool) return b;
|
.bool => return b,
|
||||||
return error.TypeError;
|
.@"union" => |unionInfo| inline for (unionInfo.fields) |field| {
|
||||||
|
var r: T = undefined;
|
||||||
|
r = @unionInit(T, field.name, b);
|
||||||
|
return r;
|
||||||
|
},
|
||||||
|
else => return error.TypeError,
|
||||||
},
|
},
|
||||||
.number => |number| switch (Schema) {
|
.number => |number| switch (Schema) {
|
||||||
.int, .comptime_int => return @intFromFloat(number),
|
.int, .comptime_int => return @intFromFloat(number),
|
||||||
.float, .comptime_float => return @floatCast(number),
|
.float, .comptime_float => return @floatCast(number),
|
||||||
|
.@"enum" => |enumInfo| {
|
||||||
|
const int: enumInfo.tag_type = @intFromFloat(number);
|
||||||
|
return @enumFromInt(int);
|
||||||
|
},
|
||||||
.@"struct" => |structInfo| switch (structInfo.layout) {
|
.@"struct" => |structInfo| switch (structInfo.layout) {
|
||||||
.@"packed" => {
|
.@"packed" => {
|
||||||
const my_int: structInfo.backing_integer.? =
|
const int: structInfo.backing_integer.? = @intFromFloat(number);
|
||||||
@intFromFloat(number);
|
return @bitCast(int);
|
||||||
return @bitCast(my_int);
|
|
||||||
},
|
},
|
||||||
else => return error.TypeError,
|
else => return error.TypeError,
|
||||||
},
|
},
|
||||||
|
.@"union" => |unionInfo| {
|
||||||
|
inline for (unionInfo.fields) |field| switch (@typeInfo(field.type)) {
|
||||||
|
.int, .comptime_int => return @unionInit(T, field.name, @intFromFloat(number)),
|
||||||
|
.float, .comptime_float => return @unionInit(T, field.name, @floatCast(number)),
|
||||||
|
else => {},
|
||||||
|
};
|
||||||
|
return error.TypeError;
|
||||||
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
},
|
},
|
||||||
.string => |string| switch (Schema) {
|
.string => |string| switch (Schema) {
|
||||||
|
.@"union" => |unionInfo| inline for (unionInfo.fields) |field| {
|
||||||
|
if (field.type == []const u8) {
|
||||||
|
var r: T = undefined;
|
||||||
|
const strslice = string.slice(&self.language.strings);
|
||||||
|
r = @unionInit(T, field.name, strslice);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
},
|
||||||
.array => |arrayInfo| {
|
.array => |arrayInfo| {
|
||||||
assert(arrayInfo.child == u8);
|
assert(arrayInfo.child == u8);
|
||||||
const strslice = string.slice(&self.language.strings);
|
const strslice = string.slice(&self.language.strings);
|
||||||
@ -141,7 +165,11 @@ pub fn reflectT(self: *Self, comptime T: type, allocator: mem.Allocator, idx: us
|
|||||||
if (map.get(field.name)) |next_i| {
|
if (map.get(field.name)) |next_i| {
|
||||||
@field(r, field.name) = try self.reflectT(field.type, allocator, next_i);
|
@field(r, field.name) = try self.reflectT(field.type, allocator, next_i);
|
||||||
} else switch (@typeInfo(field.type)) {
|
} else switch (@typeInfo(field.type)) {
|
||||||
.optional => @field(r, field.name) = null,
|
.optional => {
|
||||||
|
if (flags.bitfields)
|
||||||
|
@field(r, field.name) = null;
|
||||||
|
@panic("Unknown property: " ++ field.name);
|
||||||
|
},
|
||||||
else => @panic("Unknown property: " ++ field.name),
|
else => @panic("Unknown property: " ++ field.name),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -163,7 +191,9 @@ test reflectT {
|
|||||||
\\ "age": 15,
|
\\ "age": 15,
|
||||||
\\ "name": "Yuzu",
|
\\ "name": "Yuzu",
|
||||||
\\ "admin": true,
|
\\ "admin": true,
|
||||||
\\ "flags": 0
|
\\ "flags": 0,
|
||||||
|
\\ "union": ":D",
|
||||||
|
\\ "enum": 1
|
||||||
\\}
|
\\}
|
||||||
;
|
;
|
||||||
var self = try allocator.create(Self);
|
var self = try allocator.create(Self);
|
||||||
@ -184,9 +214,11 @@ test reflectT {
|
|||||||
name: []const u8,
|
name: []const u8,
|
||||||
admin: bool,
|
admin: bool,
|
||||||
flags: UserFlags,
|
flags: UserFlags,
|
||||||
|
@"union": union { hi: bool, bye: f64, n128: []const u8 },
|
||||||
|
@"enum": enum { hello, world },
|
||||||
};
|
};
|
||||||
|
|
||||||
const root = try self.reflectT(UserSchema, allocator, idx);
|
const root = try self.reflectT(UserSchema, allocator, idx);
|
||||||
|
|
||||||
std.debug.print("is cool? {} is friendly? {}\n", .{ root.flags.is_cool, root.flags.is_friendly });
|
std.debug.print("friend? {s}\n", .{root.@"union".n128});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user