repo: hackvr-turbo
action: commit
revision: 
path_from: 
revision_from: eea55bcd0406f877918f5907da94e034c15c2455:
path_to: 
revision_to: 
git.thebackupbox.net
hackvr-turbo
git clone git://git.thebackupbox.net/hackvr-turbo
commit eea55bcd0406f877918f5907da94e034c15c2455
Author: Felix (xq) Queißner 
Date:   Thu Jun 25 21:32:27 2020 +0200

    Completes parser.

diff --git a/lib/hackvr/parser.zig b/lib/hackvr/parser.zig
index 39c3d6b0f0dc354cfa85540aa11712a190ede8b6..
index ..d37eeb4d937373131d51f6244c421ee8f2bdcfd3 100644
--- a/lib/hackvr/parser.zig
+++ b/lib/hackvr/parser.zig
@@ -21,10 +21,11 @@ pub const Parser = struct {
         return Parser{
             .line_buffer = undefined,
             .line_offset = 0,
+            .point_buffer = undefined,
         };
     }

-    fn parseLine(line: []const u8) !?Event {
+    fn parseLine(self: *Parser, line: []const u8) !?Event {
         // max number of slices separated by a
         var items = FixedList([]const u8, 512).init();

@@ -133,8 +134,109 @@ pub const Parser = struct {
                             .groups = args[0],
                         },
                     };
-                }
+                } else if (std.mem.eql(u8, cmd, "addshape")) {
+                    if (args.len < 2)
+                        return error.ArgumentMismatch;
+                    const color = try std.fmt.parseInt(u8, args[0], 10);
+                    const argc = try std.fmt.parseInt(usize, args[1], 10);
+
+                    if (args.len != (2 + 3 * argc))
+                        return error.ArgumentMismatch;
+
+                    const slice = self.point_buffer[0..argc];
+
+                    for (slice) |*item, i| {
+                        const off = 2 + 3 * i;
+                        item.x = try std.fmt.parseFloat(hvr.real, args[off + 0]);
+                        item.y = try std.fmt.parseFloat(hvr.real, args[off + 1]);
+                        item.z = try std.fmt.parseFloat(hvr.real, args[off + 2]);
+                    }

+                    return Event{
+                        .add_shape = AddShapeData{
+                            .selector = selector,
+                            .color = color,
+                            .polygon = slice,
+                        },
+                    };
+                } else if (std.mem.eql(u8, cmd, "ping")) {
+                    if (args.len != 1)
+                        return error.ArgumentMismatch;
+                    return Event{
+                        .ping = PingData{
+                            .selector = selector,
+                            .ping_target = args[0],
+                        },
+                    };
+                } else if (std.mem.eql(u8, cmd, "scale")) {
+                    if (args.len != 3)
+                        return error.ArgumentMismatch;
+                    return Event{
+                        .scale = ScaleData{
+                            .selector = selector,
+                            .scale = hvr.Vec3D{
+                                .x = try std.fmt.parseFloat(hvr.real, args[0]),
+                                .y = try std.fmt.parseFloat(hvr.real, args[1]),
+                                .z = try std.fmt.parseFloat(hvr.real, args[2]),
+                            },
+                        },
+                    };
+                } else if (std.mem.eql(u8, cmd, "rotate")) {
+                    if (args.len != 3)
+                        return error.ArgumentMismatch;
+                    return Event{
+                        .rotate = AbsRelVectorData{
+                            .selector = selector,
+                            .vector = AbsRelVector{
+                                .x = try AbsRel.parse(args[0]),
+                                .y = try AbsRel.parse(args[1]),
+                                .z = try AbsRel.parse(args[2]),
+                            },
+                        },
+                    };
+                } else if (std.mem.eql(u8, cmd, "move")) {
+                    switch (args.len) {
+                        1 => {
+                            var dir = if (std.mem.eql(u8, args[0], "forward"))
+                                MoveData.Direction{ .forward = {} }
+                            else if (std.mem.eql(u8, args[0], "backward"))
+                                MoveData.Direction{ .backward = {} }
+                            else if (std.mem.eql(u8, args[0], "up"))
+                                MoveData.Direction{ .up = {} }
+                            else if (std.mem.eql(u8, args[0], "down"))
+                                MoveData.Direction{ .down = {} }
+                            else if (std.mem.eql(u8, args[0], "left"))
+                                MoveData.Direction{ .left = {} }
+                            else if (std.mem.eql(u8, args[0], "right"))
+                                MoveData.Direction{ .right = {} }
+                            else
+                                return error.InvalidArgument;
+
+                            return Event{
+                                .move = MoveData{
+                                    .selector = selector,
+                                    .direction = dir,
+                                },
+                            };
+                        },
+                        3 => {
+                            return Event{
+                                .move = MoveData{
+                                    .selector = selector,
+                                    .direction = .{
+                                        .offset = AbsRelVector{
+                                            .x = try AbsRel.parse(args[0]),
+                                            .y = try AbsRel.parse(args[1]),
+                                            .z = try AbsRel.parse(args[2]),
+                                        },
+                                    },
+                                },
+                            };
+                        },
+
+                        else => return error.ArgumentMismatch,
+                    }
+                }
                 return error.UnknownCommand;
             },
         }
@@ -161,7 +263,7 @@ pub const Parser = struct {
                 const rest = source[offset..];

                 if (line.len > 0) {
-                    const event = parseLine(line) catch |err| switch (err) {
+                    const event = self.parseLine(line) catch |err| switch (err) {
                         error.UnknownCommand => return PushResult{
                             .parse_error = .{
                                 .rest = rest,
@@ -228,30 +330,9 @@ pub const PushResult = union(enum) {
     },
 };

-pub const EventType = enum {
-    help,
-    version,
-    status,
-    dump,
-    quit,
-    set,
-    physics,
-    control,
-    addshape,
-    @"export",
-    ping,
-    scale,
-    rotate,
-    periodic,
-    flatten,
-    move,
-    delete_group,
-    assimilate,
-    rename_group,
-    delete_all_except,
-};
-
 pub const AbsRel = union(enum) {
+    const Self = @This();
+
     absolute: hvr.real,
     relative: hvr.real,

@@ -263,16 +344,34 @@ pub const AbsRel = union(enum) {
             };
         } else {
             return AbsRel{
-                .absolute = try std.fmt.parseFloat(hvr.real, str[1..]),
+                .absolute = try std.fmt.parseFloat(hvr.real, str),
             };
         }
     }
+
+    /// Applies the value to a previous value
+    pub fn apply(self: Self, in: hvr.real) hvr.real {
+        return switch (self) {
+            .relative => |v| in + v,
+            .absolute => |v| v,
+        };
+    }
 };

 pub const AbsRelVector = struct {
+    const Self = @This();
+
     x: AbsRel,
     y: AbsRel,
     z: AbsRel,
+
+    pub fn apply(self: Self, v3d: hvr.Vec3D) hvr.Vec3D {
+        return .{
+            .x = self.x.apply(v3d.x),
+            .y = self.x.apply(v3d.y),
+            .z = self.x.apply(v3d.z),
+        };
+    }
 };

 pub const Selector = struct {
@@ -301,8 +400,8 @@ pub const AbsRelVectorData = struct {
 };

 pub const MoveData = struct {
-    selector: Selector,
-    direction: union(enum) {
+    const Type = @TagType(Direction);
+    const Direction = union(enum) {
         forward,
         backward,
         left,
@@ -310,7 +409,10 @@ pub const MoveData = struct {
         up,
         down,
         offset: AbsRelVector,
-    },
+    };
+
+    selector: Selector,
+    direction: Direction,
 };

 pub const PingData = struct {
@@ -318,7 +420,8 @@ pub const PingData = struct {
     ping_target: []const u8,
 };

-pub const Event = union(EventType) {
+pub const EventType = @TagType(Event);
+pub const Event = union(enum) {
     delete_group: GroupArgSelector,
     assimilate: GroupArgSelector,
     rename_group: GroupArgSelector,
@@ -331,7 +434,7 @@ pub const Event = union(EventType) {
     set: Selector,
     physics: Selector,
     control: GroupArgSelector,
-    addshape: AddShapeData,
+    add_shape: AddShapeData,
     @"export": GroupArgSelector,
     ping: PingData,
     scale: ScaleData,
@@ -383,7 +486,7 @@ test "parser: ParseResult.rest/event" {
 }

 test "parser: parse line" {
-    _ = Parser.parseLine("  a bb cccc ") catch |err| {
+    _ = Parser.init().parseLine("  a bb cccc ") catch |err| {
         std.testing.expect(err == error.UnknownCommand);
         return;
     };
@@ -391,59 +494,59 @@ test "parser: parse line" {
 }

 test "parser: cmd help" {
-    const result = (try Parser.parseLine("help")) orelse return error.ExpectedEvent;
+    const result = (try Parser.init().parseLine("help")) orelse return error.ExpectedEvent;
     std.testing.expect(result == .help);
 }

 test "parser: cmd version" {
-    const result = (try Parser.parseLine("version")) orelse return error.ExpectedEvent;
+    const result = (try Parser.init().parseLine("version")) orelse return error.ExpectedEvent;
     std.testing.expect(result == .version);
 }

 test "parser: cmd status" {
-    const result = (try Parser.parseLine("foobar status")) orelse return error.ExpectedEvent;
+    const result = (try Parser.init().parseLine("foobar status")) orelse return error.ExpectedEvent;
     std.testing.expect(result == .status);
     std.testing.expectEqualStrings("foobar", result.status.groups);
 }

 test "parser: cmd dump" {
-    const result = (try Parser.parseLine("foobar dump")) orelse return error.ExpectedEvent;
+    const result = (try Parser.init().parseLine("foobar dump")) orelse return error.ExpectedEvent;
     std.testing.expect(result == .dump);
     std.testing.expectEqualStrings("foobar", result.dump.groups);
 }

 test "parser: cmd quit" {
-    const result = (try Parser.parseLine("foobar quit")) orelse return error.ExpectedEvent;
+    const result = (try Parser.init().parseLine("foobar quit")) orelse return error.ExpectedEvent;
     std.testing.expect(result == .quit);
     std.testing.expectEqualStrings("foobar", result.quit.groups);
 }

 test "parser: cmd set" {
-    const result = (try Parser.parseLine("foobar set")) orelse return error.ExpectedEvent;
+    const result = (try Parser.init().parseLine("foobar set")) orelse return error.ExpectedEvent;
     std.testing.expect(result == .set);
     std.testing.expectEqualStrings("foobar", result.set.groups);
 }

 test "parser: cmd physics" {
-    const result = (try Parser.parseLine("foobar physics")) orelse return error.ExpectedEvent;
+    const result = (try Parser.init().parseLine("foobar physics")) orelse return error.ExpectedEvent;
     std.testing.expect(result == .physics);
     std.testing.expectEqualStrings("foobar", result.physics.groups);
 }

 test "parser: cmd periodic" {
-    const result = (try Parser.parseLine("foobar periodic")) orelse return error.ExpectedEvent;
+    const result = (try Parser.init().parseLine("foobar periodic")) orelse return error.ExpectedEvent;
     std.testing.expect(result == .periodic);
     std.testing.expectEqualStrings("foobar", result.periodic.groups);
 }

 test "parser: cmd flatten" {
-    const result = (try Parser.parseLine("foobar flatten")) orelse return error.ExpectedEvent;
+    const result = (try Parser.init().parseLine("foobar flatten")) orelse return error.ExpectedEvent;
     std.testing.expect(result == .flatten);
     std.testing.expectEqualStrings("foobar", result.flatten.groups);
 }

 test "parser: cmd deleteallexcept" {
-    const result = (try Parser.parseLine("foobar deleteallexcept groupsel")) orelse return error.ExpectedEvent;
+    const result = (try Parser.init().parseLine("foobar deleteallexcept groupsel")) orelse return error.ExpectedEvent;

     std.testing.expect(result == .delete_all_except);
     std.testing.expectEqualStrings("foobar", result.delete_all_except.selector.groups);
@@ -451,7 +554,7 @@ test "parser: cmd deleteallexcept" {
 }

 test "parser: cmd delete_group" {
-    const result = (try Parser.parseLine("foobar deletegroup groupsel")) orelse return error.ExpectedEvent;
+    const result = (try Parser.init().parseLine("foobar deletegroup groupsel")) orelse return error.ExpectedEvent;

     std.testing.expect(result == .delete_group);
     std.testing.expectEqualStrings("foobar", result.delete_group.selector.groups);
@@ -459,7 +562,7 @@ test "parser: cmd delete_group" {
 }

 test "parser: cmd delete_group" {
-    const result = (try Parser.parseLine("foobar renamegroup groupsel")) orelse return error.ExpectedEvent;
+    const result = (try Parser.init().parseLine("foobar renamegroup groupsel")) orelse return error.ExpectedEvent;

     std.testing.expect(result == .rename_group);
     std.testing.expectEqualStrings("foobar", result.rename_group.selector.groups);
@@ -467,7 +570,7 @@ test "parser: cmd delete_group" {
 }

 test "parser: cmd delete_group" {
-    const result = (try Parser.parseLine("foobar assimilate groupsel")) orelse return error.ExpectedEvent;
+    const result = (try Parser.init().parseLine("foobar assimilate groupsel")) orelse return error.ExpectedEvent;

     std.testing.expect(result == .assimilate);
     std.testing.expectEqualStrings("foobar", result.assimilate.selector.groups);
@@ -475,7 +578,7 @@ test "parser: cmd delete_group" {
 }

 test "parser: cmd control" {
-    const result = (try Parser.parseLine("foobar control groupsel")) orelse return error.ExpectedEvent;
+    const result = (try Parser.init().parseLine("foobar control groupsel")) orelse return error.ExpectedEvent;

     std.testing.expect(result == .control);
     std.testing.expectEqualStrings("foobar", result.control.selector.groups);
@@ -483,9 +586,150 @@ test "parser: cmd control" {
 }

 test "parser: cmd export" {
-    const result = (try Parser.parseLine("foobar export groupsel")) orelse return error.ExpectedEvent;
+    const result = (try Parser.init().parseLine("foobar export groupsel")) orelse return error.ExpectedEvent;

     std.testing.expect(result == .@"export");
     std.testing.expectEqualStrings("foobar", result.@"export".selector.groups);
     std.testing.expectEqualStrings("groupsel", result.@"export".groups);
 }
+
+test "parser: cmd addshape" {
+    var parser = Parser.init();
+
+    {
+        const result = (try parser.parseLine("foobar addshape 3 0")) orelse return error.ExpectedEvent;
+
+        std.testing.expect(result == .add_shape);
+        std.testing.expectEqualStrings("foobar", result.add_shape.selector.groups);
+        std.testing.expectEqual(@as(u8, 3), result.add_shape.color);
+        std.testing.expectEqualSlices(
+            hvr.Vec3D,
+            &[_]hvr.Vec3D{},
+            result.add_shape.polygon,
+        );
+    }
+
+    {
+        const result = (try parser.parseLine("foobar addshape 3 1 1.5 2.5 3.5")) orelse return error.ExpectedEvent;
+
+        std.testing.expect(result == .add_shape);
+        std.testing.expectEqualStrings("foobar", result.add_shape.selector.groups);
+        std.testing.expectEqual(@as(u8, 3), result.add_shape.color);
+        std.testing.expectEqualSlices(
+            hvr.Vec3D,
+            &[_]hvr.Vec3D{
+                .{ .x = 1.5, .y = 2.5, .z = 3.5 },
+            },
+            result.add_shape.polygon,
+        );
+    }
+
+    {
+        const result = (try parser.parseLine("foobar addshape 3 2 1.5 2.5 3.5 7 8 132213.3")) orelse return error.ExpectedEvent;
+
+        std.testing.expect(result == .add_shape);
+        std.testing.expectEqualStrings("foobar", result.add_shape.selector.groups);
+        std.testing.expectEqual(@as(u8, 3), result.add_shape.color);
+        std.testing.expectEqualSlices(
+            hvr.Vec3D,
+            &[_]hvr.Vec3D{
+                .{ .x = 1.5, .y = 2.5, .z = 3.5 },
+                .{ .x = 7.0, .y = 8.0, .z = 132213.3 },
+            },
+            result.add_shape.polygon,
+        );
+    }
+}
+
+test "parser: cmd ping" {
+    const result = (try Parser.init().parseLine("foobar ping long.text.without.spaces")) orelse return error.ExpectedEvent;
+
+    std.testing.expect(result == .ping);
+    std.testing.expectEqualStrings("foobar", result.ping.selector.groups);
+    std.testing.expectEqualStrings("long.text.without.spaces", result.ping.ping_target);
+}
+
+test "parser: cmd scale" {
+    const result = (try Parser.init().parseLine("foobar scale 1.4 -2.3 1.8")) orelse return error.ExpectedEvent;
+
+    std.testing.expect(result == .scale);
+    std.testing.expectEqualStrings("foobar", result.scale.selector.groups);
+    std.testing.expectEqual(hvr.Vec3D{ .x = 1.4, .y = -2.3, .z = 1.8 }, result.scale.scale);
+}
+
+test "parser: cmd rotate" {
+    const result = (try Parser.init().parseLine("foobar rotate +1.4 -2.25 +-1.8")) orelse return error.ExpectedEvent;
+
+    std.testing.expect(result == .rotate);
+    std.testing.expectEqualStrings("foobar", result.rotate.selector.groups);
+    std.testing.expectEqual(AbsRelVector{
+        .x = AbsRel{ .relative = 1.4 },
+        .y = AbsRel{ .absolute = -2.25 },
+        .z = AbsRel{ .relative = -1.8 },
+    }, result.rotate.vector);
+}
+
+test "parser: cmd move" {
+    var parser = Parser.init();
+
+    {
+        const result = (try parser.parseLine("foobar move +1.4 -2.3 +-1.8")) orelse return error.ExpectedEvent;
+
+        std.testing.expect(result == .move);
+        std.testing.expectEqualStrings("foobar", result.move.selector.groups);
+        std.testing.expectEqual(MoveData.Type.offset, result.move.direction);
+        std.testing.expectEqual(AbsRelVector{
+            .x = AbsRel{ .relative = 1.4 },
+            .y = AbsRel{ .absolute = -2.3 },
+            .z = AbsRel{ .relative = -1.8 },
+        }, result.move.direction.offset);
+    }
+
+    {
+        const result = (try parser.parseLine("foobar move forward")) orelse return error.ExpectedEvent;
+
+        std.testing.expect(result == .move);
+        std.testing.expectEqualStrings("foobar", result.move.selector.groups);
+        std.testing.expectEqual(MoveData.Type.forward, result.move.direction);
+    }
+
+    {
+        const result = (try parser.parseLine("foobar move backward")) orelse return error.ExpectedEvent;
+
+        std.testing.expect(result == .move);
+        std.testing.expectEqualStrings("foobar", result.move.selector.groups);
+        std.testing.expectEqual(MoveData.Type.backward, result.move.direction);
+    }
+
+    {
+        const result = (try parser.parseLine("foobar move right")) orelse return error.ExpectedEvent;
+
+        std.testing.expect(result == .move);
+        std.testing.expectEqualStrings("foobar", result.move.selector.groups);
+        std.testing.expectEqual(MoveData.Type.right, result.move.direction);
+    }
+
+    {
+        const result = (try parser.parseLine("foobar move left")) orelse return error.ExpectedEvent;
+
+        std.testing.expect(result == .move);
+        std.testing.expectEqualStrings("foobar", result.move.selector.groups);
+        std.testing.expectEqual(MoveData.Type.left, result.move.direction);
+    }
+
+    {
+        const result = (try parser.parseLine("foobar move up")) orelse return error.ExpectedEvent;
+
+        std.testing.expect(result == .move);
+        std.testing.expectEqualStrings("foobar", result.move.selector.groups);
+        std.testing.expectEqual(MoveData.Type.up, result.move.direction);
+    }
+
+    {
+        const result = (try parser.parseLine("foobar move down")) orelse return error.ExpectedEvent;
+
+        std.testing.expect(result == .move);
+        std.testing.expectEqualStrings("foobar", result.move.selector.groups);
+        std.testing.expectEqual(MoveData.Type.down, result.move.direction);
+    }
+}

-----END OF PAGE-----