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;
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)
}