Compile time verified byte writer for slice and vector.
toml
[dependencies]
const-writer = "0.1.0"
```rust use constwriter::ConstWrite; fn main() { let mut vec = vec![]; let writer = vec.constwriter::<10>() // reserve 10 bytes in vec .writeu32le(12) // no runtime checks .writeu32le(34); // no runtime checks
assert_eq!(writer.remaining(), 2);
assert_eq!(vec.len(), 8);
assert_eq!(&vec[0..8], &[12, 0, 0, 0, 34, 0, 0, 0]);
} ```
rust
use const_writer::ConstWrite;
fn main() {
let mut buff = [0u8; 1024];
buff.as_mut().const_writer::<10>()
.write_slice(&[1, 2, 3, 4, 5, 6])
.write_u64_le(111); // compile error.
}
```rust
use constwriter::{ConstWriterAdapter, ConstWriter, ConstWrite};
fn main() {
// write 10 bytes
fn writestruct
let mut buff = [0u8; 16]; writestruct(buff.asmut().constwriter()); asserteq!(buff, [34, 0, 2, 0, 3, 0, 4, 0, 5, 0, 0, 0, 0, 0, 0, 0]); } ```
It generates super optimal assembly with pretty rust syntax
```rust // we return modified reference so compiler won't optimise away reference manipulation pub fn write(mut refbuff: &mut [u8]) -> &mut [u8] { use crate::ConstWrite; refbuff.constwriter::<31>() .writeu8le(0x01) .writeu16le(0x0203) .writeu32le(0x04050607) .writeu64le(0x08090A0B0C0D0E0F) .writeu128_le(0x101112131415161718191A1B1C1D1E1F);
ref_buff
} ```
Assembly consists only one comparison
asm
write:
subq $88, %rsp
movq %rsi, %rdx
cmpq $30, %rsi
jbe .LBB2_1 # panic
movq %rdi, %rax
movb $1, (%rdi)
movw $515, 1(%rdi) # imm = 0x203
movl $67438087, 3(%rdi) # imm = 0x4050607
movabsq $579005069656919567, %rcx # imm = 0x8090A0B0C0D0E0F
movq %rcx, 7(%rdi)
movabsq $1157726452361532951, %rcx # imm = 0x1011121314151617
movq %rcx, 23(%rdi)
movabsq $1736447835066146335, %rcx # imm = 0x18191A1B1C1D1E1F
movq %rcx, 15(%rdi)
addq $31, %rax
addq $-31, %rdx
addq $88, %rsp
retq
And sometimes rustc can generate really pretty assembly :heart_eyes:
rust
pub fn write_struct<T: ConstWriterAdapter>(writer: ConstWriter<T, 12>) -> ConstWriter<T, 0> {
writer.write_u32_le(34).write_u16_le(2).write_u16_le(3).write_u16_le(4).write_u16_le(5)
}
asm
write_struct:
movq %rdi, %rax
movl $34, (%rsi)
movabsq $1407392063619074, %rcx # imm = 0x5000400030002 <- OMG
movq %rcx, 4(%rsi)
leaq 12(%rsi), %rdx
retq
no_std