kapiti 0.0.3

The Kapiti DNS Server
Documentation
/// Implementation of `character-string`s as defined by RFC1035 section 3.3
use anyhow::{bail, Result};
use bytes::{BufMut, Bytes, BytesMut};

/// Writes a `character-string`: A length byte followed by a 0-255 byte payload.
/// Returns an error if the provided `in_buf` exceeds 255 bytes.
pub fn write(in_buf: &[u8], out_buf: &mut BytesMut, description: &str) -> Result<()> {
    if in_buf.len() > 255 {
        bail!(
            "{} length {} exceeds maximum 255",
            description,
            in_buf.len()
        );
    }
    out_buf.reserve(1 + in_buf.len());
    out_buf.put_u8(in_buf.len() as u8);
    out_buf.put_slice(&in_buf);
    return Ok(());
}

/// Reads a `character-string`: A length byte followed by a 0-255 byte payload, from the specified offset in `in_buf`.
/// This is different from `domain-name`s where each label is 0-63 bytes, and a "length" exceeding 192 indicates a pointer.
/// Returns an error if `in_buf`+`original_offset` doesn't have enough room for the length byte or the payload
pub fn read(in_buf: &[u8], original_offset: usize, description: &str) -> Result<(usize, Bytes)> {
    let mut offset = original_offset;
    let mut out = BytesMut::new();

    // First byte should be size of label (0-255)
    if in_buf.len() < offset + 1 {
        bail!("{} is empty, expected string size", description);
    }
    let label_size = in_buf[offset] as usize;
    offset += 1;
    // Fetch remaining bytes and include trailing '.'
    if in_buf.len() < offset + label_size {
        bail!(
            "{} remaining buffer length {} is shorter than required offset {} + string {}",
            description,
            in_buf.len(),
            offset,
            label_size
        );
    }
    out.extend_from_slice(&in_buf[offset..offset + label_size]);
    return Ok((1 + label_size, out.freeze()));
}