authorgravatar for tgschultz@gmail.comtgschultz <tgschultz@gmail.com> 2019-05-04 13:31:53+00:00
committergravatar for tgschultz@gmail.comtgschultz <tgschultz@gmail.com> 2019-05-04 13:31:53+00:00
log27ed525e03879502a983bc4782625e9c081c1c4d
tree7abaf49e78e4e9ff03babe62897fd3b0c81e5901
parent4dfd1f54db66cec2e02e245397b1c5df5051656c

zig fmt


1 files changed, 153 insertions(+), 217 deletions(-)

std/packed_int_array.zig+153-217
......@@ -3,141 +3,128 @@ const builtin = @import("builtin");
33const debug = std.debug;
44const testing = std.testing;
55
6pub fn PackedIntIo(comptime Int: type) type
7{
6pub fn PackedIntIo(comptime Int: type) type {
87 //The general technique employed here is to cast bytes in the array to a container
98 // integer (having bits % 8 == 0) large enough to contain the number of bits we want,
109 // then we can retrieve or store the new value with a relative minimum of masking
1110 // and shifting. In this worst case, this means that we'll need an integer that's
1211 // actually 1 byte larger than the minimum required to store the bits, because it
13 // is possible that the bits start at the end of the first byte, continue through
12 // is possible that the bits start at the end of the first byte, continue through
1413 // zero or more, then end in the beginning of the last. But, if we try to access
1514 // a value in the very last byte of memory with that integer size, that extra byte
1615 // will be out of bounds. Depending on the circumstances of the memory, that might
1716 // mean the OS fatally kills the program. Thus, we use a larger container (MaxIo)
1817 // most of the time, but a smaller container (MinIo) when touching the last byte
1918 // of the memory.
20
2119 const int_bits = comptime std.meta.bitCount(Int);
22
20
2321 //in the best case, this is the number of bytes we need to touch
2422 // to read or write a value, as bits
2523 const min_io_bits = ((int_bits + 7) / 8) * 8;
26
24
2725 //in the worst case, this is the number of bytes we need to touch
2826 // to read or write a value, as bits
29 const max_io_bits = switch(int_bits)
30 {
27 const max_io_bits = switch (int_bits) {
3128 0 => 0,
3229 1 => 8,
3330 2...9 => 16,
3431 10...65535 => ((int_bits / 8) + 2) * 8,
3532 else => unreachable,
3633 };
37
34
3835 //we bitcast the desired Int type to an unsigned version of itself
3936 // to avoid issues with shifting signed ints.
4037 const UnInt = @IntType(false, int_bits);
41
38
4239 //The maximum container int type
4340 const MinIo = @IntType(false, min_io_bits);
44
41
4542 //The minimum container int type
4643 const MaxIo = @IntType(false, max_io_bits);
47
48 return struct
49 {
50 pub fn get(bytes: []const u8, index: usize, bit_offset: u7) Int
51 {
52 if(int_bits == 0) return 0;
53
44
45 return struct {
46 pub fn get(bytes: []const u8, index: usize, bit_offset: u7) Int {
47 if (int_bits == 0) return 0;
48
5449 const bit_index = (index * int_bits) + bit_offset;
5550 const max_end_byte = (bit_index + max_io_bits) / 8;
56
51
5752 //Using the larger container size will potentially read out of bounds
58 if(max_end_byte > bytes.len) return getBits(bytes, MinIo, bit_index);
53 if (max_end_byte > bytes.len) return getBits(bytes, MinIo, bit_index);
5954 return getBits(bytes, MaxIo, bit_index);
6055 }
61
62 fn getBits(bytes: []const u8, comptime Container: type, bit_index: usize) Int
63 {
56
57 fn getBits(bytes: []const u8, comptime Container: type, bit_index: usize) Int {
6458 const container_bits = comptime std.meta.bitCount(Container);
6559 const Shift = std.math.Log2Int(Container);
66
60
6761 const start_byte = bit_index / 8;
6862 const head_keep_bits = bit_index - (start_byte * 8);
6963 const tail_keep_bits = container_bits - (int_bits + head_keep_bits);
70
64
7165 //read bytes as container
72 const value_ptr = @ptrCast(*const align(1) Container, &bytes[start_byte]);
66 const value_ptr = @ptrCast(*align(1) const Container, &bytes[start_byte]);
7367 var value = value_ptr.*;
7468
75 switch(builtin.endian)
76 {
77 .Big =>
78 {
69 switch (builtin.endian) {
70 .Big => {
7971 value <<= @intCast(Shift, head_keep_bits);
8072 value >>= @intCast(Shift, head_keep_bits);
8173 value >>= @intCast(Shift, tail_keep_bits);
8274 },
83 .Little =>
84 {
75 .Little => {
8576 value <<= @intCast(Shift, tail_keep_bits);
8677 value >>= @intCast(Shift, tail_keep_bits);
8778 value >>= @intCast(Shift, head_keep_bits);
8879 },
8980 }
90
81
9182 return @bitCast(Int, @truncate(UnInt, value));
9283 }
93
94 pub fn set(bytes: []u8, index: usize, bit_offset: u3, int: Int) void
95 {
96 if(int_bits == 0) return;
84
85 pub fn set(bytes: []u8, index: usize, bit_offset: u3, int: Int) void {
86 if (int_bits == 0) return;
9787
9888 const bit_index = (index * int_bits) + bit_offset;
9989 const max_end_byte = (bit_index + max_io_bits) / 8;
100
90
10191 //Using the larger container size will potentially write out of bounds
102 if(max_end_byte > bytes.len) return setBits(bytes, MinIo, bit_index, int);
92 if (max_end_byte > bytes.len) return setBits(bytes, MinIo, bit_index, int);
10393 setBits(bytes, MaxIo, bit_index, int);
10494 }
105
106 fn setBits(bytes: []u8, comptime Container: type, bit_index: usize, int: Int) void
107 {
95
96 fn setBits(bytes: []u8, comptime Container: type, bit_index: usize, int: Int) void {
10897 const container_bits = comptime std.meta.bitCount(Container);
10998 const Shift = std.math.Log2Int(Container);
110
99
111100 const start_byte = bit_index / 8;
112101 const head_keep_bits = bit_index - (start_byte * 8);
113102 const tail_keep_bits = container_bits - (int_bits + head_keep_bits);
114 const keep_shift = switch(builtin.endian)
115 {
103 const keep_shift = switch (builtin.endian) {
116104 .Big => @intCast(Shift, tail_keep_bits),
117105 .Little => @intCast(Shift, head_keep_bits),
118106 };
119
107
120108 //position the bits where they need to be in the container
121109 const value = @intCast(Container, @bitCast(UnInt, int)) << keep_shift;
122
110
123111 //read existing bytes
124112 const target_ptr = @ptrCast(*align(1) Container, &bytes[start_byte]);
125113 var target = target_ptr.*;
126
114
127115 //zero the bits we want to replace in the existing bytes
128116 const inv_mask = @intCast(Container, std.math.maxInt(UnInt)) << keep_shift;
129117 const mask = ~inv_mask;
130118 target &= mask;
131
119
132120 //merge the new value
133121 target |= value;
134
122
135123 //save it back
136124 target_ptr.* = target;
137125 }
138
139 fn slice(bytes: []u8, bit_offset: u3, start: usize, end: usize) PackedIntSlice(Int)
140 {
126
127 fn slice(bytes: []u8, bit_offset: u3, start: usize, end: usize) PackedIntSlice(Int) {
141128 debug.assert(end >= start);
142129
143130 const length = end - start;
......@@ -145,25 +132,23 @@ pub fn PackedIntIo(comptime Int: type) type
145132 const start_byte = bit_index / 8;
146133 const end_byte = (bit_index + (length * int_bits) + 7) / 8;
147134 const new_bytes = bytes[start_byte..end_byte];
148
149 if(length == 0) return PackedIntSlice(Int).init(new_bytes[0..0], 0);
150
135
136 if (length == 0) return PackedIntSlice(Int).init(new_bytes[0..0], 0);
137
151138 var new_slice = PackedIntSlice(Int).init(new_bytes, length);
152139 new_slice.bit_offset = @intCast(u3, (bit_index - (start_byte * 8)));
153140 return new_slice;
154141 }
155
156 fn sliceCast(bytes: []u8, comptime NewInt: type, bit_offset: u3, old_len: usize)
157 PackedIntSlice(NewInt)
158 {
142
143 fn sliceCast(bytes: []u8, comptime NewInt: type, bit_offset: u3, old_len: usize) PackedIntSlice(NewInt) {
159144 const new_int_bits = comptime std.meta.bitCount(NewInt);
160145 const New = PackedIntSlice(NewInt);
161
146
162147 const total_bits = (old_len * int_bits);
163148 const new_int_count = total_bits / new_int_bits;
164
149
165150 debug.assert(total_bits == new_int_count * new_int_bits);
166
151
167152 var new = New.init(bytes, new_int_count);
168153 new.bit_offset = bit_offset;
169154 return new;
......@@ -174,152 +159,132 @@ pub fn PackedIntIo(comptime Int: type) type
174159///Creates a bit-packed array of integers of type Int. Bits
175160/// are packed using native endianess and without storing any meta
176161/// data. PackedIntArray(i3, 8) will occupy exactly 3 bytes of memory.
177pub fn PackedIntArray(comptime Int: type, comptime int_count: usize) type
178{
162pub fn PackedIntArray(comptime Int: type, comptime int_count: usize) type {
179163 const int_bits = comptime std.meta.bitCount(Int);
180164 const total_bits = int_bits * int_count;
181165 const total_bytes = (total_bits + 7) / 8;
182
166
183167 const Io = PackedIntIo(Int);
184
185 return struct
186 {
168
169 return struct {
187170 const Self = @This();
188
171
189172 bytes: [total_bytes]u8,
190
173
191174 ///Returns the number of elements in the packed array
192 pub fn len(self: Self) usize
193 {
175 pub fn len(self: Self) usize {
194176 return int_count;
195177 }
196
178
197179 ///Initialize a packed array using an unpacked array
198180 /// or, more likely, an array literal.
199 pub fn init(ints: [int_count]Int) Self
200 {
181 pub fn init(ints: [int_count]Int) Self {
201182 var self = Self(undefined);
202 for(ints) |int, i| self.set(i, int);
183 for (ints) |int, i| self.set(i, int);
203184 return self;
204185 }
205
186
206187 ///Return the Int stored at index
207 pub fn get(self: Self, index: usize) Int
208 {
188 pub fn get(self: Self, index: usize) Int {
209189 debug.assert(index < int_count);
210190 return Io.get(self.bytes, index, 0);
211191 }
212
192
213193 ///Copy int into the array at index
214 pub fn set(self: *Self, index: usize, int: Int) void
215 {
194 pub fn set(self: *Self, index: usize, int: Int) void {
216195 debug.assert(index < int_count);
217196 return Io.set(&self.bytes, index, 0, int);
218197 }
219
198
220199 ///Create a PackedIntSlice of the array from given start to given end
221 pub fn slice(self: *Self, start: usize, end: usize) PackedIntSlice(Int)
222 {
200 pub fn slice(self: *Self, start: usize, end: usize) PackedIntSlice(Int) {
223201 debug.assert(start < int_count);
224202 debug.assert(end <= int_count);
225203 return Io.slice(&self.bytes, 0, start, end);
226204 }
227
205
228206 ///Create a PackedIntSlice of the array using NewInt as the bit width integer.
229207 /// NewInt's bit width must fit evenly within the array's Int's total bits.
230 pub fn sliceCast(self: *Self, comptime NewInt: type) PackedIntSlice(NewInt)
231 {
208 pub fn sliceCast(self: *Self, comptime NewInt: type) PackedIntSlice(NewInt) {
232209 return Io.sliceCast(&self.bytes, NewInt, 0, int_count);
233210 }
234211 };
235212}
236213
237///Uses a slice as a bit-packed block of int_count integers of type Int.
214///Uses a slice as a bit-packed block of int_count integers of type Int.
238215/// Bits are packed using native endianess and without storing any meta
239216/// data.
240pub fn PackedIntSlice(comptime Int: type) type
241{
217pub fn PackedIntSlice(comptime Int: type) type {
242218 const int_bits = comptime std.meta.bitCount(Int);
243219 const Io = PackedIntIo(Int);
244
245 return struct
246 {
220
221 return struct {
247222 const Self = @This();
248
223
249224 bytes: []u8,
250225 int_count: usize,
251226 bit_offset: u3,
252
227
253228 ///Returns the number of elements in the packed slice
254 pub fn len(self: Self) usize
255 {
229 pub fn len(self: Self) usize {
256230 return self.int_count;
257231 }
258
232
259233 ///Calculates the number of bytes required to store a desired count
260234 /// of Ints
261 pub fn bytesRequired(int_count: usize) usize
262 {
235 pub fn bytesRequired(int_count: usize) usize {
263236 const total_bits = int_bits * int_count;
264237 const total_bytes = (total_bits + 7) / 8;
265238 return total_bytes;
266239 }
267
240
268241 ///Initialize a packed slice using the memory at bytes, with int_count
269242 /// elements. bytes must be large enough to accomodate the requested
270243 /// count.
271 pub fn init(bytes: []u8, int_count: usize) Self
272 {
244 pub fn init(bytes: []u8, int_count: usize) Self {
273245 debug.assert(bytes.len >= bytesRequired(int_count));
274
275 return Self
276 {
246
247 return Self{
277248 .bytes = bytes,
278249 .int_count = int_count,
279250 .bit_offset = 0,
280251 };
281252 }
282
253
283254 ///Return the Int stored at index
284 pub fn get(self: Self, index: usize) Int
285 {
255 pub fn get(self: Self, index: usize) Int {
286256 debug.assert(index < self.int_count);
287257 return Io.get(self.bytes, index, self.bit_offset);
288258 }
289
259
290260 ///Copy int into the array at index
291 pub fn set(self: *Self, index: usize, int: Int) void
292 {
261 pub fn set(self: *Self, index: usize, int: Int) void {
293262 debug.assert(index < self.int_count);
294263 return Io.set(self.bytes, index, self.bit_offset, int);
295264 }
296
265
297266 ///Create a PackedIntSlice of this slice from given start to given end
298 pub fn slice(self: Self, start: usize, end: usize) PackedIntSlice(Int)
299 {
267 pub fn slice(self: Self, start: usize, end: usize) PackedIntSlice(Int) {
300268 debug.assert(start < self.int_count);
301269 debug.assert(end <= self.int_count);
302270 return Io.slice(self.bytes, self.bit_offset, start, end);
303271 }
304
272
305273 ///Create a PackedIntSlice of this slice using NewInt as the bit width integer.
306274 /// NewInt's bit width must fit evenly within this slice's Int's total bits.
307 pub fn sliceCast(self: Self, comptime NewInt: type) PackedIntSlice(NewInt)
308 {
275 pub fn sliceCast(self: Self, comptime NewInt: type) PackedIntSlice(NewInt) {
309276 return Io.sliceCast(self.bytes, NewInt, self.bit_offset, self.int_count);
310277 }
311278 };
312279}
313280
314test "PackedIntArray"
315{
281test "PackedIntArray" {
316282 @setEvalBranchQuota(10000);
317283 const max_bits = 256;
318284 const int_count = 19;
319
285
320286 comptime var bits = 0;
321 inline while(bits <= 256):(bits += 1)
322 {
287 inline while (bits <= 256) : (bits += 1) {
323288 //alternate unsigned and signed
324289 const even = bits % 2 == 0;
325290 const I = @IntType(even, bits);
......@@ -327,100 +292,90 @@ test "PackedIntArray"
327292 const PackedArray = PackedIntArray(I, int_count);
328293 const expected_bytes = ((bits * int_count) + 7) / 8;
329294 testing.expect(@sizeOf(PackedArray) == expected_bytes);
330
295
331296 var data = PackedArray(undefined);
332
297
333298 //write values, counting up
334299 var i = usize(0);
335300 var count = I(0);
336 while(i < data.len()):(i += 1)
337 {
301 while (i < data.len()) : (i += 1) {
338302 data.set(i, count);
339 if(bits > 0) count +%= 1;
303 if (bits > 0) count +%= 1;
340304 }
341
305
342306 //read and verify values
343307 i = 0;
344308 count = 0;
345 while(i < data.len()):(i += 1)
346 {
309 while (i < data.len()) : (i += 1) {
347310 const val = data.get(i);
348311 testing.expect(val == count);
349 if(bits > 0) count +%= 1;
312 if (bits > 0) count +%= 1;
350313 }
351314 }
352315}
353316
354test "PackedIntArray init"
355{
317test "PackedIntArray init" {
356318 const PackedArray = PackedIntArray(u3, 8);
357 var packed_array = PackedArray.init([]u3{0,1,2,3,4,5,6,7});
319 var packed_array = PackedArray.init([]u3{ 0, 1, 2, 3, 4, 5, 6, 7 });
358320 var i = usize(0);
359 while(i < packed_array.len()):(i += 1) testing.expect(packed_array.get(i) == i);
321 while (i < packed_array.len()) : (i += 1) testing.expect(packed_array.get(i) == i);
360322}
361323
362test "PackedIntSlice"
363{
324test "PackedIntSlice" {
364325 @setEvalBranchQuota(10000);
365326 const max_bits = 256;
366327 const int_count = 19;
367328 const total_bits = max_bits * int_count;
368329 const total_bytes = (total_bits + 7) / 8;
369
330
370331 var buffer: [total_bytes]u8 = undefined;
371
332
372333 comptime var bits = 0;
373 inline while(bits <= 256):(bits += 1)
374 {
334 inline while (bits <= 256) : (bits += 1) {
375335 //alternate unsigned and signed
376336 const even = bits % 2 == 0;
377337 const I = @IntType(even, bits);
378338 const P = PackedIntSlice(I);
379
339
380340 var data = P.init(&buffer, int_count);
381
341
382342 //write values, counting up
383343 var i = usize(0);
384344 var count = I(0);
385 while(i < data.len()):(i += 1)
386 {
345 while (i < data.len()) : (i += 1) {
387346 data.set(i, count);
388 if(bits > 0) count +%= 1;
347 if (bits > 0) count +%= 1;
389348 }
390
349
391350 //read and verify values
392351 i = 0;
393352 count = 0;
394 while(i < data.len()):(i += 1)
395 {
353 while (i < data.len()) : (i += 1) {
396354 const val = data.get(i);
397355 testing.expect(val == count);
398 if(bits > 0) count +%= 1;
356 if (bits > 0) count +%= 1;
399357 }
400358 }
401359}
402360
403test "PackedIntSlice of PackedInt(Array/Slice)"
404{
361test "PackedIntSlice of PackedInt(Array/Slice)" {
405362 const max_bits = 16;
406363 const int_count = 19;
407
364
408365 comptime var bits = 0;
409 inline while(bits <= max_bits):(bits += 1)
410 {
366 inline while (bits <= max_bits) : (bits += 1) {
411367 const Int = @IntType(false, bits);
412
368
413369 const PackedArray = PackedIntArray(Int, int_count);
414370 var packed_array = PackedArray(undefined);
415
371
416372 const limit = (1 << bits);
417
373
418374 var i = usize(0);
419 while(i < packed_array.len()):(i += 1)
420 {
375 while (i < packed_array.len()) : (i += 1) {
421376 packed_array.set(i, @intCast(Int, i % limit));
422377 }
423
378
424379 //slice of array
425380 var packed_slice = packed_array.slice(2, 5);
426381 testing.expect(packed_slice.len() == 3);
......@@ -432,10 +387,10 @@ test "PackedIntSlice of PackedInt(Array/Slice)"
432387 testing.expect(packed_slice.get(2) == 4 % limit);
433388 packed_slice.set(1, 7 % limit);
434389 testing.expect(packed_slice.get(1) == 7 % limit);
435
390
436391 //write through slice
437392 testing.expect(packed_array.get(3) == 7 % limit);
438
393
439394 //slice of a slice
440395 const packed_slice_two = packed_slice.slice(0, 3);
441396 testing.expect(packed_slice_two.len() == 3);
......@@ -444,7 +399,7 @@ test "PackedIntSlice of PackedInt(Array/Slice)"
444399 testing.expect(packed_slice_two.bytes.len == ps2_expected_bytes);
445400 testing.expect(packed_slice_two.get(1) == 7 % limit);
446401 testing.expect(packed_slice_two.get(2) == 4 % limit);
447
402
448403 //size one case
449404 const packed_slice_three = packed_slice_two.slice(1, 2);
450405 testing.expect(packed_slice_three.len() == 1);
......@@ -452,12 +407,12 @@ test "PackedIntSlice of PackedInt(Array/Slice)"
452407 const ps3_expected_bytes = (ps3_bit_count + 7) / 8;
453408 testing.expect(packed_slice_three.bytes.len == ps3_expected_bytes);
454409 testing.expect(packed_slice_three.get(0) == 7 % limit);
455
410
456411 //empty slice case
457412 const packed_slice_empty = packed_slice.slice(0, 0);
458413 testing.expect(packed_slice_empty.len() == 0);
459414 testing.expect(packed_slice_empty.bytes.len == 0);
460
415
461416 //slicing at byte boundaries
462417 const packed_slice_edge = packed_array.slice(8, 16);
463418 testing.expect(packed_slice_edge.len() == 8);
......@@ -466,84 +421,70 @@ test "PackedIntSlice of PackedInt(Array/Slice)"
466421 testing.expect(packed_slice_edge.bytes.len == pse_expected_bytes);
467422 testing.expect(packed_slice_edge.bit_offset == 0);
468423 }
469
470424}
471425
472test "PackedIntSlice accumulating bit offsets"
473{
426test "PackedIntSlice accumulating bit offsets" {
474427 //bit_offset is u3, so standard debugging asserts should catch
475428 // anything
476429 {
477430 const PackedArray = PackedIntArray(u3, 16);
478431 var packed_array = PackedArray(undefined);
479
432
480433 var packed_slice = packed_array.slice(0, packed_array.len());
481434 var i = usize(0);
482 while(i < packed_array.len() - 1):(i += 1)
483 {
484
435 while (i < packed_array.len() - 1) : (i += 1) {
485436 packed_slice = packed_slice.slice(1, packed_slice.len());
486437 }
487438 }
488439 {
489440 const PackedArray = PackedIntArray(u11, 88);
490441 var packed_array = PackedArray(undefined);
491
442
492443 var packed_slice = packed_array.slice(0, packed_array.len());
493444 var i = usize(0);
494 while(i < packed_array.len() - 1):(i += 1)
495 {
445 while (i < packed_array.len() - 1) : (i += 1) {
496446 packed_slice = packed_slice.slice(1, packed_slice.len());
497447 }
498448 }
499
500449}
501450
502451//@NOTE: As I do not have a big endian system to test this on,
503452// big endian values were not tested
504test "PackedInt(Array/Slice) sliceCast"
505{
453test "PackedInt(Array/Slice) sliceCast" {
506454 const PackedArray = PackedIntArray(u1, 16);
507 var packed_array = PackedArray.init([]u1{0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1});
455 var packed_array = PackedArray.init([]u1{ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 });
508456 const packed_slice_cast_2 = packed_array.sliceCast(u2);
509457 const packed_slice_cast_4 = packed_slice_cast_2.sliceCast(u4);
510458 var packed_slice_cast_9 = packed_array.slice(0, (packed_array.len() / 9) * 9).sliceCast(u9);
511459 const packed_slice_cast_3 = packed_slice_cast_9.sliceCast(u3);
512
460
513461 var i = usize(0);
514 while(i < packed_slice_cast_2.len()):(i += 1)
515 {
516 const val = switch(builtin.endian)
517 {
462 while (i < packed_slice_cast_2.len()) : (i += 1) {
463 const val = switch (builtin.endian) {
518464 .Big => 0b01,
519465 .Little => 0b10,
520466 };
521467 testing.expect(packed_slice_cast_2.get(i) == val);
522468 }
523469 i = 0;
524 while(i < packed_slice_cast_4.len()):(i += 1)
525 {
526 const val = switch(builtin.endian)
527 {
470 while (i < packed_slice_cast_4.len()) : (i += 1) {
471 const val = switch (builtin.endian) {
528472 .Big => 0b0101,
529473 .Little => 0b1010,
530474 };
531475 testing.expect(packed_slice_cast_4.get(i) == val);
532476 }
533477 i = 0;
534 while(i < packed_slice_cast_9.len()):(i += 1)
535 {
478 while (i < packed_slice_cast_9.len()) : (i += 1) {
536479 const val = 0b010101010;
537480 testing.expect(packed_slice_cast_9.get(i) == val);
538481 packed_slice_cast_9.set(i, 0b111000111);
539482 }
540483 i = 0;
541 while(i < packed_slice_cast_3.len()):(i += 1)
542 {
543 const val = switch(builtin.endian)
544 {
545 .Big => if(i % 2 == 0) u3(0b111) else u3(0b000),
546 .Little => if(i % 2 == 0) u3(0b111) else u3(0b000),
484 while (i < packed_slice_cast_3.len()) : (i += 1) {
485 const val = switch (builtin.endian) {
486 .Big => if (i % 2 == 0) u3(0b111) else u3(0b000),
487 .Little => if (i % 2 == 0) u3(0b111) else u3(0b000),
547488 };
548489 testing.expect(packed_slice_cast_3.get(i) == val);
549490 }
......@@ -558,44 +499,39 @@ test "PackedInt(Array/Slice) sliceCast"
558499// and reading the last element. The assumption is that the page
559500// after this one is not mapped and will cause a segfault if we
560501// don't account for the bounds.
561test "PackedIntArray at end of available memory"
562{
563 switch(builtin.os)
564 {
502test "PackedIntArray at end of available memory" {
503 switch (builtin.os) {
565504 .linux, .macosx, .ios, .freebsd, .netbsd => {},
566505 else => return,
567506 }
568507 const PackedArray = PackedIntArray(u3, 8);
569
570 const Padded = struct
571 {
508
509 const Padded = struct {
572510 _: [std.os.page_size - @sizeOf(PackedArray)]u8,
573511 p: PackedArray,
574512 };
575
513
576514 var da = std.heap.DirectAllocator.init();
577515 const allocator = &da.allocator;
578
516
579517 var pad = try allocator.create(Padded);
580518 defer allocator.destroy(pad);
581519 pad.p.set(7, std.math.maxInt(u3));
582520}
583521
584test "PackedIntSlice at end of available memory"
585{
586 switch(builtin.os)
587 {
522test "PackedIntSlice at end of available memory" {
523 switch (builtin.os) {
588524 .linux, .macosx, .ios, .freebsd, .netbsd => {},
589525 else => return,
590526 }
591527 const PackedSlice = PackedIntSlice(u11);
592
528
593529 var da = std.heap.DirectAllocator.init();
594530 const allocator = &da.allocator;
595
531
596532 var page = try allocator.alloc(u8, std.os.page_size);
597533 defer allocator.free(page);
598
599 var p = PackedSlice.init(page[std.os.page_size - 2..], 1);
534
535 var p = PackedSlice.init(page[std.os.page_size - 2 ..], 1);
600536 p.set(0, std.math.maxInt(u11));
601537}