backup_lib 0.2.0

backup macro to inject function into mod and actor
Documentation
use ic_cdk::api::stable::{stable64_read, stable64_write};
use ic_cdk::trap;

pub fn encode_vec<T: Clone + candid::CandidType + serde::de::DeserializeOwned>(data: &[T]) -> Vec<u8> {
  let records = data.to_vec();
  candid::encode_one(records).unwrap()
}

pub fn decode_vec<T: candid::CandidType + serde::de::DeserializeOwned>(encoded: &[u8]) -> Vec<T> {
  candid::decode_one(encoded).unwrap()
}

pub fn write_record<T: Clone + candid::CandidType + serde::de::DeserializeOwned>(record: T, offset: usize, entry_size: usize) -> Result<usize, String> {
  let buf = candid::encode_one(record.clone()).unwrap();

  if buf.len() + 2 > entry_size {
    trap(&format!(
      "record size {} exceeds maximum size {}",
      buf.len(),
      entry_size
    ))
  }

  stable64_write(offset as u64, &(buf.len() as u16).to_le_bytes());
  stable64_write(offset as u64 + std::mem::size_of::<u16>() as u64, &buf);

  Ok(buf.len() + 2)
}

pub fn read_record<T: candid::CandidType + serde::de::DeserializeOwned>(offset: usize, entry_size: usize) -> Result<T, String> {
  let mut buf = vec![0; entry_size as usize];
  stable64_read(offset as u64, &mut buf);

  let len = u16::from_le_bytes(buf[0..2].try_into().unwrap()) as usize;

  // This error most likely indicates stable memory corruption.
  if len + 2 > entry_size {
    trap(&format!(
      "persisted value size {} exceeds maximum size {}",
      len,
      entry_size
    ))
  }

  let data: T =
    candid::decode_one(&buf[2..2 + len]).unwrap();

  Ok(data)
}