Something went wrong. Try again.
javascript for 🐜's, a tiny runtime with big ambitions antjs.org
Something went wrong. Try again.
Zig
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336const std = @import("std");
pub const yyjson = @cImport({ @cInclude("yyjson.h");});
pub const JsonError = error{ ParseError, OutOfMemory, InvalidType, KeyNotFound, IoError,};
pub const JsonDoc = struct { doc: *yyjson.yyjson_doc,
pub fn parse(data: []const u8) !JsonDoc { const doc = yyjson.yyjson_read(data.ptr, data.len, 0); if (doc == null) return error.ParseError; return JsonDoc{ .doc = doc.? }; }
pub fn parseFile(path: [:0]const u8) !JsonDoc { const doc = yyjson.yyjson_read_file(path.ptr, 0, null, null); if (doc == null) return error.ParseError; return JsonDoc{ .doc = doc.? }; }
pub fn deinit(self: *JsonDoc) void { yyjson.yyjson_doc_free(self.doc); }
pub fn root(self: *JsonDoc) JsonValue { return JsonValue{ .val = yyjson.yyjson_doc_get_root(self.doc).? }; }};
pub const JsonValue = struct { val: *yyjson.yyjson_val,
pub fn getString(self: JsonValue, key: [:0]const u8) ?[]const u8 { const obj = yyjson.yyjson_obj_get(self.val, key.ptr) orelse return null; if (!yyjson.yyjson_is_str(obj)) return null; const ptr = yyjson.yyjson_get_str(obj) orelse return null; const len = yyjson.yyjson_get_len(obj); return ptr[0..len]; }
pub fn getInt(self: JsonValue, key: [:0]const u8) ?i64 { const obj = yyjson.yyjson_obj_get(self.val, key.ptr) orelse return null; if (!yyjson.yyjson_is_int(obj)) return null; return yyjson.yyjson_get_sint(obj); }
pub fn getUint(self: JsonValue, key: [:0]const u8) ?u64 { const obj = yyjson.yyjson_obj_get(self.val, key.ptr) orelse return null; if (!yyjson.yyjson_is_uint(obj)) return null; return yyjson.yyjson_get_uint(obj); }
pub fn getDouble(self: JsonValue, key: [:0]const u8) ?f64 { const obj = yyjson.yyjson_obj_get(self.val, key.ptr) orelse return null; if (!yyjson.yyjson_is_real(obj)) return null; return yyjson.yyjson_get_real(obj); }
pub fn getBool(self: JsonValue, key: [:0]const u8) ?bool { const obj = yyjson.yyjson_obj_get(self.val, key.ptr) orelse return null; if (!yyjson.yyjson_is_bool(obj)) return null; return yyjson.yyjson_get_bool(obj); }
pub fn getObject(self: JsonValue, key: [:0]const u8) ?JsonValue { const obj = yyjson.yyjson_obj_get(self.val, key.ptr) orelse return null; if (!yyjson.yyjson_is_obj(obj)) return null; return JsonValue{ .val = obj }; }
pub fn getArray(self: JsonValue, key: [:0]const u8) ?JsonValue { const obj = yyjson.yyjson_obj_get(self.val, key.ptr) orelse return null; if (!yyjson.yyjson_is_arr(obj)) return null; return JsonValue{ .val = obj }; }
pub fn isNull(self: JsonValue) bool { return yyjson.yyjson_is_null(self.val); }
pub fn isArray(self: JsonValue) bool { return yyjson.yyjson_is_arr(self.val); }
pub fn isObject(self: JsonValue) bool { return yyjson.yyjson_is_obj(self.val); }
pub fn arrayLen(self: JsonValue) usize { return yyjson.yyjson_arr_size(self.val); }
pub fn arrayGet(self: JsonValue, index: usize) ?JsonValue { const elem = yyjson.yyjson_arr_get(self.val, index) orelse return null; return JsonValue{ .val = elem }; }
pub fn asString(self: JsonValue) ?[]const u8 { if (!yyjson.yyjson_is_str(self.val)) return null; const ptr = yyjson.yyjson_get_str(self.val) orelse return null; const len = yyjson.yyjson_get_len(self.val); return ptr[0..len]; }
pub const ObjectIterator = struct { iter: yyjson.yyjson_obj_iter,
pub fn next(self: *ObjectIterator) ?struct { key: []const u8, value: JsonValue } { const key_val = yyjson.yyjson_obj_iter_next(&self.iter) orelse return null; const val = yyjson.yyjson_obj_iter_get_val(key_val) orelse return null;
const key_ptr = yyjson.yyjson_get_str(key_val) orelse return null; const key_len = yyjson.yyjson_get_len(key_val);
return .{ .key = key_ptr[0..key_len], .value = JsonValue{ .val = val }, }; }
pub fn deinit(_: *ObjectIterator) void {} };
pub fn objectIterator(self: JsonValue) ?ObjectIterator { if (!yyjson.yyjson_is_obj(self.val)) return null; var iter: yyjson.yyjson_obj_iter = undefined; if (!yyjson.yyjson_obj_iter_init(self.val, &iter)) return null; return ObjectIterator{ .iter = iter }; }
pub const ArrayIterator = struct { iter: yyjson.yyjson_arr_iter,
pub fn next(self: *ArrayIterator) ?JsonValue { const val = yyjson.yyjson_arr_iter_next(&self.iter) orelse return null; return JsonValue{ .val = val }; }
pub fn deinit(_: *ArrayIterator) void {} };
pub fn arrayIterator(self: JsonValue) ?ArrayIterator { if (!yyjson.yyjson_is_arr(self.val)) return null; var iter: yyjson.yyjson_arr_iter = undefined; if (!yyjson.yyjson_arr_iter_init(self.val, &iter)) return null; return ArrayIterator{ .iter = iter }; }};
pub const JsonWriter = struct { doc: *yyjson.yyjson_mut_doc,
pub fn init() !JsonWriter { const doc = yyjson.yyjson_mut_doc_new(null); if (doc == null) return error.OutOfMemory; return JsonWriter{ .doc = doc.? }; }
pub fn deinit(self: *JsonWriter) void { yyjson.yyjson_mut_doc_free(self.doc); }
pub fn createObject(self: *JsonWriter) *yyjson.yyjson_mut_val { return yyjson.yyjson_mut_obj(self.doc).?; }
pub fn createArray(self: *JsonWriter) *yyjson.yyjson_mut_val { return yyjson.yyjson_mut_arr(self.doc).?; }
pub fn createString(self: *JsonWriter, str: []const u8) *yyjson.yyjson_mut_val { return yyjson.yyjson_mut_strncpy(self.doc, str.ptr, str.len).?; }
pub fn createInt(self: *JsonWriter, val: i64) *yyjson.yyjson_mut_val { return yyjson.yyjson_mut_sint(self.doc, val).?; }
pub fn createUint(self: *JsonWriter, val: u64) *yyjson.yyjson_mut_val { return yyjson.yyjson_mut_uint(self.doc, val).?; }
pub fn createBool(self: *JsonWriter, val: bool) *yyjson.yyjson_mut_val { return yyjson.yyjson_mut_bool(self.doc, val).?; }
pub fn createReal(self: *JsonWriter, val: f64) *yyjson.yyjson_mut_val { return yyjson.yyjson_mut_real(self.doc, val).?; }
pub fn createNull(self: *JsonWriter) *yyjson.yyjson_mut_val { return yyjson.yyjson_mut_null(self.doc).?; }
pub fn objectAdd(self: *JsonWriter, obj: *yyjson.yyjson_mut_val, key: []const u8, val: *yyjson.yyjson_mut_val) void { const key_val = yyjson.yyjson_mut_strncpy(self.doc, key.ptr, key.len); _ = yyjson.yyjson_mut_obj_add(obj, key_val, val); }
pub fn arrayAppend(_: *JsonWriter, arr: *yyjson.yyjson_mut_val, val: *yyjson.yyjson_mut_val) void { _ = yyjson.yyjson_mut_arr_append(arr, val); }
pub fn setRoot(self: *JsonWriter, val: *yyjson.yyjson_mut_val) void { yyjson.yyjson_mut_doc_set_root(self.doc, val); }
pub fn write(self: *JsonWriter, allocator: std.mem.Allocator) ![]u8 { var len: usize = 0; const ptr = yyjson.yyjson_mut_write(self.doc, yyjson.YYJSON_WRITE_PRETTY_TWO_SPACES, &len); if (ptr == null) return error.OutOfMemory; defer std.c.free(ptr);
const result = try allocator.alloc(u8, len); @memcpy(result, ptr[0..len]); return result; }
pub fn writeToFile(self: *JsonWriter, path: [:0]const u8) !void { const success = yyjson.yyjson_mut_write_file(path.ptr, self.doc, yyjson.YYJSON_WRITE_PRETTY_TWO_SPACES, null, null); if (!success) return error.IoError; }};
pub const PackageJson = struct { name: []const u8, version: []const u8, dependencies: std.StringHashMap([]const u8), dev_dependencies: std.StringHashMap([]const u8), peer_dependencies: std.StringHashMap([]const u8), optional_dependencies: std.StringHashMap([]const u8), trusted_dependencies: std.StringHashMap(void),
pub fn parse(allocator: std.mem.Allocator, path: [:0]const u8) !PackageJson { var doc = try JsonDoc.parseFile(path); defer doc.deinit();
const root_val = doc.root();
var pkg = PackageJson{ .name = "", .version = "", .dependencies = std.StringHashMap([]const u8).init(allocator), .dev_dependencies = std.StringHashMap([]const u8).init(allocator), .peer_dependencies = std.StringHashMap([]const u8).init(allocator), .optional_dependencies = std.StringHashMap([]const u8).init(allocator), .trusted_dependencies = std.StringHashMap(void).init(allocator), };
if (root_val.getString("name")) |s| { pkg.name = try allocator.dupe(u8, s); }
if (root_val.getString("version")) |s| { pkg.version = try allocator.dupe(u8, s); }
try parseDeps(allocator, root_val, "dependencies", &pkg.dependencies); try parseDeps(allocator, root_val, "devDependencies", &pkg.dev_dependencies); try parseDeps(allocator, root_val, "peerDependencies", &pkg.peer_dependencies); try parseDeps(allocator, root_val, "optionalDependencies", &pkg.optional_dependencies);
if (root_val.getArray("trustedDependencies")) |arr| { for (0..arr.arrayLen()) |i| { const name = (arr.arrayGet(i) orelse continue).asString() orelse continue; try pkg.trusted_dependencies.put(try allocator.dupe(u8, name), {}); } }
return pkg; }
fn parseDeps( allocator: std.mem.Allocator, root_val: JsonValue, key: [:0]const u8, map: *std.StringHashMap([]const u8), ) !void { if (root_val.getObject(key)) |deps| { var iter = deps.objectIterator() orelse return; defer iter.deinit(); while (iter.next()) |entry| { const version = entry.value.asString() orelse continue; try map.put(try allocator.dupe(u8, entry.key), try allocator.dupe(u8, version)); } } }
pub fn deinit(self: *PackageJson, allocator: std.mem.Allocator) void { if (self.name.len > 0) allocator.free(self.name); if (self.version.len > 0) allocator.free(self.version);
var iter = self.dependencies.iterator(); while (iter.next()) |entry| { allocator.free(entry.key_ptr.*); allocator.free(entry.value_ptr.*); } self.dependencies.deinit();
iter = self.dev_dependencies.iterator(); while (iter.next()) |entry| { allocator.free(entry.key_ptr.*); allocator.free(entry.value_ptr.*); } self.dev_dependencies.deinit();
iter = self.peer_dependencies.iterator(); while (iter.next()) |entry| { allocator.free(entry.key_ptr.*); allocator.free(entry.value_ptr.*); } self.peer_dependencies.deinit();
iter = self.optional_dependencies.iterator(); while (iter.next()) |entry| { allocator.free(entry.key_ptr.*); allocator.free(entry.value_ptr.*); } self.optional_dependencies.deinit();
var trusted_iter = self.trusted_dependencies.keyIterator(); while (trusted_iter.next()) |key| { allocator.free(key.*); } self.trusted_dependencies.deinit(); }};