use crate::{Error, Marker, WriteBuffer};

/// Encode the length of a byte array and the binary data itself.
pub fn write_bin(buf: &mut WriteBuffer, data: &[u8]) -> Result<Marker, Error> {
    let len = data.len();
    let (marker, bytes): (_, &[u8]) = if len < u8::MAX as _ {
        (Marker::B8, &u8::to_be_bytes(len as _))
    } else if len < u16::MAX as _ {
        (Marker::B16, &u16::to_be_bytes(len as _))
    } else if len < u32::MAX as _ {
        (Marker::B32, &u32::to_be_bytes(len as _))
    } else {
        return Err(Error::OutOfRange);
    };

    let args = marker.argument_bytes();
    buf.write(len + 1 + args, |buf| {
        // Safety: bytes.len() + len + 1 bytes available in buf.
        unsafe {
            let buf = buf.as_mut_ptr();
            *buf = marker.encoding();

            let buf = buf.add(1);
            buf.copy_from_nonoverlapping(bytes.as_ptr(), bytes.len());

            let buf = buf.add(bytes.len());
            buf.copy_from_nonoverlapping(data.as_ptr(), len);
        }
    })?;

    Ok(marker)
}
