Lots of things, idk o_0
This commit is contained in:
parent
4f59f87fbf
commit
3e85bcde6c
|
@ -12,7 +12,6 @@ pub fn build(b: *std.build.Builder) void {
|
|||
const mode = b.standardReleaseOptions();
|
||||
|
||||
const exe = b.addExecutable("mgtzm", "src/main.zig");
|
||||
exe.use_stage1 = true; // for sqlite
|
||||
|
||||
// Add dependencies
|
||||
exe.linkSystemLibrary("json-c");
|
||||
|
|
|
@ -41,7 +41,7 @@ const SubtagIterator = struct {
|
|||
const opt_i = std.mem.indexOfScalarPos(u8, self.orig_tag, index, ':');
|
||||
|
||||
if (opt_i) |i| {
|
||||
defer self.index = i+1;
|
||||
defer self.index = i + 1;
|
||||
return self.orig_tag[0..i];
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,7 @@ pub fn persist(self: *Self, db: *Db, allocator: std.mem.Allocator) !void {
|
|||
var iter = SubtagIterator.init(tag);
|
||||
while (iter.next()) |subtag| {
|
||||
// allocate "tag:<tagname>"
|
||||
var tagkey = try std.mem.concat(allocator, u8, &[_][]const u8{"tag:", subtag});
|
||||
var tagkey = try std.mem.concat(allocator, u8, &[_][]const u8{ "tag:", subtag });
|
||||
defer allocator.free(tagkey);
|
||||
|
||||
// Append the tag to the total of tags if it doesn't exist
|
||||
|
@ -215,7 +215,7 @@ pub fn fromJson(jobj: json.Obj, allocator: std.mem.Allocator) !Self {
|
|||
};
|
||||
}
|
||||
|
||||
pub fn tagsFromJson(jobj: *json.Obj, allocator: std.mem.Allocator) ![]Tag {
|
||||
pub fn tagsFromJson(jobj: *const json.Obj, allocator: std.mem.Allocator) ![]Tag {
|
||||
// Reserve space for slice of tags
|
||||
const len = @intCast(usize, jobj.arrayLen());
|
||||
var tags = try allocator.alloc(Tag, len);
|
||||
|
|
36
src/json.zig
36
src/json.zig
|
@ -4,7 +4,7 @@ pub const c = @cImport({
|
|||
const std = @import("std");
|
||||
|
||||
const Type = enum(c.json_type) {
|
||||
@"null" = c.json_type_null,
|
||||
null = c.json_type_null,
|
||||
boolean = c.json_type_boolean,
|
||||
double = c.json_type_double,
|
||||
int = c.json_type_int,
|
||||
|
@ -36,8 +36,14 @@ pub const Obj = struct {
|
|||
pub fn newInt64(i: i64) Obj {
|
||||
return Obj{ .obj = c.json_object_new_int64(i).? };
|
||||
}
|
||||
pub fn newFromString(s: [*c]const u8) Obj {
|
||||
return Obj{ .obj = c.json_tokener_parse(s).? };
|
||||
pub fn newFromString(s: [*c]const u8) !Obj {
|
||||
const FromStringError = error{
|
||||
MalformedString,
|
||||
};
|
||||
|
||||
return Obj{
|
||||
.obj = c.json_tokener_parse(s) orelse return FromStringError.MalformedString,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Obj) void {
|
||||
|
@ -48,7 +54,7 @@ pub const Obj = struct {
|
|||
// ** General functions **
|
||||
/////////////////////////////////
|
||||
|
||||
const TypeError = error {
|
||||
const TypeError = error{
|
||||
TypeMismatch, // Tried to use a function on the wrong JSON format
|
||||
};
|
||||
|
||||
|
@ -58,7 +64,7 @@ pub const Obj = struct {
|
|||
}
|
||||
|
||||
// Not *const Obj because the json_object retains ownership of the string
|
||||
pub fn toString(self: *Obj) []const u8 {
|
||||
pub fn toString(self: *const Obj) []const u8 {
|
||||
// TODO: Allow passing of flags as an enum like the SDL2 binding
|
||||
return std.mem.sliceTo(c.json_object_to_json_string(self.obj), 0);
|
||||
}
|
||||
|
@ -68,7 +74,7 @@ pub const Obj = struct {
|
|||
/////////////////////////////////
|
||||
|
||||
// Not *const Obj because the json_object retains ownership of the string
|
||||
pub fn getString(self: *Obj) []const u8 {
|
||||
pub fn getString(self: *const Obj) []const u8 {
|
||||
// TODO: Check type to not allow other types
|
||||
return std.mem.sliceTo(c.json_object_get_string(self.obj), 0);
|
||||
}
|
||||
|
@ -94,17 +100,17 @@ pub const Obj = struct {
|
|||
// Everything went alright
|
||||
if (obj) |ret| {
|
||||
return Obj{ .obj = c.json_object_get(ret).? };
|
||||
} else if (obj == null and succ != 0){
|
||||
} else if (obj == null and succ != 0) {
|
||||
// The actual value is just null
|
||||
return Obj{ .obj = null };
|
||||
} else if (self.getType() != Type.object){
|
||||
} else if (self.getType() != Type.object) {
|
||||
return GetError.TypeMismatch;
|
||||
} else {
|
||||
return GetError.KeyNotFound;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn objectAdd(self: *Obj, key: [*c]const u8, value: ?*Obj) void {
|
||||
pub fn objectAdd(self: *Obj, key: [*c]const u8, value: ?*const Obj) void {
|
||||
// TODO: Check type and error return
|
||||
|
||||
// We need the json-c object or null, not the zig object
|
||||
|
@ -113,6 +119,10 @@ pub const Obj = struct {
|
|||
_ = c.json_object_object_add(self.obj, key, o);
|
||||
}
|
||||
|
||||
pub fn objectAddString(self: *Obj, key: [*c]const u8, value: [*c]const u8) void {
|
||||
_ = c.json_object_object_add(self.obj, key, newString(value).obj);
|
||||
}
|
||||
|
||||
pub fn objectLen(self: *const Obj) c_int {
|
||||
return c.json_object_object_length(self.obj);
|
||||
}
|
||||
|
@ -161,7 +171,7 @@ pub const Obj = struct {
|
|||
// ** Array functions **
|
||||
/////////////////////////////////
|
||||
|
||||
pub fn arrayAdd(self: *Obj, value: ?*Obj) void {
|
||||
pub fn arrayAdd(self: *Obj, value: ?*const Obj) void {
|
||||
// TODO: Check type and error return
|
||||
|
||||
// We need the json-c object or null, not the zig object
|
||||
|
@ -173,7 +183,7 @@ pub const Obj = struct {
|
|||
return c.json_object_array_length(self.obj);
|
||||
}
|
||||
|
||||
pub fn arrayGet(self: *Obj, idx: usize) ?Obj {
|
||||
pub fn arrayGet(self: *const Obj, idx: usize) ?Obj {
|
||||
// Sould the .? be there?
|
||||
if (c.json_object_array_get_idx(self.obj, idx)) |obj| {
|
||||
return Obj{ .obj = c.json_object_get(obj).? };
|
||||
|
@ -182,12 +192,12 @@ pub const Obj = struct {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn arrayGetIterator (self: *Obj) ArrayIterator {
|
||||
pub fn arrayGetIterator(self: *const Obj) ArrayIterator {
|
||||
return ArrayIterator{ .obj = self, .idx = 0 };
|
||||
}
|
||||
|
||||
pub const ArrayIterator = struct {
|
||||
obj: *Obj,
|
||||
obj: *const Obj,
|
||||
idx: usize = 0,
|
||||
|
||||
pub fn next(self: *ArrayIterator) ?Obj {
|
||||
|
|
90
src/main.zig
90
src/main.zig
|
@ -5,66 +5,64 @@ const Item = @import("Item.zig");
|
|||
const Tag = @import("Tag.zig");
|
||||
const json = @import("json.zig");
|
||||
const request = @import("request.zig");
|
||||
const util = @import("util.zig");
|
||||
|
||||
pub fn main() !void {
|
||||
|
||||
var db = Db.open("test.tkh", true, "");
|
||||
const sock_path = "/tmp/mgtzm.sock";
|
||||
|
||||
// ---------------------- ADD ---------------------------
|
||||
// Remove the socket file if it exists
|
||||
std.fs.deleteFileAbsolute(sock_path) catch |err| {
|
||||
switch (err) {
|
||||
// Do not error out if the file doesn't exist
|
||||
error.FileNotFound => {},
|
||||
else => unreachable,
|
||||
}
|
||||
};
|
||||
|
||||
const jsonText: [:0]const u8 =
|
||||
\\{ "add" : [
|
||||
\\ [
|
||||
\\ "task:uned:led",
|
||||
\\ "fur:dusk",
|
||||
\\ "made_with:krita",
|
||||
\\ "date:2022:10:01",
|
||||
\\ "alunya"
|
||||
\\ ],[
|
||||
\\ "fur:lara",
|
||||
\\ "made_with:krita",
|
||||
\\ "date:2022:04:08",
|
||||
\\ "cell-shading"
|
||||
\\ ],[
|
||||
\\ "made_with:ballpoint_pen",
|
||||
\\ "date:2022:11:04",
|
||||
\\ "practice",
|
||||
\\ "pose_practice"
|
||||
\\ ],[
|
||||
\\ "fur:lidiarock1",
|
||||
\\ "made_with:krita",
|
||||
\\ "date:2022:10:15",
|
||||
\\ "niko_(oneshot)"
|
||||
\\ ]
|
||||
\\] }
|
||||
;
|
||||
var server = std.net.StreamServer.init(.{});
|
||||
defer server.deinit();
|
||||
const addr = try std.net.Address.initUnix(sock_path);
|
||||
|
||||
var jobj = json.Obj.newFromString(jsonText);
|
||||
defer jobj.deinit();
|
||||
try server.listen(addr);
|
||||
|
||||
try request.process(&jobj, &db);
|
||||
while (true) {
|
||||
|
||||
std.debug.print("\n\n", .{});
|
||||
// Initialization
|
||||
// ----------------
|
||||
|
||||
// -------------------- DELETE --------------------------
|
||||
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||
defer arena.deinit();
|
||||
const allocator = arena.allocator();
|
||||
|
||||
const jsonDelete: [:0]const u8 =
|
||||
\\{ "delete" : [ "0000", "0003" ] }
|
||||
;
|
||||
const connection = try server.accept();
|
||||
defer connection.stream.close();
|
||||
|
||||
var jdelete = json.Obj.newFromString(jsonDelete);
|
||||
defer jdelete.deinit();
|
||||
// Receive and process message
|
||||
// ----------------
|
||||
|
||||
try request.process(&jdelete, &db);
|
||||
const read = connection.stream.reader();
|
||||
|
||||
// -------------------- QUERY ---------------------------
|
||||
var msg = util.readUntilDelimiterAllocZ(read, allocator, 0, 1024) catch |err| {
|
||||
std.debug.print("Failed to read from connection: {any}\n", .{err});
|
||||
continue;
|
||||
};
|
||||
defer allocator.free(msg);
|
||||
|
||||
const jsonQuery: [:0]const u8 =
|
||||
\\{ "query" : "" }
|
||||
;
|
||||
var jobj = json.Obj.newFromString(msg) catch {
|
||||
var errorObj = json.Obj.newObject();
|
||||
errorObj.objectAddString("error", "Invalid JSON request.");
|
||||
|
||||
var jquery = json.Obj.newFromString(jsonQuery);
|
||||
defer jquery.deinit();
|
||||
_ = connection.stream.write(errorObj.toString()) catch {};
|
||||
continue;
|
||||
};
|
||||
defer jobj.deinit();
|
||||
|
||||
try request.process(&jquery, &db);
|
||||
const answer = try request.process(&jobj, &db, allocator);
|
||||
defer allocator.free(answer);
|
||||
|
||||
// Reply
|
||||
// ----------------
|
||||
_ = try connection.stream.write(answer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,34 +6,38 @@ const Tag = @import("Tag.zig");
|
|||
const json = @import("json.zig");
|
||||
const util = @import("util.zig");
|
||||
|
||||
pub fn process(jobj: *json.Obj, db: *Db) !void {
|
||||
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||
defer arena.deinit();
|
||||
const allocator = arena.allocator();
|
||||
|
||||
pub fn process(jobj: *json.Obj, db: *Db, allocator: std.mem.Allocator) ![]const u8 {
|
||||
var jret = json.Obj.newObject();
|
||||
defer jret.deinit();
|
||||
|
||||
// Test the action to carry and pass the object
|
||||
if (jobj.objectGet("add") catch null) |*jaction| {
|
||||
// TODO: Change to { "type" : "<action>", "data" : <data> }
|
||||
// TODO: Automatize this, give a list of actions and autobuild the checks in comptime
|
||||
if (jobj.objectGet("add")) |*jaction| {
|
||||
var ret = try add(jaction, db, allocator);
|
||||
jret.objectAdd("added", &ret);
|
||||
}
|
||||
// TODO: Maybe change all of these to "affected"?
|
||||
jret.objectAddString("type", "added");
|
||||
jret.objectAdd("data", &ret);
|
||||
} else |_| {}
|
||||
|
||||
if (jobj.objectGet("query") catch null) |*jaction| {
|
||||
if (jobj.objectGet("query")) |*jaction| {
|
||||
var ret = try query(jaction, db, allocator);
|
||||
jret.objectAdd("queried", &ret);
|
||||
}
|
||||
jret.objectAddString("type", "queried");
|
||||
jret.objectAdd("data", &ret);
|
||||
} else |_| {}
|
||||
|
||||
if (jobj.objectGet("delete") catch null) |*jaction| {
|
||||
if (jobj.objectGet("delete")) |*jaction| {
|
||||
var ret = try delete(jaction, db, allocator);
|
||||
jret.objectAdd("deleted", &ret);
|
||||
}
|
||||
jret.objectAddString("type", "deleted");
|
||||
jret.objectAdd("data", &ret);
|
||||
} else |_| {}
|
||||
|
||||
std.debug.print("{s}\n", .{jret.toString()});
|
||||
const ret_str = std.mem.sliceTo(jret.toString(), 0);
|
||||
|
||||
return allocator.dupe(u8, ret_str);
|
||||
}
|
||||
|
||||
pub fn add(jobj: *json.Obj, db: *Db, allocator: std.mem.Allocator) !json.Obj {
|
||||
pub fn add(jobj: *const json.Obj, db: *Db, allocator: std.mem.Allocator) !json.Obj {
|
||||
// TODO: Maybe return error when no items in the array?
|
||||
|
||||
// Freed by the caller
|
||||
|
@ -57,7 +61,7 @@ pub fn add(jobj: *json.Obj, db: *Db, allocator: std.mem.Allocator) !json.Obj {
|
|||
return jret;
|
||||
}
|
||||
|
||||
pub fn query(jobj: *json.Obj, db: *Db, allocator: std.mem.Allocator) !json.Obj {
|
||||
pub fn query(jobj: *const json.Obj, db: *Db, allocator: std.mem.Allocator) !json.Obj {
|
||||
// TODO: Have into account limits so it is scalable
|
||||
// TODO: Do not fetch EVERY id at once, iterate where possible
|
||||
const query_str = jobj.getString();
|
||||
|
@ -100,7 +104,7 @@ pub fn query(jobj: *json.Obj, db: *Db, allocator: std.mem.Allocator) !json.Obj {
|
|||
return jret;
|
||||
}
|
||||
|
||||
pub fn delete(jobj: *json.Obj, db: *Db, allocator: std.mem.Allocator) !json.Obj {
|
||||
pub fn delete(jobj: *const json.Obj, db: *Db, allocator: std.mem.Allocator) !json.Obj {
|
||||
var jret = json.Obj.newArray();
|
||||
|
||||
// Go over each tag
|
||||
|
|
17
src/util.zig
17
src/util.zig
|
@ -1,12 +1,11 @@
|
|||
const std = @import("std");
|
||||
|
||||
|
||||
pub const IntersectionIterator = struct {
|
||||
ref: std.mem.TokenIterator(u8),
|
||||
rest: []const []const u8,
|
||||
|
||||
/// Returns the next occurrence or null. Returned value is owned by originally passed slice
|
||||
pub fn next(self: *IntersectionIterator) ?[]const u8{
|
||||
pub fn next(self: *IntersectionIterator) ?[]const u8 {
|
||||
// If this returns null, there's no more items to check. We're finished.
|
||||
const needle = self.ref.next() orelse return null;
|
||||
|
||||
|
@ -40,3 +39,17 @@ pub fn intersection(slices: []const []const u8) IntersectionIterator {
|
|||
.rest = slices[1..],
|
||||
};
|
||||
}
|
||||
|
||||
pub fn readUntilDelimiterAllocZ(
|
||||
reader: anytype, // TODO: Fix this and set the correct type, I got no clue rn
|
||||
allocator: std.mem.Allocator,
|
||||
delimiter: u8,
|
||||
max_size: usize,
|
||||
) ![:0]u8 {
|
||||
var array_list = std.ArrayList(u8).init(allocator);
|
||||
defer array_list.deinit();
|
||||
|
||||
try reader.readUntilDelimiterArrayList(&array_list, delimiter, max_size);
|
||||
|
||||
return array_list.toOwnedSliceSentinel(0);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue