zabi_rs/
encoder.rs

1use crate::error::ZError;
2
3/// Write a 32-byte word to the buffer at the specific offset.
4#[inline(always)]
5fn write_word(buf: &mut [u8], offset: usize, word: &[u8; 32]) -> Result<(), ZError> {
6    if offset + 32 > buf.len() {
7        return Err(ZError::OutOfBounds(offset + 32, buf.len()));
8    }
9    buf[offset..offset + 32].copy_from_slice(word);
10    Ok(())
11}
12
13/// Encode a U256 (32 bytes) into the buffer.
14#[inline]
15pub fn encode_u256(buf: &mut [u8], offset: usize, value: &[u8; 32]) -> Result<(), ZError> {
16    write_word(buf, offset, value)
17}
18
19/// Encode an Address (20 bytes) into the buffer (padded to 32 bytes).
20#[inline]
21pub fn encode_address(buf: &mut [u8], offset: usize, value: &[u8; 20]) -> Result<(), ZError> {
22    if offset + 32 > buf.len() {
23        return Err(ZError::OutOfBounds(offset + 32, buf.len()));
24    }
25    // Zero out high bytes
26    buf[offset..offset + 12].fill(0);
27    // Copy address
28    buf[offset + 12..offset + 32].copy_from_slice(value);
29    Ok(())
30}
31
32/// Encode a boolean.
33#[inline]
34pub fn encode_bool(buf: &mut [u8], offset: usize, value: bool) -> Result<(), ZError> {
35    if offset + 32 > buf.len() {
36        return Err(ZError::OutOfBounds(offset + 32, buf.len()));
37    }
38    buf[offset..offset + 31].fill(0);
39    buf[offset + 31] = if value { 1 } else { 0 };
40    Ok(())
41}
42
43/// Encode raw bytes (dynamic).
44///
45/// Use this when constructing the data part of bytes/string.
46/// Does NOT write length prefix or offset (that's for higher level logic).
47/// Just pads the data to 32-byte boundary if needed?
48/// Actually, ABI encoding of bytes is:
49/// [offset] [length] [data + padding]
50/// This helper writes `[data + padding]` given a destination.
51/// Returns number of bytes written (including padding).
52pub fn encode_bytes_data(buf: &mut [u8], offset: usize, data: &[u8]) -> Result<usize, ZError> {
53    let len = data.len();
54    let padded_len = (len + 31) & !31; // Round up to nearest 32
55
56    if offset + padded_len > buf.len() {
57        return Err(ZError::OutOfBounds(offset + padded_len, buf.len()));
58    }
59
60    // Copy data
61    buf[offset..offset + len].copy_from_slice(data);
62    // Zero padding
63    if padded_len > len {
64        buf[offset + len..offset + padded_len].fill(0);
65    }
66
67    Ok(padded_len)
68}