authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-04-25 00:24:25-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-04-25 00:24:25-04:00
log17ffe166c286de5ff0ef4d67f60267abba5f6e12
treeb76b7924fb16a2313721b7a294b04f75db621bcb
parente1bf74fca3de7943b8f7c15be4da3dbc8e3da17e
signature Commit is signed but in an unrecognized format.

add preliminary windows support to std.io.COutStream


5 files changed, 610 insertions(+), 592 deletions(-)

std/c.zig+2
...@@ -13,6 +13,8 @@ pub use switch (builtin.os) {...@@ -13,6 +13,8 @@ pub use switch (builtin.os) {
13// TODO https://github.com/ziglang/zig/issues/265 on this whole file13// TODO https://github.com/ziglang/zig/issues/265 on this whole file
1414
15pub const FILE = @OpaqueType();15pub const FILE = @OpaqueType();
16pub extern "c" fn fopen(filename: [*]const u8, modes: [*]const u8) ?*FILE;
17pub extern "c" fn fclose(stream: *FILE) c_int;
16pub extern "c" fn fwrite(ptr: [*]const u8, size_of_type: usize, item_count: usize, stream: *FILE) usize;18pub extern "c" fn fwrite(ptr: [*]const u8, size_of_type: usize, item_count: usize, stream: *FILE) usize;
17pub extern "c" fn fread(ptr: [*]u8, size_of_type: usize, item_count: usize, stream: *FILE) usize;19pub extern "c" fn fread(ptr: [*]u8, size_of_type: usize, item_count: usize, stream: *FILE) usize;
1820
std/io.zig+2-1
...@@ -1092,6 +1092,7 @@ test "io.readLineSliceFrom" {...@@ -1092,6 +1092,7 @@ test "io.readLineSliceFrom" {
1092pub const Packing = enum {1092pub const Packing = enum {
1093 /// Pack data to byte alignment1093 /// Pack data to byte alignment
1094 Byte,1094 Byte,
1095
1095 /// Pack data to bit alignment1096 /// Pack data to bit alignment
1096 Bit,1097 Bit,
1097};1098};
...@@ -1454,6 +1455,6 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co...@@ -1454,6 +1455,6 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co
14541455
1455test "import io tests" {1456test "import io tests" {
1456 comptime {1457 comptime {
1457 _ = @import("io_test.zig");1458 _ = @import("io/test.zig");
1458 }1459 }
1459}1460}
std/io/c_out_stream.zig+4
...@@ -24,6 +24,10 @@ pub const COutStream = struct {...@@ -24,6 +24,10 @@ pub const COutStream = struct {
24 const self = @fieldParentPtr(COutStream, "stream", out_stream);24 const self = @fieldParentPtr(COutStream, "stream", out_stream);
25 const amt_written = std.c.fwrite(bytes.ptr, 1, bytes.len, self.c_file);25 const amt_written = std.c.fwrite(bytes.ptr, 1, bytes.len, self.c_file);
26 if (amt_written == bytes.len) return;26 if (amt_written == bytes.len) return;
27 // TODO errno on windows. should we have a posix layer for windows?
28 if (builtin.os == .windows) {
29 return error.InputOutput;
30 }
27 const errno = std.c._errno().*;31 const errno = std.c._errno().*;
28 switch (errno) {32 switch (errno) {
29 0 => unreachable,33 0 => unreachable,
std/io/test.zig created+602
...@@ -0,0 +1,602 @@
1const std = @import("../std.zig");
2const io = std.io;
3const meta = std.meta;
4const trait = std.trait;
5const DefaultPrng = std.rand.DefaultPrng;
6const expect = std.testing.expect;
7const expectError = std.testing.expectError;
8const mem = std.mem;
9const os = std.os;
10const builtin = @import("builtin");
11
12test "write a file, read it, then delete it" {
13 var raw_bytes: [200 * 1024]u8 = undefined;
14 var allocator = &std.heap.FixedBufferAllocator.init(raw_bytes[0..]).allocator;
15
16 var data: [1024]u8 = undefined;
17 var prng = DefaultPrng.init(1234);
18 prng.random.bytes(data[0..]);
19 const tmp_file_name = "temp_test_file.txt";
20 {
21 var file = try os.File.openWrite(tmp_file_name);
22 defer file.close();
23
24 var file_out_stream = file.outStream();
25 var buf_stream = io.BufferedOutStream(os.File.WriteError).init(&file_out_stream.stream);
26 const st = &buf_stream.stream;
27 try st.print("begin");
28 try st.write(data[0..]);
29 try st.print("end");
30 try buf_stream.flush();
31 }
32
33 {
34 // make sure openWriteNoClobber doesn't harm the file
35 if (os.File.openWriteNoClobber(tmp_file_name, os.File.default_mode)) |file| {
36 unreachable;
37 } else |err| {
38 std.debug.assert(err == os.File.OpenError.PathAlreadyExists);
39 }
40 }
41
42 {
43 var file = try os.File.openRead(tmp_file_name);
44 defer file.close();
45
46 const file_size = try file.getEndPos();
47 const expected_file_size = "begin".len + data.len + "end".len;
48 expect(file_size == expected_file_size);
49
50 var file_in_stream = file.inStream();
51 var buf_stream = io.BufferedInStream(os.File.ReadError).init(&file_in_stream.stream);
52 const st = &buf_stream.stream;
53 const contents = try st.readAllAlloc(allocator, 2 * 1024);
54 defer allocator.free(contents);
55
56 expect(mem.eql(u8, contents[0.."begin".len], "begin"));
57 expect(mem.eql(u8, contents["begin".len .. contents.len - "end".len], data));
58 expect(mem.eql(u8, contents[contents.len - "end".len ..], "end"));
59 }
60 try os.deleteFile(tmp_file_name);
61}
62
63test "BufferOutStream" {
64 var bytes: [100]u8 = undefined;
65 var allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator;
66
67 var buffer = try std.Buffer.initSize(allocator, 0);
68 var buf_stream = &std.io.BufferOutStream.init(&buffer).stream;
69
70 const x: i32 = 42;
71 const y: i32 = 1234;
72 try buf_stream.print("x: {}\ny: {}\n", x, y);
73
74 expect(mem.eql(u8, buffer.toSlice(), "x: 42\ny: 1234\n"));
75}
76
77test "SliceInStream" {
78 const bytes = []const u8{ 1, 2, 3, 4, 5, 6, 7 };
79 var ss = io.SliceInStream.init(bytes);
80
81 var dest: [4]u8 = undefined;
82
83 var read = try ss.stream.read(dest[0..4]);
84 expect(read == 4);
85 expect(mem.eql(u8, dest[0..4], bytes[0..4]));
86
87 read = try ss.stream.read(dest[0..4]);
88 expect(read == 3);
89 expect(mem.eql(u8, dest[0..3], bytes[4..7]));
90
91 read = try ss.stream.read(dest[0..4]);
92 expect(read == 0);
93}
94
95test "PeekStream" {
96 const bytes = []const u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
97 var ss = io.SliceInStream.init(bytes);
98 var ps = io.PeekStream(2, io.SliceInStream.Error).init(&ss.stream);
99
100 var dest: [4]u8 = undefined;
101
102 ps.putBackByte(9);
103 ps.putBackByte(10);
104
105 var read = try ps.stream.read(dest[0..4]);
106 expect(read == 4);
107 expect(dest[0] == 10);
108 expect(dest[1] == 9);
109 expect(mem.eql(u8, dest[2..4], bytes[0..2]));
110
111 read = try ps.stream.read(dest[0..4]);
112 expect(read == 4);
113 expect(mem.eql(u8, dest[0..4], bytes[2..6]));
114
115 read = try ps.stream.read(dest[0..4]);
116 expect(read == 2);
117 expect(mem.eql(u8, dest[0..2], bytes[6..8]));
118
119 ps.putBackByte(11);
120 ps.putBackByte(12);
121
122 read = try ps.stream.read(dest[0..4]);
123 expect(read == 2);
124 expect(dest[0] == 12);
125 expect(dest[1] == 11);
126}
127
128test "SliceOutStream" {
129 var buffer: [10]u8 = undefined;
130 var ss = io.SliceOutStream.init(buffer[0..]);
131
132 try ss.stream.write("Hello");
133 expect(mem.eql(u8, ss.getWritten(), "Hello"));
134
135 try ss.stream.write("world");
136 expect(mem.eql(u8, ss.getWritten(), "Helloworld"));
137
138 expectError(error.OutOfSpace, ss.stream.write("!"));
139 expect(mem.eql(u8, ss.getWritten(), "Helloworld"));
140
141 ss.reset();
142 expect(ss.getWritten().len == 0);
143
144 expectError(error.OutOfSpace, ss.stream.write("Hello world!"));
145 expect(mem.eql(u8, ss.getWritten(), "Hello worl"));
146}
147
148test "BitInStream" {
149 const mem_be = []u8{ 0b11001101, 0b00001011 };
150 const mem_le = []u8{ 0b00011101, 0b10010101 };
151
152 var mem_in_be = io.SliceInStream.init(mem_be[0..]);
153 const InError = io.SliceInStream.Error;
154 var bit_stream_be = io.BitInStream(builtin.Endian.Big, InError).init(&mem_in_be.stream);
155
156 var out_bits: usize = undefined;
157
158 expect(1 == try bit_stream_be.readBits(u2, 1, &out_bits));
159 expect(out_bits == 1);
160 expect(2 == try bit_stream_be.readBits(u5, 2, &out_bits));
161 expect(out_bits == 2);
162 expect(3 == try bit_stream_be.readBits(u128, 3, &out_bits));
163 expect(out_bits == 3);
164 expect(4 == try bit_stream_be.readBits(u8, 4, &out_bits));
165 expect(out_bits == 4);
166 expect(5 == try bit_stream_be.readBits(u9, 5, &out_bits));
167 expect(out_bits == 5);
168 expect(1 == try bit_stream_be.readBits(u1, 1, &out_bits));
169 expect(out_bits == 1);
170
171 mem_in_be.pos = 0;
172 bit_stream_be.bit_count = 0;
173 expect(0b110011010000101 == try bit_stream_be.readBits(u15, 15, &out_bits));
174 expect(out_bits == 15);
175
176 mem_in_be.pos = 0;
177 bit_stream_be.bit_count = 0;
178 expect(0b1100110100001011 == try bit_stream_be.readBits(u16, 16, &out_bits));
179 expect(out_bits == 16);
180
181 _ = try bit_stream_be.readBits(u0, 0, &out_bits);
182
183 expect(0 == try bit_stream_be.readBits(u1, 1, &out_bits));
184 expect(out_bits == 0);
185 expectError(error.EndOfStream, bit_stream_be.readBitsNoEof(u1, 1));
186
187 var mem_in_le = io.SliceInStream.init(mem_le[0..]);
188 var bit_stream_le = io.BitInStream(builtin.Endian.Little, InError).init(&mem_in_le.stream);
189
190 expect(1 == try bit_stream_le.readBits(u2, 1, &out_bits));
191 expect(out_bits == 1);
192 expect(2 == try bit_stream_le.readBits(u5, 2, &out_bits));
193 expect(out_bits == 2);
194 expect(3 == try bit_stream_le.readBits(u128, 3, &out_bits));
195 expect(out_bits == 3);
196 expect(4 == try bit_stream_le.readBits(u8, 4, &out_bits));
197 expect(out_bits == 4);
198 expect(5 == try bit_stream_le.readBits(u9, 5, &out_bits));
199 expect(out_bits == 5);
200 expect(1 == try bit_stream_le.readBits(u1, 1, &out_bits));
201 expect(out_bits == 1);
202
203 mem_in_le.pos = 0;
204 bit_stream_le.bit_count = 0;
205 expect(0b001010100011101 == try bit_stream_le.readBits(u15, 15, &out_bits));
206 expect(out_bits == 15);
207
208 mem_in_le.pos = 0;
209 bit_stream_le.bit_count = 0;
210 expect(0b1001010100011101 == try bit_stream_le.readBits(u16, 16, &out_bits));
211 expect(out_bits == 16);
212
213 _ = try bit_stream_le.readBits(u0, 0, &out_bits);
214
215 expect(0 == try bit_stream_le.readBits(u1, 1, &out_bits));
216 expect(out_bits == 0);
217 expectError(error.EndOfStream, bit_stream_le.readBitsNoEof(u1, 1));
218}
219
220test "BitOutStream" {
221 var mem_be = []u8{0} ** 2;
222 var mem_le = []u8{0} ** 2;
223
224 var mem_out_be = io.SliceOutStream.init(mem_be[0..]);
225 const OutError = io.SliceOutStream.Error;
226 var bit_stream_be = io.BitOutStream(builtin.Endian.Big, OutError).init(&mem_out_be.stream);
227
228 try bit_stream_be.writeBits(u2(1), 1);
229 try bit_stream_be.writeBits(u5(2), 2);
230 try bit_stream_be.writeBits(u128(3), 3);
231 try bit_stream_be.writeBits(u8(4), 4);
232 try bit_stream_be.writeBits(u9(5), 5);
233 try bit_stream_be.writeBits(u1(1), 1);
234
235 expect(mem_be[0] == 0b11001101 and mem_be[1] == 0b00001011);
236
237 mem_out_be.pos = 0;
238
239 try bit_stream_be.writeBits(u15(0b110011010000101), 15);
240 try bit_stream_be.flushBits();
241 expect(mem_be[0] == 0b11001101 and mem_be[1] == 0b00001010);
242
243 mem_out_be.pos = 0;
244 try bit_stream_be.writeBits(u32(0b110011010000101), 16);
245 expect(mem_be[0] == 0b01100110 and mem_be[1] == 0b10000101);
246
247 try bit_stream_be.writeBits(u0(0), 0);
248
249 var mem_out_le = io.SliceOutStream.init(mem_le[0..]);
250 var bit_stream_le = io.BitOutStream(builtin.Endian.Little, OutError).init(&mem_out_le.stream);
251
252 try bit_stream_le.writeBits(u2(1), 1);
253 try bit_stream_le.writeBits(u5(2), 2);
254 try bit_stream_le.writeBits(u128(3), 3);
255 try bit_stream_le.writeBits(u8(4), 4);
256 try bit_stream_le.writeBits(u9(5), 5);
257 try bit_stream_le.writeBits(u1(1), 1);
258
259 expect(mem_le[0] == 0b00011101 and mem_le[1] == 0b10010101);
260
261 mem_out_le.pos = 0;
262 try bit_stream_le.writeBits(u15(0b110011010000101), 15);
263 try bit_stream_le.flushBits();
264 expect(mem_le[0] == 0b10000101 and mem_le[1] == 0b01100110);
265
266 mem_out_le.pos = 0;
267 try bit_stream_le.writeBits(u32(0b1100110100001011), 16);
268 expect(mem_le[0] == 0b00001011 and mem_le[1] == 0b11001101);
269
270 try bit_stream_le.writeBits(u0(0), 0);
271}
272
273test "BitStreams with File Stream" {
274 const tmp_file_name = "temp_test_file.txt";
275 {
276 var file = try os.File.openWrite(tmp_file_name);
277 defer file.close();
278
279 var file_out = file.outStream();
280 var file_out_stream = &file_out.stream;
281 const OutError = os.File.WriteError;
282 var bit_stream = io.BitOutStream(builtin.endian, OutError).init(file_out_stream);
283
284 try bit_stream.writeBits(u2(1), 1);
285 try bit_stream.writeBits(u5(2), 2);
286 try bit_stream.writeBits(u128(3), 3);
287 try bit_stream.writeBits(u8(4), 4);
288 try bit_stream.writeBits(u9(5), 5);
289 try bit_stream.writeBits(u1(1), 1);
290 try bit_stream.flushBits();
291 }
292 {
293 var file = try os.File.openRead(tmp_file_name);
294 defer file.close();
295
296 var file_in = file.inStream();
297 var file_in_stream = &file_in.stream;
298 const InError = os.File.ReadError;
299 var bit_stream = io.BitInStream(builtin.endian, InError).init(file_in_stream);
300
301 var out_bits: usize = undefined;
302
303 expect(1 == try bit_stream.readBits(u2, 1, &out_bits));
304 expect(out_bits == 1);
305 expect(2 == try bit_stream.readBits(u5, 2, &out_bits));
306 expect(out_bits == 2);
307 expect(3 == try bit_stream.readBits(u128, 3, &out_bits));
308 expect(out_bits == 3);
309 expect(4 == try bit_stream.readBits(u8, 4, &out_bits));
310 expect(out_bits == 4);
311 expect(5 == try bit_stream.readBits(u9, 5, &out_bits));
312 expect(out_bits == 5);
313 expect(1 == try bit_stream.readBits(u1, 1, &out_bits));
314 expect(out_bits == 1);
315
316 expectError(error.EndOfStream, bit_stream.readBitsNoEof(u1, 1));
317 }
318 try os.deleteFile(tmp_file_name);
319}
320
321fn testIntSerializerDeserializer(comptime endian: builtin.Endian, comptime packing: io.Packing) !void {
322 //@NOTE: if this test is taking too long, reduce the maximum tested bitsize
323 const max_test_bitsize = 128;
324
325 const total_bytes = comptime blk: {
326 var bytes = 0;
327 comptime var i = 0;
328 while (i <= max_test_bitsize) : (i += 1) bytes += (i / 8) + @boolToInt(i % 8 > 0);
329 break :blk bytes * 2;
330 };
331
332 var data_mem: [total_bytes]u8 = undefined;
333 var out = io.SliceOutStream.init(data_mem[0..]);
334 const OutError = io.SliceOutStream.Error;
335 var out_stream = &out.stream;
336 var serializer = io.Serializer(endian, packing, OutError).init(out_stream);
337
338 var in = io.SliceInStream.init(data_mem[0..]);
339 const InError = io.SliceInStream.Error;
340 var in_stream = &in.stream;
341 var deserializer = io.Deserializer(endian, packing, InError).init(in_stream);
342
343 comptime var i = 0;
344 inline while (i <= max_test_bitsize) : (i += 1) {
345 const U = @IntType(false, i);
346 const S = @IntType(true, i);
347 try serializer.serializeInt(U(i));
348 if (i != 0) try serializer.serializeInt(S(-1)) else try serializer.serialize(S(0));
349 }
350 try serializer.flush();
351
352 i = 0;
353 inline while (i <= max_test_bitsize) : (i += 1) {
354 const U = @IntType(false, i);
355 const S = @IntType(true, i);
356 const x = try deserializer.deserializeInt(U);
357 const y = try deserializer.deserializeInt(S);
358 expect(x == U(i));
359 if (i != 0) expect(y == S(-1)) else expect(y == 0);
360 }
361
362 const u8_bit_count = comptime meta.bitCount(u8);
363 //0 + 1 + 2 + ... n = (n * (n + 1)) / 2
364 //and we have each for unsigned and signed, so * 2
365 const total_bits = (max_test_bitsize * (max_test_bitsize + 1));
366 const extra_packed_byte = @boolToInt(total_bits % u8_bit_count > 0);
367 const total_packed_bytes = (total_bits / u8_bit_count) + extra_packed_byte;
368
369 expect(in.pos == if (packing == .Bit) total_packed_bytes else total_bytes);
370
371 //Verify that empty error set works with serializer.
372 //deserializer is covered by SliceInStream
373 const NullError = io.NullOutStream.Error;
374 var null_out = io.NullOutStream.init();
375 var null_out_stream = &null_out.stream;
376 var null_serializer = io.Serializer(endian, packing, NullError).init(null_out_stream);
377 try null_serializer.serialize(data_mem[0..]);
378 try null_serializer.flush();
379}
380
381test "Serializer/Deserializer Int" {
382 try testIntSerializerDeserializer(.Big, .Byte);
383 try testIntSerializerDeserializer(.Little, .Byte);
384 // TODO these tests are disabled due to tripping an LLVM assertion
385 // https://github.com/ziglang/zig/issues/2019
386 //try testIntSerializerDeserializer(builtin.Endian.Big, true);
387 //try testIntSerializerDeserializer(builtin.Endian.Little, true);
388}
389
390fn testIntSerializerDeserializerInfNaN(
391 comptime endian: builtin.Endian,
392 comptime packing: io.Packing,
393) !void {
394 const mem_size = (16 * 2 + 32 * 2 + 64 * 2 + 128 * 2) / comptime meta.bitCount(u8);
395 var data_mem: [mem_size]u8 = undefined;
396
397 var out = io.SliceOutStream.init(data_mem[0..]);
398 const OutError = io.SliceOutStream.Error;
399 var out_stream = &out.stream;
400 var serializer = io.Serializer(endian, packing, OutError).init(out_stream);
401
402 var in = io.SliceInStream.init(data_mem[0..]);
403 const InError = io.SliceInStream.Error;
404 var in_stream = &in.stream;
405 var deserializer = io.Deserializer(endian, packing, InError).init(in_stream);
406
407 //@TODO: isInf/isNan not currently implemented for f128.
408 try serializer.serialize(std.math.nan(f16));
409 try serializer.serialize(std.math.inf(f16));
410 try serializer.serialize(std.math.nan(f32));
411 try serializer.serialize(std.math.inf(f32));
412 try serializer.serialize(std.math.nan(f64));
413 try serializer.serialize(std.math.inf(f64));
414 //try serializer.serialize(std.math.nan(f128));
415 //try serializer.serialize(std.math.inf(f128));
416 const nan_check_f16 = try deserializer.deserialize(f16);
417 const inf_check_f16 = try deserializer.deserialize(f16);
418 const nan_check_f32 = try deserializer.deserialize(f32);
419 const inf_check_f32 = try deserializer.deserialize(f32);
420 const nan_check_f64 = try deserializer.deserialize(f64);
421 const inf_check_f64 = try deserializer.deserialize(f64);
422 //const nan_check_f128 = try deserializer.deserialize(f128);
423 //const inf_check_f128 = try deserializer.deserialize(f128);
424 expect(std.math.isNan(nan_check_f16));
425 expect(std.math.isInf(inf_check_f16));
426 expect(std.math.isNan(nan_check_f32));
427 expect(std.math.isInf(inf_check_f32));
428 expect(std.math.isNan(nan_check_f64));
429 expect(std.math.isInf(inf_check_f64));
430 //expect(std.math.isNan(nan_check_f128));
431 //expect(std.math.isInf(inf_check_f128));
432}
433
434test "Serializer/Deserializer Int: Inf/NaN" {
435 try testIntSerializerDeserializerInfNaN(.Big, .Byte);
436 try testIntSerializerDeserializerInfNaN(.Little, .Byte);
437 try testIntSerializerDeserializerInfNaN(.Big, .Bit);
438 try testIntSerializerDeserializerInfNaN(.Little, .Bit);
439}
440
441fn testAlternateSerializer(self: var, serializer: var) !void {
442 try serializer.serialize(self.f_f16);
443}
444
445fn testSerializerDeserializer(comptime endian: builtin.Endian, comptime packing: io.Packing) !void {
446 const ColorType = enum(u4) {
447 RGB8 = 1,
448 RA16 = 2,
449 R32 = 3,
450 };
451
452 const TagAlign = union(enum(u32)) {
453 A: u8,
454 B: u8,
455 C: u8,
456 };
457
458 const Color = union(ColorType) {
459 RGB8: struct {
460 r: u8,
461 g: u8,
462 b: u8,
463 a: u8,
464 },
465 RA16: struct {
466 r: u16,
467 a: u16,
468 },
469 R32: u32,
470 };
471
472 const PackedStruct = packed struct {
473 f_i3: i3,
474 f_u2: u2,
475 };
476
477 //to test custom serialization
478 const Custom = struct {
479 f_f16: f16,
480 f_unused_u32: u32,
481
482 pub fn deserialize(self: *@This(), deserializer: var) !void {
483 try deserializer.deserializeInto(&self.f_f16);
484 self.f_unused_u32 = 47;
485 }
486
487 pub const serialize = testAlternateSerializer;
488 };
489
490 const MyStruct = struct {
491 f_i3: i3,
492 f_u8: u8,
493 f_tag_align: TagAlign,
494 f_u24: u24,
495 f_i19: i19,
496 f_void: void,
497 f_f32: f32,
498 f_f128: f128,
499 f_packed_0: PackedStruct,
500 f_i7arr: [10]i7,
501 f_of64n: ?f64,
502 f_of64v: ?f64,
503 f_color_type: ColorType,
504 f_packed_1: PackedStruct,
505 f_custom: Custom,
506 f_color: Color,
507 };
508
509 const my_inst = MyStruct{
510 .f_i3 = -1,
511 .f_u8 = 8,
512 .f_tag_align = TagAlign{ .B = 148 },
513 .f_u24 = 24,
514 .f_i19 = 19,
515 .f_void = {},
516 .f_f32 = 32.32,
517 .f_f128 = 128.128,
518 .f_packed_0 = PackedStruct{ .f_i3 = -1, .f_u2 = 2 },
519 .f_i7arr = [10]i7{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
520 .f_of64n = null,
521 .f_of64v = 64.64,
522 .f_color_type = ColorType.R32,
523 .f_packed_1 = PackedStruct{ .f_i3 = 1, .f_u2 = 1 },
524 .f_custom = Custom{ .f_f16 = 38.63, .f_unused_u32 = 47 },
525 .f_color = Color{ .R32 = 123822 },
526 };
527
528 var data_mem: [@sizeOf(MyStruct)]u8 = undefined;
529 var out = io.SliceOutStream.init(data_mem[0..]);
530 const OutError = io.SliceOutStream.Error;
531 var out_stream = &out.stream;
532 var serializer = io.Serializer(endian, packing, OutError).init(out_stream);
533
534 var in = io.SliceInStream.init(data_mem[0..]);
535 const InError = io.SliceInStream.Error;
536 var in_stream = &in.stream;
537 var deserializer = io.Deserializer(endian, packing, InError).init(in_stream);
538
539 try serializer.serialize(my_inst);
540
541 const my_copy = try deserializer.deserialize(MyStruct);
542 expect(meta.eql(my_copy, my_inst));
543}
544
545test "Serializer/Deserializer generic" {
546 try testSerializerDeserializer(builtin.Endian.Big, .Byte);
547 try testSerializerDeserializer(builtin.Endian.Little, .Byte);
548 try testSerializerDeserializer(builtin.Endian.Big, .Bit);
549 try testSerializerDeserializer(builtin.Endian.Little, .Bit);
550}
551
552fn testBadData(comptime endian: builtin.Endian, comptime packing: io.Packing) !void {
553 const E = enum(u14) {
554 One = 1,
555 Two = 2,
556 };
557
558 const A = struct {
559 e: E,
560 };
561
562 const C = union(E) {
563 One: u14,
564 Two: f16,
565 };
566
567 var data_mem: [4]u8 = undefined;
568 var out = io.SliceOutStream.init(data_mem[0..]);
569 const OutError = io.SliceOutStream.Error;
570 var out_stream = &out.stream;
571 var serializer = io.Serializer(endian, packing, OutError).init(out_stream);
572
573 var in = io.SliceInStream.init(data_mem[0..]);
574 const InError = io.SliceInStream.Error;
575 var in_stream = &in.stream;
576 var deserializer = io.Deserializer(endian, packing, InError).init(in_stream);
577
578 try serializer.serialize(u14(3));
579 expectError(error.InvalidEnumTag, deserializer.deserialize(A));
580 out.pos = 0;
581 try serializer.serialize(u14(3));
582 try serializer.serialize(u14(88));
583 expectError(error.InvalidEnumTag, deserializer.deserialize(C));
584}
585
586test "Deserializer bad data" {
587 try testBadData(.Big, .Byte);
588 try testBadData(.Little, .Byte);
589 try testBadData(.Big, .Bit);
590 try testBadData(.Little, .Bit);
591}
592
593test "c out stream" {
594 if (!builtin.link_libc) return error.SkipZigTest;
595
596 const filename = c"tmp_io_test_file.txt";
597 const out_file = std.c.fopen(filename, c"w") orelse return error.UnableToOpenTestFile;
598 defer std.os.deleteFileC(filename) catch {};
599
600 const out_stream = &io.COutStream.init(out_file).stream;
601 try out_stream.print("hi: {}\n", i32(123));
602}
std/io_test.zig deleted-591
...@@ -1,591 +0,0 @@
1const std = @import("std.zig");
2const io = std.io;
3const meta = std.meta;
4const trait = std.trait;
5const DefaultPrng = std.rand.DefaultPrng;
6const expect = std.testing.expect;
7const expectError = std.testing.expectError;
8const mem = std.mem;
9const os = std.os;
10const builtin = @import("builtin");
11
12test "write a file, read it, then delete it" {
13 var raw_bytes: [200 * 1024]u8 = undefined;
14 var allocator = &std.heap.FixedBufferAllocator.init(raw_bytes[0..]).allocator;
15
16 var data: [1024]u8 = undefined;
17 var prng = DefaultPrng.init(1234);
18 prng.random.bytes(data[0..]);
19 const tmp_file_name = "temp_test_file.txt";
20 {
21 var file = try os.File.openWrite(tmp_file_name);
22 defer file.close();
23
24 var file_out_stream = file.outStream();
25 var buf_stream = io.BufferedOutStream(os.File.WriteError).init(&file_out_stream.stream);
26 const st = &buf_stream.stream;
27 try st.print("begin");
28 try st.write(data[0..]);
29 try st.print("end");
30 try buf_stream.flush();
31 }
32
33 {
34 // make sure openWriteNoClobber doesn't harm the file
35 if (os.File.openWriteNoClobber(tmp_file_name, os.File.default_mode)) |file| {
36 unreachable;
37 } else |err| {
38 std.debug.assert(err == os.File.OpenError.PathAlreadyExists);
39 }
40 }
41
42 {
43 var file = try os.File.openRead(tmp_file_name);
44 defer file.close();
45
46 const file_size = try file.getEndPos();
47 const expected_file_size = "begin".len + data.len + "end".len;
48 expect(file_size == expected_file_size);
49
50 var file_in_stream = file.inStream();
51 var buf_stream = io.BufferedInStream(os.File.ReadError).init(&file_in_stream.stream);
52 const st = &buf_stream.stream;
53 const contents = try st.readAllAlloc(allocator, 2 * 1024);
54 defer allocator.free(contents);
55
56 expect(mem.eql(u8, contents[0.."begin".len], "begin"));
57 expect(mem.eql(u8, contents["begin".len .. contents.len - "end".len], data));
58 expect(mem.eql(u8, contents[contents.len - "end".len ..], "end"));
59 }
60 try os.deleteFile(tmp_file_name);
61}
62
63test "BufferOutStream" {
64 var bytes: [100]u8 = undefined;
65 var allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator;
66
67 var buffer = try std.Buffer.initSize(allocator, 0);
68 var buf_stream = &std.io.BufferOutStream.init(&buffer).stream;
69
70 const x: i32 = 42;
71 const y: i32 = 1234;
72 try buf_stream.print("x: {}\ny: {}\n", x, y);
73
74 expect(mem.eql(u8, buffer.toSlice(), "x: 42\ny: 1234\n"));
75}
76
77test "SliceInStream" {
78 const bytes = []const u8{ 1, 2, 3, 4, 5, 6, 7 };
79 var ss = io.SliceInStream.init(bytes);
80
81 var dest: [4]u8 = undefined;
82
83 var read = try ss.stream.read(dest[0..4]);
84 expect(read == 4);
85 expect(mem.eql(u8, dest[0..4], bytes[0..4]));
86
87 read = try ss.stream.read(dest[0..4]);
88 expect(read == 3);
89 expect(mem.eql(u8, dest[0..3], bytes[4..7]));
90
91 read = try ss.stream.read(dest[0..4]);
92 expect(read == 0);
93}
94
95test "PeekStream" {
96 const bytes = []const u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
97 var ss = io.SliceInStream.init(bytes);
98 var ps = io.PeekStream(2, io.SliceInStream.Error).init(&ss.stream);
99
100 var dest: [4]u8 = undefined;
101
102 ps.putBackByte(9);
103 ps.putBackByte(10);
104
105 var read = try ps.stream.read(dest[0..4]);
106 expect(read == 4);
107 expect(dest[0] == 10);
108 expect(dest[1] == 9);
109 expect(mem.eql(u8, dest[2..4], bytes[0..2]));
110
111 read = try ps.stream.read(dest[0..4]);
112 expect(read == 4);
113 expect(mem.eql(u8, dest[0..4], bytes[2..6]));
114
115 read = try ps.stream.read(dest[0..4]);
116 expect(read == 2);
117 expect(mem.eql(u8, dest[0..2], bytes[6..8]));
118
119 ps.putBackByte(11);
120 ps.putBackByte(12);
121
122 read = try ps.stream.read(dest[0..4]);
123 expect(read == 2);
124 expect(dest[0] == 12);
125 expect(dest[1] == 11);
126}
127
128test "SliceOutStream" {
129 var buffer: [10]u8 = undefined;
130 var ss = io.SliceOutStream.init(buffer[0..]);
131
132 try ss.stream.write("Hello");
133 expect(mem.eql(u8, ss.getWritten(), "Hello"));
134
135 try ss.stream.write("world");
136 expect(mem.eql(u8, ss.getWritten(), "Helloworld"));
137
138 expectError(error.OutOfSpace, ss.stream.write("!"));
139 expect(mem.eql(u8, ss.getWritten(), "Helloworld"));
140
141 ss.reset();
142 expect(ss.getWritten().len == 0);
143
144 expectError(error.OutOfSpace, ss.stream.write("Hello world!"));
145 expect(mem.eql(u8, ss.getWritten(), "Hello worl"));
146}
147
148test "BitInStream" {
149 const mem_be = []u8{ 0b11001101, 0b00001011 };
150 const mem_le = []u8{ 0b00011101, 0b10010101 };
151
152 var mem_in_be = io.SliceInStream.init(mem_be[0..]);
153 const InError = io.SliceInStream.Error;
154 var bit_stream_be = io.BitInStream(builtin.Endian.Big, InError).init(&mem_in_be.stream);
155
156 var out_bits: usize = undefined;
157
158 expect(1 == try bit_stream_be.readBits(u2, 1, &out_bits));
159 expect(out_bits == 1);
160 expect(2 == try bit_stream_be.readBits(u5, 2, &out_bits));
161 expect(out_bits == 2);
162 expect(3 == try bit_stream_be.readBits(u128, 3, &out_bits));
163 expect(out_bits == 3);
164 expect(4 == try bit_stream_be.readBits(u8, 4, &out_bits));
165 expect(out_bits == 4);
166 expect(5 == try bit_stream_be.readBits(u9, 5, &out_bits));
167 expect(out_bits == 5);
168 expect(1 == try bit_stream_be.readBits(u1, 1, &out_bits));
169 expect(out_bits == 1);
170
171 mem_in_be.pos = 0;
172 bit_stream_be.bit_count = 0;
173 expect(0b110011010000101 == try bit_stream_be.readBits(u15, 15, &out_bits));
174 expect(out_bits == 15);
175
176 mem_in_be.pos = 0;
177 bit_stream_be.bit_count = 0;
178 expect(0b1100110100001011 == try bit_stream_be.readBits(u16, 16, &out_bits));
179 expect(out_bits == 16);
180
181 _ = try bit_stream_be.readBits(u0, 0, &out_bits);
182
183 expect(0 == try bit_stream_be.readBits(u1, 1, &out_bits));
184 expect(out_bits == 0);
185 expectError(error.EndOfStream, bit_stream_be.readBitsNoEof(u1, 1));
186
187 var mem_in_le = io.SliceInStream.init(mem_le[0..]);
188 var bit_stream_le = io.BitInStream(builtin.Endian.Little, InError).init(&mem_in_le.stream);
189
190 expect(1 == try bit_stream_le.readBits(u2, 1, &out_bits));
191 expect(out_bits == 1);
192 expect(2 == try bit_stream_le.readBits(u5, 2, &out_bits));
193 expect(out_bits == 2);
194 expect(3 == try bit_stream_le.readBits(u128, 3, &out_bits));
195 expect(out_bits == 3);
196 expect(4 == try bit_stream_le.readBits(u8, 4, &out_bits));
197 expect(out_bits == 4);
198 expect(5 == try bit_stream_le.readBits(u9, 5, &out_bits));
199 expect(out_bits == 5);
200 expect(1 == try bit_stream_le.readBits(u1, 1, &out_bits));
201 expect(out_bits == 1);
202
203 mem_in_le.pos = 0;
204 bit_stream_le.bit_count = 0;
205 expect(0b001010100011101 == try bit_stream_le.readBits(u15, 15, &out_bits));
206 expect(out_bits == 15);
207
208 mem_in_le.pos = 0;
209 bit_stream_le.bit_count = 0;
210 expect(0b1001010100011101 == try bit_stream_le.readBits(u16, 16, &out_bits));
211 expect(out_bits == 16);
212
213 _ = try bit_stream_le.readBits(u0, 0, &out_bits);
214
215 expect(0 == try bit_stream_le.readBits(u1, 1, &out_bits));
216 expect(out_bits == 0);
217 expectError(error.EndOfStream, bit_stream_le.readBitsNoEof(u1, 1));
218}
219
220test "BitOutStream" {
221 var mem_be = []u8{0} ** 2;
222 var mem_le = []u8{0} ** 2;
223
224 var mem_out_be = io.SliceOutStream.init(mem_be[0..]);
225 const OutError = io.SliceOutStream.Error;
226 var bit_stream_be = io.BitOutStream(builtin.Endian.Big, OutError).init(&mem_out_be.stream);
227
228 try bit_stream_be.writeBits(u2(1), 1);
229 try bit_stream_be.writeBits(u5(2), 2);
230 try bit_stream_be.writeBits(u128(3), 3);
231 try bit_stream_be.writeBits(u8(4), 4);
232 try bit_stream_be.writeBits(u9(5), 5);
233 try bit_stream_be.writeBits(u1(1), 1);
234
235 expect(mem_be[0] == 0b11001101 and mem_be[1] == 0b00001011);
236
237 mem_out_be.pos = 0;
238
239 try bit_stream_be.writeBits(u15(0b110011010000101), 15);
240 try bit_stream_be.flushBits();
241 expect(mem_be[0] == 0b11001101 and mem_be[1] == 0b00001010);
242
243 mem_out_be.pos = 0;
244 try bit_stream_be.writeBits(u32(0b110011010000101), 16);
245 expect(mem_be[0] == 0b01100110 and mem_be[1] == 0b10000101);
246
247 try bit_stream_be.writeBits(u0(0), 0);
248
249 var mem_out_le = io.SliceOutStream.init(mem_le[0..]);
250 var bit_stream_le = io.BitOutStream(builtin.Endian.Little, OutError).init(&mem_out_le.stream);
251
252 try bit_stream_le.writeBits(u2(1), 1);
253 try bit_stream_le.writeBits(u5(2), 2);
254 try bit_stream_le.writeBits(u128(3), 3);
255 try bit_stream_le.writeBits(u8(4), 4);
256 try bit_stream_le.writeBits(u9(5), 5);
257 try bit_stream_le.writeBits(u1(1), 1);
258
259 expect(mem_le[0] == 0b00011101 and mem_le[1] == 0b10010101);
260
261 mem_out_le.pos = 0;
262 try bit_stream_le.writeBits(u15(0b110011010000101), 15);
263 try bit_stream_le.flushBits();
264 expect(mem_le[0] == 0b10000101 and mem_le[1] == 0b01100110);
265
266 mem_out_le.pos = 0;
267 try bit_stream_le.writeBits(u32(0b1100110100001011), 16);
268 expect(mem_le[0] == 0b00001011 and mem_le[1] == 0b11001101);
269
270 try bit_stream_le.writeBits(u0(0), 0);
271}
272
273test "BitStreams with File Stream" {
274 const tmp_file_name = "temp_test_file.txt";
275 {
276 var file = try os.File.openWrite(tmp_file_name);
277 defer file.close();
278
279 var file_out = file.outStream();
280 var file_out_stream = &file_out.stream;
281 const OutError = os.File.WriteError;
282 var bit_stream = io.BitOutStream(builtin.endian, OutError).init(file_out_stream);
283
284 try bit_stream.writeBits(u2(1), 1);
285 try bit_stream.writeBits(u5(2), 2);
286 try bit_stream.writeBits(u128(3), 3);
287 try bit_stream.writeBits(u8(4), 4);
288 try bit_stream.writeBits(u9(5), 5);
289 try bit_stream.writeBits(u1(1), 1);
290 try bit_stream.flushBits();
291 }
292 {
293 var file = try os.File.openRead(tmp_file_name);
294 defer file.close();
295
296 var file_in = file.inStream();
297 var file_in_stream = &file_in.stream;
298 const InError = os.File.ReadError;
299 var bit_stream = io.BitInStream(builtin.endian, InError).init(file_in_stream);
300
301 var out_bits: usize = undefined;
302
303 expect(1 == try bit_stream.readBits(u2, 1, &out_bits));
304 expect(out_bits == 1);
305 expect(2 == try bit_stream.readBits(u5, 2, &out_bits));
306 expect(out_bits == 2);
307 expect(3 == try bit_stream.readBits(u128, 3, &out_bits));
308 expect(out_bits == 3);
309 expect(4 == try bit_stream.readBits(u8, 4, &out_bits));
310 expect(out_bits == 4);
311 expect(5 == try bit_stream.readBits(u9, 5, &out_bits));
312 expect(out_bits == 5);
313 expect(1 == try bit_stream.readBits(u1, 1, &out_bits));
314 expect(out_bits == 1);
315
316 expectError(error.EndOfStream, bit_stream.readBitsNoEof(u1, 1));
317 }
318 try os.deleteFile(tmp_file_name);
319}
320
321fn testIntSerializerDeserializer(comptime endian: builtin.Endian, comptime packing: io.Packing) !void {
322 //@NOTE: if this test is taking too long, reduce the maximum tested bitsize
323 const max_test_bitsize = 128;
324
325 const total_bytes = comptime blk: {
326 var bytes = 0;
327 comptime var i = 0;
328 while (i <= max_test_bitsize) : (i += 1) bytes += (i / 8) + @boolToInt(i % 8 > 0);
329 break :blk bytes * 2;
330 };
331
332 var data_mem: [total_bytes]u8 = undefined;
333 var out = io.SliceOutStream.init(data_mem[0..]);
334 const OutError = io.SliceOutStream.Error;
335 var out_stream = &out.stream;
336 var serializer = io.Serializer(endian, packing, OutError).init(out_stream);
337
338 var in = io.SliceInStream.init(data_mem[0..]);
339 const InError = io.SliceInStream.Error;
340 var in_stream = &in.stream;
341 var deserializer = io.Deserializer(endian, packing, InError).init(in_stream);
342
343 comptime var i = 0;
344 inline while (i <= max_test_bitsize) : (i += 1) {
345 const U = @IntType(false, i);
346 const S = @IntType(true, i);
347 try serializer.serializeInt(U(i));
348 if (i != 0) try serializer.serializeInt(S(-1)) else try serializer.serialize(S(0));
349 }
350 try serializer.flush();
351
352 i = 0;
353 inline while (i <= max_test_bitsize) : (i += 1) {
354 const U = @IntType(false, i);
355 const S = @IntType(true, i);
356 const x = try deserializer.deserializeInt(U);
357 const y = try deserializer.deserializeInt(S);
358 expect(x == U(i));
359 if (i != 0) expect(y == S(-1)) else expect(y == 0);
360 }
361
362 const u8_bit_count = comptime meta.bitCount(u8);
363 //0 + 1 + 2 + ... n = (n * (n + 1)) / 2
364 //and we have each for unsigned and signed, so * 2
365 const total_bits = (max_test_bitsize * (max_test_bitsize + 1));
366 const extra_packed_byte = @boolToInt(total_bits % u8_bit_count > 0);
367 const total_packed_bytes = (total_bits / u8_bit_count) + extra_packed_byte;
368
369 expect(in.pos == if (packing == .Bit) total_packed_bytes else total_bytes);
370
371 //Verify that empty error set works with serializer.
372 //deserializer is covered by SliceInStream
373 const NullError = io.NullOutStream.Error;
374 var null_out = io.NullOutStream.init();
375 var null_out_stream = &null_out.stream;
376 var null_serializer = io.Serializer(endian, packing, NullError).init(null_out_stream);
377 try null_serializer.serialize(data_mem[0..]);
378 try null_serializer.flush();
379}
380
381test "Serializer/Deserializer Int" {
382 try testIntSerializerDeserializer(.Big, .Byte);
383 try testIntSerializerDeserializer(.Little, .Byte);
384 // TODO these tests are disabled due to tripping an LLVM assertion
385 // https://github.com/ziglang/zig/issues/2019
386 //try testIntSerializerDeserializer(builtin.Endian.Big, true);
387 //try testIntSerializerDeserializer(builtin.Endian.Little, true);
388}
389
390fn testIntSerializerDeserializerInfNaN(
391 comptime endian: builtin.Endian,
392 comptime packing: io.Packing,
393) !void {
394 const mem_size = (16 * 2 + 32 * 2 + 64 * 2 + 128 * 2) / comptime meta.bitCount(u8);
395 var data_mem: [mem_size]u8 = undefined;
396
397 var out = io.SliceOutStream.init(data_mem[0..]);
398 const OutError = io.SliceOutStream.Error;
399 var out_stream = &out.stream;
400 var serializer = io.Serializer(endian, packing, OutError).init(out_stream);
401
402 var in = io.SliceInStream.init(data_mem[0..]);
403 const InError = io.SliceInStream.Error;
404 var in_stream = &in.stream;
405 var deserializer = io.Deserializer(endian, packing, InError).init(in_stream);
406
407 //@TODO: isInf/isNan not currently implemented for f128.
408 try serializer.serialize(std.math.nan(f16));
409 try serializer.serialize(std.math.inf(f16));
410 try serializer.serialize(std.math.nan(f32));
411 try serializer.serialize(std.math.inf(f32));
412 try serializer.serialize(std.math.nan(f64));
413 try serializer.serialize(std.math.inf(f64));
414 //try serializer.serialize(std.math.nan(f128));
415 //try serializer.serialize(std.math.inf(f128));
416 const nan_check_f16 = try deserializer.deserialize(f16);
417 const inf_check_f16 = try deserializer.deserialize(f16);
418 const nan_check_f32 = try deserializer.deserialize(f32);
419 const inf_check_f32 = try deserializer.deserialize(f32);
420 const nan_check_f64 = try deserializer.deserialize(f64);
421 const inf_check_f64 = try deserializer.deserialize(f64);
422 //const nan_check_f128 = try deserializer.deserialize(f128);
423 //const inf_check_f128 = try deserializer.deserialize(f128);
424 expect(std.math.isNan(nan_check_f16));
425 expect(std.math.isInf(inf_check_f16));
426 expect(std.math.isNan(nan_check_f32));
427 expect(std.math.isInf(inf_check_f32));
428 expect(std.math.isNan(nan_check_f64));
429 expect(std.math.isInf(inf_check_f64));
430 //expect(std.math.isNan(nan_check_f128));
431 //expect(std.math.isInf(inf_check_f128));
432}
433
434test "Serializer/Deserializer Int: Inf/NaN" {
435 try testIntSerializerDeserializerInfNaN(.Big, .Byte);
436 try testIntSerializerDeserializerInfNaN(.Little, .Byte);
437 try testIntSerializerDeserializerInfNaN(.Big, .Bit);
438 try testIntSerializerDeserializerInfNaN(.Little, .Bit);
439}
440
441fn testAlternateSerializer(self: var, serializer: var) !void {
442 try serializer.serialize(self.f_f16);
443}
444
445fn testSerializerDeserializer(comptime endian: builtin.Endian, comptime packing: io.Packing) !void {
446 const ColorType = enum(u4) {
447 RGB8 = 1,
448 RA16 = 2,
449 R32 = 3,
450 };
451
452 const TagAlign = union(enum(u32)) {
453 A: u8,
454 B: u8,
455 C: u8,
456 };
457
458 const Color = union(ColorType) {
459 RGB8: struct {
460 r: u8,
461 g: u8,
462 b: u8,
463 a: u8,
464 },
465 RA16: struct {
466 r: u16,
467 a: u16,
468 },
469 R32: u32,
470 };
471
472 const PackedStruct = packed struct {
473 f_i3: i3,
474 f_u2: u2,
475 };
476
477 //to test custom serialization
478 const Custom = struct {
479 f_f16: f16,
480 f_unused_u32: u32,
481
482 pub fn deserialize(self: *@This(), deserializer: var) !void {
483 try deserializer.deserializeInto(&self.f_f16);
484 self.f_unused_u32 = 47;
485 }
486
487 pub const serialize = testAlternateSerializer;
488 };
489
490 const MyStruct = struct {
491 f_i3: i3,
492 f_u8: u8,
493 f_tag_align: TagAlign,
494 f_u24: u24,
495 f_i19: i19,
496 f_void: void,
497 f_f32: f32,
498 f_f128: f128,
499 f_packed_0: PackedStruct,
500 f_i7arr: [10]i7,
501 f_of64n: ?f64,
502 f_of64v: ?f64,
503 f_color_type: ColorType,
504 f_packed_1: PackedStruct,
505 f_custom: Custom,
506 f_color: Color,
507 };
508
509 const my_inst = MyStruct{
510 .f_i3 = -1,
511 .f_u8 = 8,
512 .f_tag_align = TagAlign{ .B = 148 },
513 .f_u24 = 24,
514 .f_i19 = 19,
515 .f_void = {},
516 .f_f32 = 32.32,
517 .f_f128 = 128.128,
518 .f_packed_0 = PackedStruct{ .f_i3 = -1, .f_u2 = 2 },
519 .f_i7arr = [10]i7{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
520 .f_of64n = null,
521 .f_of64v = 64.64,
522 .f_color_type = ColorType.R32,
523 .f_packed_1 = PackedStruct{ .f_i3 = 1, .f_u2 = 1 },
524 .f_custom = Custom{ .f_f16 = 38.63, .f_unused_u32 = 47 },
525 .f_color = Color{ .R32 = 123822 },
526 };
527
528 var data_mem: [@sizeOf(MyStruct)]u8 = undefined;
529 var out = io.SliceOutStream.init(data_mem[0..]);
530 const OutError = io.SliceOutStream.Error;
531 var out_stream = &out.stream;
532 var serializer = io.Serializer(endian, packing, OutError).init(out_stream);
533
534 var in = io.SliceInStream.init(data_mem[0..]);
535 const InError = io.SliceInStream.Error;
536 var in_stream = &in.stream;
537 var deserializer = io.Deserializer(endian, packing, InError).init(in_stream);
538
539 try serializer.serialize(my_inst);
540
541 const my_copy = try deserializer.deserialize(MyStruct);
542 expect(meta.eql(my_copy, my_inst));
543}
544
545test "Serializer/Deserializer generic" {
546 try testSerializerDeserializer(builtin.Endian.Big, .Byte);
547 try testSerializerDeserializer(builtin.Endian.Little, .Byte);
548 try testSerializerDeserializer(builtin.Endian.Big, .Bit);
549 try testSerializerDeserializer(builtin.Endian.Little, .Bit);
550}
551
552fn testBadData(comptime endian: builtin.Endian, comptime packing: io.Packing) !void {
553 const E = enum(u14) {
554 One = 1,
555 Two = 2,
556 };
557
558 const A = struct {
559 e: E,
560 };
561
562 const C = union(E) {
563 One: u14,
564 Two: f16,
565 };
566
567 var data_mem: [4]u8 = undefined;
568 var out = io.SliceOutStream.init(data_mem[0..]);
569 const OutError = io.SliceOutStream.Error;
570 var out_stream = &out.stream;
571 var serializer = io.Serializer(endian, packing, OutError).init(out_stream);
572
573 var in = io.SliceInStream.init(data_mem[0..]);
574 const InError = io.SliceInStream.Error;
575 var in_stream = &in.stream;
576 var deserializer = io.Deserializer(endian, packing, InError).init(in_stream);
577
578 try serializer.serialize(u14(3));
579 expectError(error.InvalidEnumTag, deserializer.deserialize(A));
580 out.pos = 0;
581 try serializer.serialize(u14(3));
582 try serializer.serialize(u14(88));
583 expectError(error.InvalidEnumTag, deserializer.deserialize(C));
584}
585
586test "Deserializer bad data" {
587 try testBadData(.Big, .Byte);
588 try testBadData(.Little, .Byte);
589 try testBadData(.Big, .Bit);
590 try testBadData(.Little, .Bit);
591}