diff options
author | Rutger Broekhoff | 2021-05-22 12:54:41 +0200 |
---|---|---|
committer | Rutger Broekhoff | 2021-05-22 12:54:54 +0200 |
commit | 6bcacd5e07d715930d43dbfb9ac5cb3d723b4df8 (patch) | |
tree | f8b81eb3218ba974c2a64579744267369d683772 | |
parent | d33099ba17c6493addc1b320890cf8a98ec0e21d (diff) | |
download | zig-nkeys-6bcacd5e07d715930d43dbfb9ac5cb3d723b4df8.tar.gz zig-nkeys-6bcacd5e07d715930d43dbfb9ac5cb3d723b4df8.zip |
Add comments to the Base32 encoder code
-rw-r--r-- | src/base32.zig | 66 |
1 files changed, 53 insertions, 13 deletions
diff --git a/src/base32.zig b/src/base32.zig index 149e5f0..fa58327 100644 --- a/src/base32.zig +++ b/src/base32.zig | |||
@@ -29,8 +29,10 @@ pub const Encoder = struct { | |||
29 | return dest[0..out_len]; | 29 | return dest[0..out_len]; |
30 | } | 30 | } |
31 | 31 | ||
32 | fn n_front_bits(self: *const Self) u3 { | 32 | // Calculates the amount of bits can be read from `self.buffer[self.index]`, |
33 | // bit_off n_front_bits | 33 | // with a maximum of 5 and an offset of `self.bit_off`. |
34 | fn frontBitsLen(self: *const Self) u3 { | ||
35 | // bit_off frontBitsLen | ||
34 | // 0 5 | 36 | // 0 5 |
35 | // 1 5 | 37 | // 1 5 |
36 | // 2 5 | 38 | // 2 5 |
@@ -42,8 +44,22 @@ pub const Encoder = struct { | |||
42 | return if (self.bit_off <= 3) 5 else 7 - self.bit_off + 1; | 44 | return if (self.bit_off <= 3) 5 else 7 - self.bit_off + 1; |
43 | } | 45 | } |
44 | 46 | ||
45 | fn front(self: *const Self, index: usize) u5 { | 47 | // Returns the bits of `self.buffer[self.index]`, read with an offset of `self.bit_off`, |
46 | // bit_off bits shl shr front | 48 | // aligned to the left of the 5-bit unsigned integer. |
49 | // Returns null if `self.index` is null. | ||
50 | // An illustration of its behaviour, with `self.buffer[self.index]` being 0b10010111: | ||
51 | // | `self.bit_off` | `frontBits` | | ||
52 | // |----------------|-------------| | ||
53 | // | 0 | 0b10010 | | ||
54 | // | 1 | 0b00101 | | ||
55 | // | 2 | 0b01011 | | ||
56 | // | 3 | 0b10111 | | ||
57 | // | 4 | 0b01110 | | ||
58 | // | 5 | 0b11100 | | ||
59 | // | 6 | 0b11000 | | ||
60 | // | 7 | 0b10000 | | ||
61 | fn frontBits(self: *const Self) ?u5 { | ||
62 | // bit_off bitmask shl shr frontBits | ||
47 | // 0 0b11111000 3 0b11111 | 63 | // 0 0b11111000 3 0b11111 |
48 | // 1 0b01111100 2 0b11111 | 64 | // 1 0b01111100 2 0b11111 |
49 | // 2 0b00111110 1 0b11111 | 65 | // 2 0b00111110 1 0b11111 |
@@ -52,33 +68,57 @@ pub const Encoder = struct { | |||
52 | // 5 0b00000111 2 0b11100 | 68 | // 5 0b00000111 2 0b11100 |
53 | // 6 0b00000011 3 0b11000 | 69 | // 6 0b00000011 3 0b11000 |
54 | // 7 0b00000001 4 0b10000 | 70 | // 7 0b00000001 4 0b10000 |
71 | const index = self.index orelse return null; | ||
55 | const bitmask = @as(u8, 0b11111000) >> self.bit_off; | 72 | const bitmask = @as(u8, 0b11111000) >> self.bit_off; |
56 | const bits = self.buffer[index] & bitmask; | 73 | const bits = self.buffer[index] & bitmask; |
57 | if (self.bit_off >= 4) return @truncate(u5, bits << (self.bit_off - 3)); | 74 | if (self.bit_off >= 4) return @truncate(u5, bits << (self.bit_off - 3)); |
58 | return @truncate(u5, bits >> (3 - self.bit_off)); | 75 | return @truncate(u5, bits >> (3 - self.bit_off)); |
59 | } | 76 | } |
60 | 77 | ||
61 | fn back(self: *const Self, index: usize, bits: u3) u5 { | 78 | // Returns the `self.buffer[self.index]` with the maximum amount specified by the `bits` parameter, |
62 | if (bits == 0) return 0; | 79 | // aligned to the right of the 5-bit unsigned integer. |
63 | return @truncate(u5, self.buffer[index] >> (7 - bits + 1)); | 80 | // Because a 5-bit integer is returned, not more than 5 bits can be read. `bits` must not be greater than 5. |
81 | // An illustration of its behaviour, with `self.buffer[self.index]` being 0b11101001: | ||
82 | // | `bits` | `backBits` | | ||
83 | // |--------|------------| | ||
84 | // | 0 | 0b00000 | | ||
85 | // | 1 | 0b10000 | | ||
86 | // | 2 | 0b11000 | | ||
87 | // | 3 | 0b11100 | | ||
88 | // | 4 | 0b11100 | | ||
89 | // | 5 | 0b11101 | | ||
90 | fn backBits(self: *const Self, bits: u3) u5 { | ||
91 | std.debug.assert(bits <= 5); | ||
92 | if (bits == 0 or self.index == null) return 0; | ||
93 | return @truncate(u5, self.buffer[self.index.?] >> (7 - bits + 1)); | ||
64 | } | 94 | } |
65 | 95 | ||
96 | // Returns the next 5-bit integer, read from `self.buffer`. | ||
66 | fn next_u5(self: *Self) ?u5 { | 97 | fn next_u5(self: *Self) ?u5 { |
67 | const front_index = self.index orelse return null; | 98 | // `self.buffer` is read 5 bits at a time by `next_u5`. |
68 | const num_front_bits = self.n_front_bits(); | 99 | // Because of the elements of `self.buffer` being 8 bits each, we need to |
69 | const front_bits = self.front(front_index); | 100 | // read from 2 bytes from `self.buffer` to return a whole u5. |
101 | // `front_bits` are the bits that come first, read from `self.buffer[self.index]`. | ||
102 | // `back_bits` are the bits that come last, read from `self.buffer[self.index + 1]`. | ||
103 | // `back_bits` is only used when we can't read 5 bits from `self.buffer[self.index]`. | ||
104 | |||
105 | const front_bits = self.frontBits() orelse return null; | ||
106 | const n_front_bits = self.frontBitsLen(); | ||
70 | 107 | ||
71 | var back_bits: u5 = 0; | 108 | var back_bits: u5 = 0; |
72 | if (self.bit_off >= 3) { | 109 | if (self.bit_off >= 3) { |
73 | self.bit_off -= 3; | 110 | // Next time we'll need to read from the next byte in `self.buffer`. |
74 | const new_index = front_index + 1; | 111 | // We may need to grab the back bits from that next byte for this call too (if it exist). |
112 | self.bit_off -= 3; // same as self.bit_off + 5 - 8 | ||
113 | const new_index = self.index.? + 1; | ||
75 | if (self.buffer.len > new_index) { | 114 | if (self.buffer.len > new_index) { |
76 | self.index = new_index; | 115 | self.index = new_index; |
77 | back_bits = self.back(new_index, 5 - num_front_bits); | 116 | back_bits = self.backBits(5 - n_front_bits); |
78 | } else { | 117 | } else { |
79 | self.index = null; | 118 | self.index = null; |
80 | } | 119 | } |
81 | } else { | 120 | } else { |
121 | // We need to read from the current byte in the next call to `next_u5` too. | ||
82 | self.bit_off += 5; | 122 | self.bit_off += 5; |
83 | } | 123 | } |
84 | 124 | ||