| ... | @@ -159,6 +159,50 @@ pub fn writeILEB128Mem(ptr: []u8, int_value: anytype) !usize { | ... | @@ -159,6 +159,50 @@ pub fn writeILEB128Mem(ptr: []u8, int_value: anytype) !usize { |
| 159 | return buf.pos; | 159 | return buf.pos; |
| 160 | } | 160 | } |
| 161 | | 161 | |
| | 162 | /// This is an "advanced" function. It allows one to use a fixed amount of memory to store a |
| | 163 | /// ULEB128. This defeats the entire purpose of using this data encoding; it will no longer use |
| | 164 | /// fewer bytes to store smaller numbers. The advantage of using a fixed width is that it makes |
| | 165 | /// fields have a predictable size and so depending on the use case this tradeoff can be worthwhile. |
| | 166 | /// An example use case of this is in emitting DWARF info where one wants to make a ULEB128 field |
| | 167 | /// "relocatable", meaning that it becomes possible to later go back and patch the number to be a |
| | 168 | /// different value without shifting all the following code. |
| | 169 | pub fn writeUnsignedFixed(comptime l: usize, ptr: *[l]u8, int: std.meta.Int(false, l * 7)) void { |
| | 170 | const T = @TypeOf(int); |
| | 171 | const U = if (T.bit_count < 8) u8 else T; |
| | 172 | var value = @intCast(U, int); |
| | 173 | |
| | 174 | comptime var i = 0; |
| | 175 | inline while (i < (l - 1)) : (i += 1) { |
| | 176 | const byte = @truncate(u8, value) | 0b1000_0000; |
| | 177 | value >>= 7; |
| | 178 | ptr[i] = byte; |
| | 179 | } |
| | 180 | ptr[i] = @truncate(u8, value); |
| | 181 | } |
| | 182 | |
| | 183 | test "writeUnsignedFixed" { |
| | 184 | { |
| | 185 | var buf: [4]u8 = undefined; |
| | 186 | writeUnsignedFixed(4, &buf, 0); |
| | 187 | testing.expect((try test_read_uleb128(u64, &buf)) == 0); |
| | 188 | } |
| | 189 | { |
| | 190 | var buf: [4]u8 = undefined; |
| | 191 | writeUnsignedFixed(4, &buf, 1); |
| | 192 | testing.expect((try test_read_uleb128(u64, &buf)) == 1); |
| | 193 | } |
| | 194 | { |
| | 195 | var buf: [4]u8 = undefined; |
| | 196 | writeUnsignedFixed(4, &buf, 1000); |
| | 197 | testing.expect((try test_read_uleb128(u64, &buf)) == 1000); |
| | 198 | } |
| | 199 | { |
| | 200 | var buf: [4]u8 = undefined; |
| | 201 | writeUnsignedFixed(4, &buf, 10000000); |
| | 202 | testing.expect((try test_read_uleb128(u64, &buf)) == 10000000); |
| | 203 | } |
| | 204 | } |
| | 205 | |
| 162 | // tests | 206 | // tests |
| 163 | fn test_read_stream_ileb128(comptime T: type, encoded: []const u8) !T { | 207 | fn test_read_stream_ileb128(comptime T: type, encoded: []const u8) !T { |
| 164 | var reader = std.io.fixedBufferStream(encoded); | 208 | var reader = std.io.fixedBufferStream(encoded); |