MIRROR: javascript for 馃悳's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 336 lines 11 kB view raw
1const std = @import("std"); 2 3pub const yyjson = @cImport({ 4 @cInclude("yyjson.h"); 5}); 6 7pub const JsonError = error{ 8 ParseError, 9 OutOfMemory, 10 InvalidType, 11 KeyNotFound, 12 IoError, 13}; 14 15pub const JsonDoc = struct { 16 doc: *yyjson.yyjson_doc, 17 18 pub fn parse(data: []const u8) !JsonDoc { 19 const doc = yyjson.yyjson_read(data.ptr, data.len, 0); 20 if (doc == null) return error.ParseError; 21 return JsonDoc{ .doc = doc.? }; 22 } 23 24 pub fn parseFile(path: [:0]const u8) !JsonDoc { 25 const doc = yyjson.yyjson_read_file(path.ptr, 0, null, null); 26 if (doc == null) return error.ParseError; 27 return JsonDoc{ .doc = doc.? }; 28 } 29 30 pub fn deinit(self: *JsonDoc) void { 31 yyjson.yyjson_doc_free(self.doc); 32 } 33 34 pub fn root(self: *JsonDoc) JsonValue { 35 return JsonValue{ .val = yyjson.yyjson_doc_get_root(self.doc).? }; 36 } 37}; 38 39pub const JsonValue = struct { 40 val: *yyjson.yyjson_val, 41 42 pub fn getString(self: JsonValue, key: [:0]const u8) ?[]const u8 { 43 const obj = yyjson.yyjson_obj_get(self.val, key.ptr) orelse return null; 44 if (!yyjson.yyjson_is_str(obj)) return null; 45 const ptr = yyjson.yyjson_get_str(obj) orelse return null; 46 const len = yyjson.yyjson_get_len(obj); 47 return ptr[0..len]; 48 } 49 50 pub fn getInt(self: JsonValue, key: [:0]const u8) ?i64 { 51 const obj = yyjson.yyjson_obj_get(self.val, key.ptr) orelse return null; 52 if (!yyjson.yyjson_is_int(obj)) return null; 53 return yyjson.yyjson_get_sint(obj); 54 } 55 56 pub fn getUint(self: JsonValue, key: [:0]const u8) ?u64 { 57 const obj = yyjson.yyjson_obj_get(self.val, key.ptr) orelse return null; 58 if (!yyjson.yyjson_is_uint(obj)) return null; 59 return yyjson.yyjson_get_uint(obj); 60 } 61 62 pub fn getDouble(self: JsonValue, key: [:0]const u8) ?f64 { 63 const obj = yyjson.yyjson_obj_get(self.val, key.ptr) orelse return null; 64 if (!yyjson.yyjson_is_real(obj)) return null; 65 return yyjson.yyjson_get_real(obj); 66 } 67 68 pub fn getBool(self: JsonValue, key: [:0]const u8) ?bool { 69 const obj = yyjson.yyjson_obj_get(self.val, key.ptr) orelse return null; 70 if (!yyjson.yyjson_is_bool(obj)) return null; 71 return yyjson.yyjson_get_bool(obj); 72 } 73 74 pub fn getObject(self: JsonValue, key: [:0]const u8) ?JsonValue { 75 const obj = yyjson.yyjson_obj_get(self.val, key.ptr) orelse return null; 76 if (!yyjson.yyjson_is_obj(obj)) return null; 77 return JsonValue{ .val = obj }; 78 } 79 80 pub fn getArray(self: JsonValue, key: [:0]const u8) ?JsonValue { 81 const obj = yyjson.yyjson_obj_get(self.val, key.ptr) orelse return null; 82 if (!yyjson.yyjson_is_arr(obj)) return null; 83 return JsonValue{ .val = obj }; 84 } 85 86 pub fn isNull(self: JsonValue) bool { 87 return yyjson.yyjson_is_null(self.val); 88 } 89 90 pub fn isArray(self: JsonValue) bool { 91 return yyjson.yyjson_is_arr(self.val); 92 } 93 94 pub fn isObject(self: JsonValue) bool { 95 return yyjson.yyjson_is_obj(self.val); 96 } 97 98 pub fn arrayLen(self: JsonValue) usize { 99 return yyjson.yyjson_arr_size(self.val); 100 } 101 102 pub fn arrayGet(self: JsonValue, index: usize) ?JsonValue { 103 const elem = yyjson.yyjson_arr_get(self.val, index) orelse return null; 104 return JsonValue{ .val = elem }; 105 } 106 107 pub fn asString(self: JsonValue) ?[]const u8 { 108 if (!yyjson.yyjson_is_str(self.val)) return null; 109 const ptr = yyjson.yyjson_get_str(self.val) orelse return null; 110 const len = yyjson.yyjson_get_len(self.val); 111 return ptr[0..len]; 112 } 113 114 pub const ObjectIterator = struct { 115 iter: yyjson.yyjson_obj_iter, 116 117 pub fn next(self: *ObjectIterator) ?struct { key: []const u8, value: JsonValue } { 118 const key_val = yyjson.yyjson_obj_iter_next(&self.iter) orelse return null; 119 const val = yyjson.yyjson_obj_iter_get_val(key_val) orelse return null; 120 121 const key_ptr = yyjson.yyjson_get_str(key_val) orelse return null; 122 const key_len = yyjson.yyjson_get_len(key_val); 123 124 return .{ 125 .key = key_ptr[0..key_len], 126 .value = JsonValue{ .val = val }, 127 }; 128 } 129 130 pub fn deinit(_: *ObjectIterator) void {} 131 }; 132 133 pub fn objectIterator(self: JsonValue) ?ObjectIterator { 134 if (!yyjson.yyjson_is_obj(self.val)) return null; 135 var iter: yyjson.yyjson_obj_iter = undefined; 136 if (!yyjson.yyjson_obj_iter_init(self.val, &iter)) return null; 137 return ObjectIterator{ .iter = iter }; 138 } 139 140 pub const ArrayIterator = struct { 141 iter: yyjson.yyjson_arr_iter, 142 143 pub fn next(self: *ArrayIterator) ?JsonValue { 144 const val = yyjson.yyjson_arr_iter_next(&self.iter) orelse return null; 145 return JsonValue{ .val = val }; 146 } 147 148 pub fn deinit(_: *ArrayIterator) void {} 149 }; 150 151 pub fn arrayIterator(self: JsonValue) ?ArrayIterator { 152 if (!yyjson.yyjson_is_arr(self.val)) return null; 153 var iter: yyjson.yyjson_arr_iter = undefined; 154 if (!yyjson.yyjson_arr_iter_init(self.val, &iter)) return null; 155 return ArrayIterator{ .iter = iter }; 156 } 157}; 158 159pub const JsonWriter = struct { 160 doc: *yyjson.yyjson_mut_doc, 161 162 pub fn init() !JsonWriter { 163 const doc = yyjson.yyjson_mut_doc_new(null); 164 if (doc == null) return error.OutOfMemory; 165 return JsonWriter{ .doc = doc.? }; 166 } 167 168 pub fn deinit(self: *JsonWriter) void { 169 yyjson.yyjson_mut_doc_free(self.doc); 170 } 171 172 pub fn createObject(self: *JsonWriter) *yyjson.yyjson_mut_val { 173 return yyjson.yyjson_mut_obj(self.doc).?; 174 } 175 176 pub fn createArray(self: *JsonWriter) *yyjson.yyjson_mut_val { 177 return yyjson.yyjson_mut_arr(self.doc).?; 178 } 179 180 pub fn createString(self: *JsonWriter, str: []const u8) *yyjson.yyjson_mut_val { 181 return yyjson.yyjson_mut_strncpy(self.doc, str.ptr, str.len).?; 182 } 183 184 pub fn createInt(self: *JsonWriter, val: i64) *yyjson.yyjson_mut_val { 185 return yyjson.yyjson_mut_sint(self.doc, val).?; 186 } 187 188 pub fn createUint(self: *JsonWriter, val: u64) *yyjson.yyjson_mut_val { 189 return yyjson.yyjson_mut_uint(self.doc, val).?; 190 } 191 192 pub fn createBool(self: *JsonWriter, val: bool) *yyjson.yyjson_mut_val { 193 return yyjson.yyjson_mut_bool(self.doc, val).?; 194 } 195 196 pub fn createReal(self: *JsonWriter, val: f64) *yyjson.yyjson_mut_val { 197 return yyjson.yyjson_mut_real(self.doc, val).?; 198 } 199 200 pub fn createNull(self: *JsonWriter) *yyjson.yyjson_mut_val { 201 return yyjson.yyjson_mut_null(self.doc).?; 202 } 203 204 pub fn objectAdd(self: *JsonWriter, obj: *yyjson.yyjson_mut_val, key: []const u8, val: *yyjson.yyjson_mut_val) void { 205 const key_val = yyjson.yyjson_mut_strncpy(self.doc, key.ptr, key.len); 206 _ = yyjson.yyjson_mut_obj_add(obj, key_val, val); 207 } 208 209 pub fn arrayAppend(_: *JsonWriter, arr: *yyjson.yyjson_mut_val, val: *yyjson.yyjson_mut_val) void { 210 _ = yyjson.yyjson_mut_arr_append(arr, val); 211 } 212 213 pub fn setRoot(self: *JsonWriter, val: *yyjson.yyjson_mut_val) void { 214 yyjson.yyjson_mut_doc_set_root(self.doc, val); 215 } 216 217 pub fn write(self: *JsonWriter, allocator: std.mem.Allocator) ![]u8 { 218 var len: usize = 0; 219 const ptr = yyjson.yyjson_mut_write(self.doc, yyjson.YYJSON_WRITE_PRETTY_TWO_SPACES, &len); 220 if (ptr == null) return error.OutOfMemory; 221 defer std.c.free(ptr); 222 223 const result = try allocator.alloc(u8, len); 224 @memcpy(result, ptr[0..len]); 225 return result; 226 } 227 228 pub fn writeToFile(self: *JsonWriter, path: [:0]const u8) !void { 229 const success = yyjson.yyjson_mut_write_file(path.ptr, self.doc, yyjson.YYJSON_WRITE_PRETTY_TWO_SPACES, null, null); 230 if (!success) return error.IoError; 231 } 232}; 233 234pub const PackageJson = struct { 235 name: []const u8, 236 version: []const u8, 237 dependencies: std.StringHashMap([]const u8), 238 dev_dependencies: std.StringHashMap([]const u8), 239 peer_dependencies: std.StringHashMap([]const u8), 240 optional_dependencies: std.StringHashMap([]const u8), 241 trusted_dependencies: std.StringHashMap(void), 242 243 pub fn parse(allocator: std.mem.Allocator, path: [:0]const u8) !PackageJson { 244 var doc = try JsonDoc.parseFile(path); 245 defer doc.deinit(); 246 247 const root_val = doc.root(); 248 249 var pkg = PackageJson{ 250 .name = "", 251 .version = "", 252 .dependencies = std.StringHashMap([]const u8).init(allocator), 253 .dev_dependencies = std.StringHashMap([]const u8).init(allocator), 254 .peer_dependencies = std.StringHashMap([]const u8).init(allocator), 255 .optional_dependencies = std.StringHashMap([]const u8).init(allocator), 256 .trusted_dependencies = std.StringHashMap(void).init(allocator), 257 }; 258 259 if (root_val.getString("name")) |s| { 260 pkg.name = try allocator.dupe(u8, s); 261 } 262 263 if (root_val.getString("version")) |s| { 264 pkg.version = try allocator.dupe(u8, s); 265 } 266 267 try parseDeps(allocator, root_val, "dependencies", &pkg.dependencies); 268 try parseDeps(allocator, root_val, "devDependencies", &pkg.dev_dependencies); 269 try parseDeps(allocator, root_val, "peerDependencies", &pkg.peer_dependencies); 270 try parseDeps(allocator, root_val, "optionalDependencies", &pkg.optional_dependencies); 271 272 if (root_val.getArray("trustedDependencies")) |arr| { 273 for (0..arr.arrayLen()) |i| { 274 const name = (arr.arrayGet(i) orelse continue).asString() orelse continue; 275 try pkg.trusted_dependencies.put(try allocator.dupe(u8, name), {}); 276 } 277 } 278 279 return pkg; 280 } 281 282 fn parseDeps( 283 allocator: std.mem.Allocator, 284 root_val: JsonValue, 285 key: [:0]const u8, 286 map: *std.StringHashMap([]const u8), 287 ) !void { 288 if (root_val.getObject(key)) |deps| { 289 var iter = deps.objectIterator() orelse return; 290 defer iter.deinit(); 291 while (iter.next()) |entry| { 292 const version = entry.value.asString() orelse continue; 293 try map.put(try allocator.dupe(u8, entry.key), try allocator.dupe(u8, version)); 294 } 295 } 296 } 297 298 pub fn deinit(self: *PackageJson, allocator: std.mem.Allocator) void { 299 if (self.name.len > 0) allocator.free(self.name); 300 if (self.version.len > 0) allocator.free(self.version); 301 302 var iter = self.dependencies.iterator(); 303 while (iter.next()) |entry| { 304 allocator.free(entry.key_ptr.*); 305 allocator.free(entry.value_ptr.*); 306 } 307 self.dependencies.deinit(); 308 309 iter = self.dev_dependencies.iterator(); 310 while (iter.next()) |entry| { 311 allocator.free(entry.key_ptr.*); 312 allocator.free(entry.value_ptr.*); 313 } 314 self.dev_dependencies.deinit(); 315 316 iter = self.peer_dependencies.iterator(); 317 while (iter.next()) |entry| { 318 allocator.free(entry.key_ptr.*); 319 allocator.free(entry.value_ptr.*); 320 } 321 self.peer_dependencies.deinit(); 322 323 iter = self.optional_dependencies.iterator(); 324 while (iter.next()) |entry| { 325 allocator.free(entry.key_ptr.*); 326 allocator.free(entry.value_ptr.*); 327 } 328 self.optional_dependencies.deinit(); 329 330 var trusted_iter = self.trusted_dependencies.keyIterator(); 331 while (trusted_iter.next()) |key| { 332 allocator.free(key.*); 333 } 334 self.trusted_dependencies.deinit(); 335 } 336};