Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

ShakeLike

sha3.ShakeLike
fn ShakeLike(comptime security_level: u11, comptime default_delim: u8, comptime rounds: u5) type

File

lib/std/crypto/sha3.zig:108

Code

fn ShakeLike(comptime security_level: u11, comptime default_delim: u8, comptime rounds: u5) type {
    const f = 1600;
    const State = KeccakState(f, security_level * 2, rounds);

    return struct {
        const Self = @This();

        st: State,
        buf: [State.rate]u8 = undefined,
        offset: usize = 0,
        padded: bool = false,

        /// The recommended output length, in bytes.
        pub const digest_length = security_level / 8 * 2;
        /// The block length, or rate, in bytes.
        pub const block_length = State.rate;
        /// The delimiter can be overwritten in the options.
        pub const Options = struct { delim: u8 = default_delim };

        /// Initialize a SHAKE extensible hash function.
        pub fn init(options: Options) Self {
            return Self{ .st = .{ .delim = options.delim } };
        }

        /// Hash a slice of bytes.
        /// `out` can be any length.
        pub fn hash(bytes: []const u8, out: []u8, options: Options) void {
            var st = Self.init(options);
            st.update(bytes);
            st.squeeze(out);
        }

        /// Absorb a slice of bytes into the state.
        pub fn update(self: *Self, bytes: []const u8) void {
            self.st.absorb(bytes);
        }

        /// Squeeze a slice of bytes from the state.
        /// `out` can be any length, and the function can be called multiple times.
        pub fn squeeze(self: *Self, out_: []u8) void {
            if (!self.padded) {
                self.st.pad();
                self.padded = true;
            }
            var out = out_;
            if (self.offset > 0) {
                const left = self.buf.len - self.offset;
                if (left > 0) {
                    const n = @min(left, out.len);
                    @memcpy(out[0..n], self.buf[self.offset..][0..n]);
                    out = out[n..];
                    self.offset += n;
                    if (out.len == 0) {
                        return;
                    }
                }
            }
            const full_blocks = out[0 .. out.len - out.len % State.rate];
            if (full_blocks.len > 0) {
                self.st.squeeze(full_blocks);
                out = out[full_blocks.len..];
            }
            if (out.len > 0) {
                self.st.squeeze(self.buf[0..]);
                @memcpy(out[0..], self.buf[0..out.len]);
                self.offset = out.len;
            }
        }

        /// Return the hash of the absorbed bytes.
        /// `out` can be of any length, but the function must not be called multiple times (use `squeeze` for that purpose instead).
        pub fn final(self: *Self, out: []u8) void {
            self.squeeze(out);
            self.st.st.clear(0, State.rate);
        }

        /// Align the input to a block boundary.
        pub fn fillBlock(self: *Self) void {
            self.st.fillBlock();
        }
    };
}