DoxigAlpha

feed

Returns the number of bytes consumed by the chunk size. This is always less than or equal to bytes.len.

After this function returns, chunk_len will contain the parsed chunk size in bytes when state is data. Alternately, state may become invalid, indicating a syntax error in the input stream.

If the amount returned is less than bytes.len, the parser is in the chunk_data state and the first byte of the chunk is at bytes[result].

Asserts state is neither data nor invalid.

Function parameters

Parameters

#
p:*ChunkParser
bytes:[]const u8

Type definitions in this namespace

Types

#

Returns the number of bytes consumed by the chunk size.

Functions

#
feed
Returns the number of bytes consumed by the chunk size.

= .{ .state = .head_size, .chunk_len = 0, }

Values

#
init
= .{ .state = .head_size, .chunk_len = 0, }

Source

Implementation

#
pub fn feed(p: *ChunkParser, bytes: []const u8) usize {
    for (bytes, 0..) |c, i| switch (p.state) {
        .data_suffix => switch (c) {
            '\r' => p.state = .data_suffix_r,
            '\n' => p.state = .head_size,
            else => {
                p.state = .invalid;
                return i;
            },
        },
        .data_suffix_r => switch (c) {
            '\n' => p.state = .head_size,
            else => {
                p.state = .invalid;
                return i;
            },
        },
        .head_size => {
            const digit = switch (c) {
                '0'...'9' => |b| b - '0',
                'A'...'Z' => |b| b - 'A' + 10,
                'a'...'z' => |b| b - 'a' + 10,
                '\r' => {
                    p.state = .head_r;
                    continue;
                },
                '\n' => {
                    p.state = .data;
                    return i + 1;
                },
                else => {
                    p.state = .head_ext;
                    continue;
                },
            };

            const new_len = p.chunk_len *% 16 +% digit;
            if (new_len <= p.chunk_len and p.chunk_len != 0) {
                p.state = .invalid;
                return i;
            }

            p.chunk_len = new_len;
        },
        .head_ext => switch (c) {
            '\r' => p.state = .head_r,
            '\n' => {
                p.state = .data;
                return i + 1;
            },
            else => continue,
        },
        .head_r => switch (c) {
            '\n' => {
                p.state = .data;
                return i + 1;
            },
            else => {
                p.state = .invalid;
                return i;
            },
        },
        .data => unreachable,
        .invalid => unreachable,
    };
    return bytes.len;
}