@@ 9,61 9,6 @@ use strings;
use strio;
use types;
export def HEADER_BUCKETS: u64 = 16;
export type header_field = struct {
raw: []u8,
key: str,
val: str,
};
// Initializes a new header field, duplicating the provided parameters.
fn new_header_field(key: str, val: str, raw: []u8) header_field = {
return header_field {
raw = alloc(raw...),
key = canonical_mime_header_key(key),
val = strings::dup(val),
};
};
fn header_field_destroy(hf: *header_field) void = {
free(hf.raw);
free(hf.key);
free(hf.val);
free(hf);
};
// Returns the raw representation of this header field, including CRLF. The
// return value is borrowed from the header field.
fn header_field_raw(hf: *header_field) ([]u8 | errors::invalid) = {
if (len(hf.raw) != 0) {
return hf.raw;
};
const iter = strings::iter(hf.key);
for (true) {
const rn = match (strings::next(&iter)) {
case let rn: rune =>
yield rn;
case void =>
break;
};
if (!ascii::isprint(rn) || rn == ':') {
return errors::invalid;
};
};
if (strings::contains(hf.val, "\r\n")) {
return errors::invalid;
};
let sink = bufio::dynamic(io::mode::WRITE);
header_field_fmt(&sink, hf)!;
hf.raw = bufio::buffer(&sink);
return hf.raw;
};
export type header = struct {
fields: []*header_field,
map: [HEADER_BUCKETS][]header_map_key,
@@ 74,6 19,14 @@ export type header_map_key = struct {
fields: []*header_field,
};
export def HEADER_BUCKETS: u64 = 16;
export type header_field = struct {
raw: []u8,
key: str,
val: str,
};
// Creates a new message header. The representation is idempotent, such that
// whitespace and field ordering is preserved.
export fn new_header() header = {
@@ 384,6 337,54 @@ export fn write_header(sink: io::handle, head: *header) (size | io::error) = {
assert(result == expect);
};
// Initializes a new header field, duplicating the provided parameters.
fn new_header_field(key: str, val: str, raw: []u8) header_field = {
return header_field {
raw = alloc(raw...),
key = canonical_mime_header_key(key),
val = strings::dup(val),
};
};
fn header_field_destroy(hf: *header_field) void = {
free(hf.raw);
free(hf.key);
free(hf.val);
free(hf);
};
// Returns the raw representation of this header field, including CRLF. The
// return value is borrowed from the header field.
fn header_field_raw(hf: *header_field) ([]u8 | errors::invalid) = {
if (len(hf.raw) != 0) {
return hf.raw;
};
const iter = strings::iter(hf.key);
for (true) {
const rn = match (strings::next(&iter)) {
case let rn: rune =>
yield rn;
case void =>
break;
};
if (!ascii::isprint(rn) || rn == ':') {
return errors::invalid;
};
};
if (strings::contains(hf.val, "\r\n")) {
return errors::invalid;
};
let sink = bufio::dynamic(io::mode::WRITE);
header_field_fmt(&sink, hf)!;
hf.raw = bufio::buffer(&sink);
return hf.raw;
};
def PREFERRED_HEADER_LEN = 76z;
def MAX_HEADER_LEN = 998z;