sark-http 0.22.0

HTTP wire types, semantics, codecs, and ownership invariants for Sark
Documentation
use o3::{
    alloc,
    buffer::{
        pool,
        write::{Sink as _, SpareExt as _},
    },
};
use sark_http::field::metadata::{
    lower::plain,
    packed,
    packed::prefix::{self, Prefix},
    section::storage,
};

#[test]
fn rejects_short_prefix() {
    let mut lease = pool::Span::try_new(1).expect("allocate");
    lease.try_append(&[0]).expect("capacity").commit();
    assert!(matches!(
        packed::Decoded::try_from(lease),
        Err(storage::Fault::Packed {
            offset: 0,
            cause: prefix::Error::Prefix {
                required: Prefix::LEN,
                available: 1
            }
        })
    ));
}

#[test]
fn rejects_short_payload() {
    let mut lease = pool::Span::try_new(Prefix::LEN).expect("allocate");
    lease
        .try_append(&[1, 0, 0, 0, 1, 0, 0, 0, 0])
        .expect("capacity")
        .commit();
    assert!(matches!(
        packed::Decoded::try_from(lease),
        Err(storage::Fault::Packed {
            offset: 0,
            cause: prefix::Error::Payload { .. }
        })
    ));
}

#[test]
fn commits_complete_records() {
    let lease = pool::Span::try_new(32).expect("allocate");
    let mut writer = storage::Writer::<packed::Decoded>::try_new(lease).expect("prefix");
    let rejected = writer.try_write::<plain::Error>(|output| {
        let foreign = Box::leak(
            alloc::BoxExt::try_new(pool::Span::try_new(32).expect("foreign field storage"))
                .expect("foreign field owner"),
        );
        let spare = Box::leak(alloc::BoxExt::try_new(foreign.spare()).expect("foreign spare"));
        *output = spare.bounded();
        output.write_slice(b"nv").map_err(plain::Error::Write)?;
        Ok(1)
    });
    assert!(matches!(rejected, Err(plain::Error::Layout([0, 1, 0]))));
    let rejected = writer.try_write::<plain::Error>(|output| {
        output.write_slice(b"x").map_err(plain::Error::Write)?;
        Ok(2)
    });
    assert!(matches!(rejected, Err(plain::Error::Layout([0, 2, 1]))));
    writer
        .try_write::<plain::Error>(|output| {
            output.write_slice(b"nv").map_err(plain::Error::Write)?;
            Ok(1)
        })
        .expect("complete field");
    let decoded = <packed::Decoded as storage::Block>::from(writer.finish());
    let mut fields = decoded.iter();
    let field = fields.next().expect("committed field");
    assert_eq!(
        (field.name, field.value),
        (b"n".as_slice(), b"v".as_slice())
    );
    assert!(fields.next().is_none());
}