diff --git a/src/client.zig b/src/client.zig index 4e56e9c..fc55720 100644 --- a/src/client.zig +++ b/src/client.zig @@ -47,7 +47,12 @@ pub const Client = struct { try map.put("ClientVersion", .{ .String = "0.1 (quasselclient)" }); try map.put("ClientDate", .{ .String = "Wed, 02 Jun 2021 17:30:30 +0100" }); try map.put("Features", .{ .Int = 0 }); - var empty = std.ArrayList([]const u8).init(s.allocator); + var featureList = std.ArrayList([]const u8).init(s.allocator); + defer featureList.deinit(); + try featureList.put("LongTime"); + try featureList.put("SenderPrefixes"); + try featureList.put("RichMessages"); + try map.put("FeatureList", .{ .QStringList = empty.items }); try write.writeFrame(list.writer(), s.allocator, map); diff --git a/src/main.zig b/src/main.zig index 26d90d0..981fda0 100644 --- a/src/main.zig +++ b/src/main.zig @@ -6,7 +6,7 @@ const write = @import("./qtshit/write.zig"); const initClient = @import("./client.zig").initClient; pub fn main() !void { - const allocator = &std.heap.loggingAllocator(std.heap.page_allocator, std.io.getStdErr().writer()).allocator; + const allocator = std.heap.page_allocator; var argIter = std.process.args(); _ = try argIter.next(allocator).?; diff --git a/src/qtshit/read/readByte.zig b/src/qtshit/read/readByte.zig index 0449a7e..26450af 100644 --- a/src/qtshit/read/readByte.zig +++ b/src/qtshit/read/readByte.zig @@ -1,5 +1,5 @@ const std = @import("std"); pub fn readByte(reader: anytype) !u8 { - std.debug.print("read: readByte\n", .{}); + //std.debug.print("read: readByte\n", .{}); return try reader.readByte(); } diff --git a/src/qtshit/read/readInt.zig b/src/qtshit/read/readInt.zig index 00eb601..dc00647 100644 --- a/src/qtshit/read/readInt.zig +++ b/src/qtshit/read/readInt.zig @@ -1,6 +1,6 @@ const std = @import("std"); pub fn readInt(reader: anytype) !i32 { - std.debug.print("read: readInt\n", .{}); + //std.debug.print("read: readInt\n", .{}); return try reader.readIntBig(i32); } diff --git a/src/qtshit/read/readLong.zig b/src/qtshit/read/readLong.zig index f61b66c..81b93e6 100644 --- a/src/qtshit/read/readLong.zig +++ b/src/qtshit/read/readLong.zig @@ -1,6 +1,6 @@ const std = @import("std"); pub fn readLong(reader: anytype) !i64 { - std.debug.print("read: readLong\n", .{}); + //std.debug.print("read: readLong\n", .{}); return try reader.readIntBig(i64); } diff --git a/src/qtshit/read/readQByteArray.zig b/src/qtshit/read/readQByteArray.zig index dc09ba8..1968162 100644 --- a/src/qtshit/read/readQByteArray.zig +++ b/src/qtshit/read/readQByteArray.zig @@ -3,12 +3,13 @@ const readUInt = @import("./readUInt.zig").readUInt; pub fn readQByteArray(reader: anytype, allocator: *std.mem.Allocator) ![]u8 { var length = try readUInt(reader); - std.debug.print("read: readQByteArray length={d} \n", .{length}); + //std.debug.print("read: readQByteArray length={d} \n", .{length}); var byteList = try allocator.alloc(u8, @intCast(usize, length)); var index: usize = 0; while (true) { + //std.debug.print("read: readQByteArray length={d} index={d} \n", .{length, index}); if (index == length) return byteList; const byte = try reader.readByte(); diff --git a/src/qtshit/read/readQDateTime.zig b/src/qtshit/read/readQDateTime.zig new file mode 100644 index 0000000..a6b4a2e --- /dev/null +++ b/src/qtshit/read/readQDateTime.zig @@ -0,0 +1,13 @@ +const std = @import("std"); +const readInt = @import("./readInt.zig").readInt; +const readByte = @import("./readByte.zig").readByte; +const QDateTime = @import("../types/QVariant.zig").QDateTime; + +pub fn readQDateTime(reader: anytype) !QDateTime { + //std.debug.print("read: readQDateTime\n", .{}); + return QDateTime{ + .JulianDay = try readInt(reader), + .MillisOfDay = try readInt(reader), + .Zone = try readByte(reader), + }; +} diff --git a/src/qtshit/read/readQStringList.zig b/src/qtshit/read/readQStringList.zig index e93e008..ff16575 100644 --- a/src/qtshit/read/readQStringList.zig +++ b/src/qtshit/read/readQStringList.zig @@ -6,7 +6,7 @@ const readString = @import("./readString.zig").readString; pub fn readQStringList(reader: anytype, allocator: *std.mem.Allocator) ![][]const u8 { var length = try readUInt(reader); - std.debug.print("read: readQStringList length={d} \n", .{length}); + //std.debug.print("read: readQStringList length={d} \n", .{length}); var stringList = try allocator.alloc([]const u8, @intCast(usize, length)); diff --git a/src/qtshit/read/readQVariant.zig b/src/qtshit/read/readQVariant.zig index 2997135..fca7604 100644 --- a/src/qtshit/read/readQVariant.zig +++ b/src/qtshit/read/readQVariant.zig @@ -7,8 +7,7 @@ const QVariant = @import("../types/QVariant.zig").QVariant; pub fn readQVariant(reader: anytype, allocator: *std.mem.Allocator) !QVariant { var type_id = try readUInt(reader); - std.debug.print("read: readQVariant type_id={d}\n", .{type_id}); - - _ = try readByte(reader); + var mysteryByte = try readByte(reader); + //std.debug.print("read: readQVariant type_id={d} mysteryByte={d} \n", .{type_id, mysteryByte}); return try readQVariantT(reader, type_id, allocator); } diff --git a/src/qtshit/read/readQVariantList.zig b/src/qtshit/read/readQVariantList.zig index a699791..57d6880 100644 --- a/src/qtshit/read/readQVariantList.zig +++ b/src/qtshit/read/readQVariantList.zig @@ -9,7 +9,7 @@ const QVariant = @import("../types/QVariant.zig").QVariant; pub fn readQVariantList(reader: anytype, allocator: *std.mem.Allocator) ![]QVariant { var length = try readUInt(reader); - std.debug.print("read: readQVariantList length={d}\n", .{length}); + //std.debug.print("read: readQVariantList length={d}\n", .{length}); var variantList = try allocator.alloc(QVariant, @intCast(usize, length)); diff --git a/src/qtshit/read/readQVariantMap.zig b/src/qtshit/read/readQVariantMap.zig index 6c1a998..70011fa 100644 --- a/src/qtshit/read/readQVariantMap.zig +++ b/src/qtshit/read/readQVariantMap.zig @@ -11,7 +11,7 @@ const QVariant = @import("../types/QVariant.zig").QVariant; pub fn readQVariantMap(reader: anytype, allocator: *std.mem.Allocator) !std.StringHashMap(QVariant) { var map = std.StringHashMap(QVariant).init(allocator); var numItems = try readUInt(reader); - std.debug.print("read: readQVariantMap length={d} \n", .{numItems}); + //std.debug.print("read: readQVariantMap length={d} \n", .{numItems}); var iter = range(u32, 0, numItems); diff --git a/src/qtshit/read/readQVariantT.zig b/src/qtshit/read/readQVariantT.zig index 83e2c0b..9250761 100644 --- a/src/qtshit/read/readQVariantT.zig +++ b/src/qtshit/read/readQVariantT.zig @@ -11,6 +11,7 @@ const readQVariantList = @import("./readQVariantList.zig").readQVariantList; const readQVariant = @import("./readQVariant.zig").readQVariant; const readQVariantMap = @import("./readQVariantMap.zig").readQVariantMap; const readQStringList = @import("./readQStringList.zig").readQStringList; +const readQDateTime = @import("./readQDateTime.zig").readQDateTime; const readUserType = @import("./usertypes/readUserType.zig").readUserType; const QVariant = @import("../types/QVariant.zig").QVariant; @@ -54,13 +55,19 @@ pub fn readQVariantT(reader: anytype, type_id: u32, allocator: *std.mem.Allocato var short = try readShort(reader); return QVariant{ .Short = short }; }, + @enumToInt(QVariantTypes.QDateTime) => { + var datetime = try readQDateTime(reader); + return QVariant{ .QDateTime = datetime }; + }, @enumToInt(QVariantTypes.UserType) => { var usertype = try readUserType(reader, allocator); return QVariant{ .UserType = usertype }; }, else => { std.debug.print("Unknown Type ID: {d}\n", .{type_id}); - @panic("Unknown Type See Above."); + return QVariant{ .String = "UnknownType" }; + + //@panic("Unknown Type See Above."); }, } return QVariant{ .empty = true }; diff --git a/src/qtshit/read/readShort.zig b/src/qtshit/read/readShort.zig index 535793f..b078b85 100644 --- a/src/qtshit/read/readShort.zig +++ b/src/qtshit/read/readShort.zig @@ -1,7 +1,6 @@ const std = @import("std"); pub fn readShort(reader: anytype) !u16 { - std.debug.print("read: readShort\n", .{}); - + //std.debug.print("read: readShort\n", .{}); return try reader.readIntBig(u16); } diff --git a/src/qtshit/read/readSignedByte.zig b/src/qtshit/read/readSignedByte.zig index 8bd188e..02e6faa 100644 --- a/src/qtshit/read/readSignedByte.zig +++ b/src/qtshit/read/readSignedByte.zig @@ -1,6 +1,6 @@ const std = @import("std"); pub fn readSignedByte(reader: anytype) !i8 { - std.debug.print("read: readSignedByte\n", .{}); + //std.debug.print("read: readSignedByte\n", .{}); return try reader.readIntBig(i8); } diff --git a/src/qtshit/read/readString.zig b/src/qtshit/read/readString.zig index ef39d07..c8137e0 100644 --- a/src/qtshit/read/readString.zig +++ b/src/qtshit/read/readString.zig @@ -8,13 +8,13 @@ pub fn readString(reader: anytype, allocator: *std.mem.Allocator) ![]u8 { var length = try readInt(reader); var chars = @divTrunc(length, 2); - std.debug.print("read: readString length={d} \n", .{length}); + //std.debug.print("read: readString length={d} \n", .{length}); var index: usize = 0; while (true) { if (index == chars) break; - const byte = try reader.readIntBig(u16); + const byte = try readShort(reader); try data.append(@truncate(u8, byte)); index += 1; } @@ -24,7 +24,7 @@ pub fn readString(reader: anytype, allocator: *std.mem.Allocator) ![]u8 { ut8Str[i] = char; } - std.debug.print("string: {s}\n", .{ut8Str}); + //std.debug.print("string: {s}\n", .{ut8Str}); return ut8Str; } diff --git a/src/qtshit/read/readUInt.zig b/src/qtshit/read/readUInt.zig index 108afbb..8327518 100644 --- a/src/qtshit/read/readUInt.zig +++ b/src/qtshit/read/readUInt.zig @@ -1,6 +1,6 @@ const std = @import("std"); pub fn readUInt(reader: anytype) !u32 { - std.debug.print("read: readUInt\n", .{}); + //std.debug.print("read: readUInt\n", .{}); return try reader.readIntBig(u32); } diff --git a/src/qtshit/read/usertypes/readUserType.zig b/src/qtshit/read/usertypes/readUserType.zig index 6b4473f..36e0dcc 100644 --- a/src/qtshit/read/usertypes/readUserType.zig +++ b/src/qtshit/read/usertypes/readUserType.zig @@ -3,6 +3,7 @@ const UserType = @import("../../types/UserType.zig").UserType; const UserTypeNames = @import("../../types/UserType.zig").UserTypeNames; const readInt = @import("../readInt.zig").readInt; const readShort = @import("../readShort.zig").readShort; +const readByte = @import("../readByte.zig").readByte; const readLong = @import("../readLong.zig").readLong; const readQByteArray = @import("../readQByteArray.zig").readQByteArray; const readQVariantMap = @import("../readQVariantMap.zig").readQVariantMap; @@ -10,7 +11,7 @@ const readQVariantMap = @import("../readQVariantMap.zig").readQVariantMap; pub fn readUserType(reader: anytype, allocator: *std.mem.Allocator) !UserType { var userTypeName = try readQByteArray(reader, allocator); userTypeName = userTypeName[0 .. userTypeName.len - 1]; - std.debug.print("read: readUserType name={s} \n", .{userTypeName}); + //std.debug.print("read: readUserType name={s} \n", .{userTypeName}); if (std.mem.eql(u8, userTypeName, "BufferId")) { return UserType{ @@ -53,12 +54,23 @@ pub fn readUserType(reader: anytype, allocator: *std.mem.Allocator) !UserType { .NetworkServer = try readQVariantMap(reader, allocator), }; } else if (std.mem.eql(u8, userTypeName, "BufferInfo")) { + + var id = try readInt(reader); + var networkid = try readInt(reader); + var btype = try readShort(reader); + // 4 undocumented bytes. + _ = try readByte(reader); + _ = try readByte(reader); + _ = try readByte(reader); + _ = try readByte(reader); + var name = try readQByteArray(reader, allocator); + return UserType{ .BufferInfo = .{ - .ID = try readInt(reader), - .NetworkID = try readInt(reader), - .Type = try readShort(reader), - .Name = try readQByteArray(reader, allocator), + .ID = id, + .NetworkID = networkid, + .Type = btype, + .Name = name, }, }; } else { diff --git a/src/qtshit/types/QVariant.zig b/src/qtshit/types/QVariant.zig index be43e3b..0aec4cf 100644 --- a/src/qtshit/types/QVariant.zig +++ b/src/qtshit/types/QVariant.zig @@ -11,5 +11,12 @@ pub const QVariant = union(enum) { QStringList: [][]const u8, QVariantList: []QVariant, QVariantMap: std.StringHashMap(QVariant), + QDateTime: QDateTime, UserType: UserType, +}; + +pub const QDateTime = struct { + JulianDay: i32, + MillisOfDay: i32, + Zone: u8, }; \ No newline at end of file diff --git a/src/qtshit/types/QVariantTypes.zig b/src/qtshit/types/QVariantTypes.zig index 16118b1..11d6c56 100644 --- a/src/qtshit/types/QVariantTypes.zig +++ b/src/qtshit/types/QVariantTypes.zig @@ -7,6 +7,7 @@ pub const QVariantTypes = enum(u32) { String = 10, QStringList = 11, QByteArray = 12, + QDateTime = 16, Short = 133, UserType = 127, }; diff --git a/src/qtshit/utils/QVariantTypeID.zig b/src/qtshit/utils/QVariantTypeID.zig index 2d38b58..e5dff1a 100644 --- a/src/qtshit/utils/QVariantTypeID.zig +++ b/src/qtshit/utils/QVariantTypeID.zig @@ -27,6 +27,9 @@ pub fn QVariantTypeID(variant: QVariant) !u32 { .QByteArray => { return @enumToInt(QVariantTypes.QByteArray); }, + .QDateTime => { + return @enumToInt(QVariantTypes.QDateTime); + }, .Short => { return @enumToInt(QVariantTypes.Short); }, diff --git a/src/qtshit/utils/freeQVariant.zig b/src/qtshit/utils/freeQVariant.zig index bfc0688..1d27b4b 100644 --- a/src/qtshit/utils/freeQVariant.zig +++ b/src/qtshit/utils/freeQVariant.zig @@ -1,21 +1,25 @@ const std = @import("std"); const QVariant = @import("../types/QVariant.zig").QVariant; +pub fn freeQVariantMap(qvariantmap: std.StringHashMap(QVariant), allocator: *std.mem.Allocator) void { + var qMapIter = qvariantmap.iterator(); + while (qMapIter.next()) |v| { + allocator.free(v.key); + freeQVariant(v.value, allocator); + } + // Compiler bug maybe? doesnt want me to drop const so have to store it in a variable + var qi = qvariantmap; + qi.deinit(); +} + pub fn freeQVariant(variant: QVariant, allocator: *std.mem.Allocator) void { switch (variant) { - .Byte, .Int, .UInt, .Short => { + .Byte, .Int, .UInt, .Short, .QDateTime => { // Static }, .QVariantMap => |q| { - var qMapIter = q.iterator(); - while (qMapIter.next()) |v| { - allocator.free(v.key); - freeQVariant(v.value, allocator); - } - // Compiler bug maybe? doesnt want me to drop const so have to store it in a variable - var qi = q; - qi.deinit(); + freeQVariantMap(q, allocator); }, .QVariantList => |l| { @@ -36,8 +40,18 @@ pub fn freeQVariant(variant: QVariant, allocator: *std.mem.Allocator) void { .QByteArray => |ba| { allocator.free(ba); }, - .UserType => { - @panic("Do Not Know How?????"); + .UserType => |usertype| { + switch (usertype) { + .BufferId, .IdentityId, .NetworkId, .MsgId, .PeerPtr => { + // Statid + }, + .IrcUser, .IrcChannel, .Identity, .NetworkInfo, .NetworkServer => |value| { + freeQVariantMap(value, allocator); + }, + .BufferInfo => |value| { + allocator.free(value.Name); + }, + } }, } } diff --git a/src/qtshit/utils/prettyPrintQVariant.zig b/src/qtshit/utils/prettyPrintQVariant.zig index b9f261a..86542fe 100644 --- a/src/qtshit/utils/prettyPrintQVariant.zig +++ b/src/qtshit/utils/prettyPrintQVariant.zig @@ -1,5 +1,7 @@ const std = @import("std"); const QVariant = @import("../types/QVariant.zig").QVariant; +const UserType = @import("../types/UserType.zig").UserType; + const range = @import("../utils/RangeIter.zig").range; pub fn print_indent_level(indentLevel: u64) void { @@ -9,6 +11,73 @@ pub fn print_indent_level(indentLevel: u64) void { } } +pub fn prettyPrintUserType(usertype: UserType, indentLevel: u64) void { + switch (usertype) { + .BufferId => |value| { + std.debug.print("BufferId: {d}\n", .{value}); + }, + .IdentityId => |value| { + std.debug.print("IdentityId: {d}\n", .{value}); + }, + .NetworkId => |value| { + std.debug.print("NetworkId: {d}\n", .{value}); + }, + .MsgId => |value| { + std.debug.print("MsgId: {d}\n", .{value}); + }, + .PeerPtr => |value| { + std.debug.print("PeerPtr: {d}\n", .{value}); + }, + .IrcUser => |value| { + std.debug.print("IrcUser:\n", .{}); + prettyPrintQVariantMap(value, indentLevel + 1); + }, + .IrcChannel => |value| { + std.debug.print("IrcChannel:\n", .{}); + prettyPrintQVariantMap(value, indentLevel + 1); + }, + .Identity => |value| { + std.debug.print("Identity:\n", .{}); + prettyPrintQVariantMap(value, indentLevel + 1); + }, + .NetworkInfo => |value| { + std.debug.print("NetworkInfo:\n", .{}); + prettyPrintQVariantMap(value, indentLevel + 1); + }, + .NetworkServer => |value| { + std.debug.print("NetworkServer:\n", .{}); + prettyPrintQVariantMap(value, indentLevel + 1); + }, + .BufferInfo => |value| { + std.debug.print("BufferInfo:\n", .{}); + print_indent_level(indentLevel + 1); + std.debug.print("ID: {d}\n", .{value.ID}); + print_indent_level(indentLevel + 1); + std.debug.print("NetworkID: {d}\n", .{value.NetworkID}); + print_indent_level(indentLevel + 1); + std.debug.print("Type: {d}\n", .{value.Type}); + print_indent_level(indentLevel + 1); + std.debug.print("Name: {s}\n", .{value.Name}); + }, + //else => { + // std.debug.print("Unknown.\n", .{}); + //}, + } +} + +pub fn prettyPrintQVariantMap(qvariantmap: std.StringHashMap(QVariant), indentLevel: u64) void { + print_indent_level(indentLevel); + std.debug.print("QVariantMap:\n", .{}); + var qMapIter = qvariantmap.iterator(); + while (qMapIter.next()) |v| { + print_indent_level(indentLevel + 1); + std.debug.print("Key: \"{s}\"\n", .{v.key}); + print_indent_level(indentLevel + 1); + std.debug.print("Value:\n", .{}); + prettyPrintQVariant(v.value, indentLevel + 2); + } +} + pub fn prettyPrintQVariant(variant: QVariant, indentLevel: u64) void { print_indent_level(indentLevel); @@ -23,19 +92,10 @@ pub fn prettyPrintQVariant(variant: QVariant, indentLevel: u64) void { std.debug.print("UInt: {d}\n", .{i}); }, .QVariantMap => |q| { - std.debug.print("QVariantMap:\n", .{}); - var qMapIter = q.iterator(); - while (qMapIter.next()) |v| { - print_indent_level(indentLevel + 1); - std.debug.print("Key: \"{s}\"\n", .{v.key}); - print_indent_level(indentLevel + 1); - std.debug.print("Value:\n", .{}); - prettyPrintQVariant(v.value, indentLevel + 2); - } + prettyPrintQVariantMap(q, indentLevel + 1); }, .QVariantList => |l| { std.debug.print("QVariantList:\n", .{}); - for (l) |varient, i| { print_indent_level(indentLevel + 1); std.debug.print("Item #{d}\n", .{i}); @@ -54,11 +114,20 @@ pub fn prettyPrintQVariant(variant: QVariant, indentLevel: u64) void { } }, .QByteArray => {}, + .QDateTime => |value| { + std.debug.print("QDateTime:\n", .{}); + print_indent_level(indentLevel + 1); + std.debug.print("JulianDay: {d}\n", .{value.JulianDay}); + print_indent_level(indentLevel + 1); + std.debug.print("MillisOfDay: {d}\n", .{value.MillisOfDay}); + print_indent_level(indentLevel + 1); + std.debug.print("Zone: {d}\n", .{value.Zone}); + }, .Short => |s| { std.debug.print("Short: \"{d}\"\n", .{s}); }, - .UserType => { - @panic("HOW PRINT?????"); + .UserType => |value| { + prettyPrintUserType(value, indentLevel + 1); }, } } diff --git a/src/qtshit/write/writeQVariant.zig b/src/qtshit/write/writeQVariant.zig index b949fc3..bca505f 100644 --- a/src/qtshit/write/writeQVariant.zig +++ b/src/qtshit/write/writeQVariant.zig @@ -44,6 +44,9 @@ pub fn writeQVariant(writer: anytype, allocator: *std.mem.Allocator, variant: QV .Short => |out| { try writeShort(writer, out); }, + .QDateTime => { + @panic("Can't write QDateTime"); + }, .UserType => { @panic("Can't write UserTypes"); },