use hopper_runtime::error::ProgramError;
#[derive(Clone, Copy)]
pub struct FieldRef<'a> {
data: &'a [u8],
}
impl<'a> FieldRef<'a> {
#[inline(always)]
pub const fn new(data: &'a [u8]) -> Self {
Self { data }
}
#[inline(always)]
pub const fn as_bytes(&self) -> &[u8] {
self.data
}
#[inline(always)]
pub fn read_u8(&self) -> Result<u8, ProgramError> {
self.data
.first()
.copied()
.ok_or(ProgramError::InvalidAccountData)
}
#[inline(always)]
pub fn read_u16(&self) -> Result<u16, ProgramError> {
if self.data.len() < 2 {
return Err(ProgramError::InvalidAccountData);
}
Ok(u16::from_le_bytes([self.data[0], self.data[1]]))
}
#[inline(always)]
pub fn read_u32(&self) -> Result<u32, ProgramError> {
if self.data.len() < 4 {
return Err(ProgramError::InvalidAccountData);
}
Ok(u32::from_le_bytes([
self.data[0],
self.data[1],
self.data[2],
self.data[3],
]))
}
#[inline(always)]
pub fn read_u64(&self) -> Result<u64, ProgramError> {
if self.data.len() < 8 {
return Err(ProgramError::InvalidAccountData);
}
Ok(u64::from_le_bytes([
self.data[0],
self.data[1],
self.data[2],
self.data[3],
self.data[4],
self.data[5],
self.data[6],
self.data[7],
]))
}
#[inline(always)]
pub fn read_bool(&self) -> Result<bool, ProgramError> {
self.read_u8().map(|v| v != 0)
}
#[inline(always)]
pub fn as_address(&self) -> Result<&[u8; 32], ProgramError> {
if self.data.len() < 32 {
return Err(ProgramError::InvalidAccountData);
}
Ok(unsafe { &*(self.data.as_ptr() as *const [u8; 32]) })
}
}
pub struct FieldMut<'a> {
data: &'a mut [u8],
}
impl<'a> FieldMut<'a> {
#[inline(always)]
pub fn new(data: &'a mut [u8]) -> Self {
Self { data }
}
#[inline(always)]
pub fn read_u8(&self) -> Result<u8, ProgramError> {
self.data
.first()
.copied()
.ok_or(ProgramError::InvalidAccountData)
}
#[inline(always)]
pub fn read_u64(&self) -> Result<u64, ProgramError> {
if self.data.len() < 8 {
return Err(ProgramError::InvalidAccountData);
}
Ok(u64::from_le_bytes([
self.data[0],
self.data[1],
self.data[2],
self.data[3],
self.data[4],
self.data[5],
self.data[6],
self.data[7],
]))
}
#[inline(always)]
pub fn write_u8(&mut self, v: u8) -> Result<(), ProgramError> {
if self.data.is_empty() {
return Err(ProgramError::InvalidAccountData);
}
self.data[0] = v;
Ok(())
}
#[inline(always)]
pub fn write_u16(&mut self, v: u16) -> Result<(), ProgramError> {
if self.data.len() < 2 {
return Err(ProgramError::InvalidAccountData);
}
let bytes = v.to_le_bytes();
self.data[0] = bytes[0];
self.data[1] = bytes[1];
Ok(())
}
#[inline(always)]
pub fn write_u32(&mut self, v: u32) -> Result<(), ProgramError> {
if self.data.len() < 4 {
return Err(ProgramError::InvalidAccountData);
}
let bytes = v.to_le_bytes();
self.data[..4].copy_from_slice(&bytes);
Ok(())
}
#[inline(always)]
pub fn write_u64(&mut self, v: u64) -> Result<(), ProgramError> {
if self.data.len() < 8 {
return Err(ProgramError::InvalidAccountData);
}
let bytes = v.to_le_bytes();
self.data[..8].copy_from_slice(&bytes);
Ok(())
}
#[inline(always)]
pub fn write_bool(&mut self, v: bool) -> Result<(), ProgramError> {
self.write_u8(v as u8)
}
#[inline(always)]
pub fn write_address(&mut self, addr: &[u8; 32]) -> Result<(), ProgramError> {
if self.data.len() < 32 {
return Err(ProgramError::InvalidAccountData);
}
self.data[..32].copy_from_slice(addr);
Ok(())
}
#[inline(always)]
pub fn copy_from(&mut self, src: &[u8]) -> Result<(), ProgramError> {
if self.data.len() < src.len() {
return Err(ProgramError::InvalidAccountData);
}
self.data[..src.len()].copy_from_slice(src);
Ok(())
}
#[inline(always)]
pub fn as_bytes(&self) -> &[u8] {
self.data
}
#[inline(always)]
pub fn as_bytes_mut(&mut self) -> &mut [u8] {
self.data
}
}