| ... | @@ -105,13 +105,17 @@ pub fn receiveMessage(s: *Server) !InMessage.Header { | ... | @@ -105,13 +105,17 @@ pub fn receiveMessage(s: *Server) !InMessage.Header { |
| 105 | assert(fifo.readableLength() == buf.len); | 105 | assert(fifo.readableLength() == buf.len); |
| 106 | if (buf.len >= @sizeOf(Header)) { | 106 | if (buf.len >= @sizeOf(Header)) { |
| 107 | const header = @ptrCast(*align(1) const Header, buf[0..@sizeOf(Header)]); | 107 | const header = @ptrCast(*align(1) const Header, buf[0..@sizeOf(Header)]); |
| | 108 | const bytes_len = bswap(header.bytes_len); |
| | 109 | const tag = bswap(header.tag); |
| 108 | | 110 | |
| 109 | if (buf.len - @sizeOf(Header) >= header.bytes_len) { | 111 | if (buf.len - @sizeOf(Header) >= bytes_len) { |
| 110 | const result = header.*; | | |
| 111 | fifo.discard(@sizeOf(Header)); | 112 | fifo.discard(@sizeOf(Header)); |
| 112 | return result; | 113 | return .{ |
| | 114 | .tag = tag, |
| | 115 | .bytes_len = bytes_len, |
| | 116 | }; |
| 113 | } else { | 117 | } else { |
| 114 | const needed = header.bytes_len - (buf.len - @sizeOf(Header)); | 118 | const needed = bytes_len - (buf.len - @sizeOf(Header)); |
| 115 | const write_buffer = try fifo.writableWithSize(needed); | 119 | const write_buffer = try fifo.writableWithSize(needed); |
| 116 | const amt = try s.in.read(write_buffer); | 120 | const amt = try s.in.read(write_buffer); |
| 117 | fifo.update(amt); | 121 | fifo.update(amt); |
| ... | @@ -130,7 +134,7 @@ pub fn receiveBody_u32(s: *Server) !u32 { | ... | @@ -130,7 +134,7 @@ pub fn receiveBody_u32(s: *Server) !u32 { |
| 130 | const buf = fifo.readableSlice(0); | 134 | const buf = fifo.readableSlice(0); |
| 131 | const result = @ptrCast(*align(1) const u32, buf[0..4]).*; | 135 | const result = @ptrCast(*align(1) const u32, buf[0..4]).*; |
| 132 | fifo.discard(4); | 136 | fifo.discard(4); |
| 133 | return result; | 137 | return bswap(result); |
| 134 | } | 138 | } |
| 135 | | 139 | |
| 136 | pub fn serveStringMessage(s: *Server, tag: OutMessage.Tag, msg: []const u8) !void { | 140 | pub fn serveStringMessage(s: *Server, tag: OutMessage.Tag, msg: []const u8) !void { |
| ... | @@ -146,8 +150,9 @@ pub fn serveMessage( | ... | @@ -146,8 +150,9 @@ pub fn serveMessage( |
| 146 | bufs: []const []const u8, | 150 | bufs: []const []const u8, |
| 147 | ) !void { | 151 | ) !void { |
| 148 | var iovecs: [10]std.os.iovec_const = undefined; | 152 | var iovecs: [10]std.os.iovec_const = undefined; |
| | 153 | const header_le = bswap(header); |
| 149 | iovecs[0] = .{ | 154 | iovecs[0] = .{ |
| 150 | .iov_base = @ptrCast([*]const u8, &header), | 155 | .iov_base = @ptrCast([*]const u8, &header_le), |
| 151 | .iov_len = @sizeOf(OutMessage.Header), | 156 | .iov_len = @sizeOf(OutMessage.Header), |
| 152 | }; | 157 | }; |
| 153 | for (bufs, iovecs[1 .. bufs.len + 1]) |buf, *iovec| { | 158 | for (bufs, iovecs[1 .. bufs.len + 1]) |buf, *iovec| { |
| ... | @@ -177,11 +182,12 @@ pub fn serveTestResults( | ... | @@ -177,11 +182,12 @@ pub fn serveTestResults( |
| 177 | s: *Server, | 182 | s: *Server, |
| 178 | msg: OutMessage.TestResults, | 183 | msg: OutMessage.TestResults, |
| 179 | ) !void { | 184 | ) !void { |
| | 185 | const msg_le = bswap(msg); |
| 180 | try s.serveMessage(.{ | 186 | try s.serveMessage(.{ |
| 181 | .tag = .test_results, | 187 | .tag = .test_results, |
| 182 | .bytes_len = @intCast(u32, @sizeOf(OutMessage.TestResults)), | 188 | .bytes_len = @intCast(u32, @sizeOf(OutMessage.TestResults)), |
| 183 | }, &.{ | 189 | }, &.{ |
| 184 | std.mem.asBytes(&msg), | 190 | std.mem.asBytes(&msg_le), |
| 185 | }); | 191 | }); |
| 186 | } | 192 | } |
| 187 | | 193 | |
| ... | @@ -204,19 +210,31 @@ pub fn serveErrorBundle(s: *Server, error_bundle: std.zig.ErrorBundle) !void { | ... | @@ -204,19 +210,31 @@ pub fn serveErrorBundle(s: *Server, error_bundle: std.zig.ErrorBundle) !void { |
| 204 | } | 210 | } |
| 205 | | 211 | |
| 206 | pub const TestMetadata = struct { | 212 | pub const TestMetadata = struct { |
| 207 | names: []const u32, | 213 | names: []u32, |
| 208 | async_frame_sizes: []const u32, | 214 | async_frame_sizes: []u32, |
| 209 | expected_panic_msgs: []const u32, | 215 | expected_panic_msgs: []u32, |
| 210 | string_bytes: []const u8, | 216 | string_bytes: []const u8, |
| 211 | }; | 217 | }; |
| 212 | | 218 | |
| 213 | pub fn serveTestMetadata(s: *Server, test_metadata: TestMetadata) !void { | 219 | pub fn serveTestMetadata(s: *Server, test_metadata: TestMetadata) !void { |
| 214 | const header: OutMessage.TestMetadata = .{ | 220 | const header: OutMessage.TestMetadata = .{ |
| 215 | .tests_len = @intCast(u32, test_metadata.names.len), | 221 | .tests_len = bswap(@intCast(u32, test_metadata.names.len)), |
| 216 | .string_bytes_len = @intCast(u32, test_metadata.string_bytes.len), | 222 | .string_bytes_len = bswap(@intCast(u32, test_metadata.string_bytes.len)), |
| 217 | }; | 223 | }; |
| 218 | const bytes_len = @sizeOf(OutMessage.TestMetadata) + | 224 | const bytes_len = @sizeOf(OutMessage.TestMetadata) + |
| 219 | 3 * 4 * test_metadata.names.len + test_metadata.string_bytes.len; | 225 | 3 * 4 * test_metadata.names.len + test_metadata.string_bytes.len; |
| | 226 | |
| | 227 | if (need_bswap) { |
| | 228 | bswap_u32_array(test_metadata.names); |
| | 229 | bswap_u32_array(test_metadata.async_frame_sizes); |
| | 230 | bswap_u32_array(test_metadata.expected_panic_msgs); |
| | 231 | } |
| | 232 | defer if (need_bswap) { |
| | 233 | bswap_u32_array(test_metadata.names); |
| | 234 | bswap_u32_array(test_metadata.async_frame_sizes); |
| | 235 | bswap_u32_array(test_metadata.expected_panic_msgs); |
| | 236 | }; |
| | 237 | |
| 220 | return s.serveMessage(.{ | 238 | return s.serveMessage(.{ |
| 221 | .tag = .test_metadata, | 239 | .tag = .test_metadata, |
| 222 | .bytes_len = @intCast(u32, bytes_len), | 240 | .bytes_len = @intCast(u32, bytes_len), |
| ... | @@ -230,10 +248,43 @@ pub fn serveTestMetadata(s: *Server, test_metadata: TestMetadata) !void { | ... | @@ -230,10 +248,43 @@ pub fn serveTestMetadata(s: *Server, test_metadata: TestMetadata) !void { |
| 230 | }); | 248 | }); |
| 231 | } | 249 | } |
| 232 | | 250 | |
| | 251 | fn bswap(x: anytype) @TypeOf(x) { |
| | 252 | if (!need_bswap) return x; |
| | 253 | |
| | 254 | const T = @TypeOf(x); |
| | 255 | switch (@typeInfo(T)) { |
| | 256 | .Enum => return @intToEnum(T, @byteSwap(@enumToInt(x))), |
| | 257 | .Int => return @byteSwap(x), |
| | 258 | .Struct => |info| switch (info.layout) { |
| | 259 | .Extern => { |
| | 260 | var result: T = undefined; |
| | 261 | inline for (info.fields) |field| { |
| | 262 | @field(result, field.name) = bswap(@field(x, field.name)); |
| | 263 | } |
| | 264 | return result; |
| | 265 | }, |
| | 266 | .Packed => { |
| | 267 | const I = info.backing_integer.?; |
| | 268 | return @bitCast(T, @byteSwap(@bitCast(I, x))); |
| | 269 | }, |
| | 270 | .Auto => @compileError("auto layout struct"), |
| | 271 | }, |
| | 272 | else => @compileError("bswap on type " ++ @typeName(T)), |
| | 273 | } |
| | 274 | } |
| | 275 | |
| | 276 | fn bswap_u32_array(slice: []u32) void { |
| | 277 | comptime assert(need_bswap); |
| | 278 | for (slice) |*elem| elem.* = @byteSwap(elem.*); |
| | 279 | } |
| | 280 | |
| 233 | const OutMessage = std.zig.Server.Message; | 281 | const OutMessage = std.zig.Server.Message; |
| 234 | const InMessage = std.zig.Client.Message; | 282 | const InMessage = std.zig.Client.Message; |
| 235 | | 283 | |
| 236 | const Server = @This(); | 284 | const Server = @This(); |
| | 285 | const builtin = @import("builtin"); |
| 237 | const std = @import("std"); | 286 | const std = @import("std"); |
| 238 | const Allocator = std.mem.Allocator; | 287 | const Allocator = std.mem.Allocator; |
| 239 | const assert = std.debug.assert; | 288 | const assert = std.debug.assert; |
| | 289 | const native_endian = builtin.target.cpu.arch.endian(); |
| | 290 | const need_bswap = native_endian != .Little; |