use crate::internal::ScratchBuf;
use crate::sys;
use crate::sys::SysResult as Result;
use crate::types::{RuntimeMemoryLength, StorageKey};
use core::mem::MaybeUninit;
use crate::sys_exn::flags::lock_after_write;
pub fn bytestring_exists(key: &StorageKey) -> Result<bool> {
match bytestring_get_len(key) {
Ok(_) => Ok(true),
Err(e) => {
if e.is_storage_key_not_exist() {
Ok(false)
} else {
Err(e)
}
}
}
}
pub fn bytestring_get_len(key: &StorageKey) -> Result<u32> {
let mut out: RuntimeMemoryLength = 0;
sys::raw_BytestringGetLen(key, &mut out)?;
Ok(out as u32)
}
pub fn bytestring_set(key: &StorageKey, slice: &[u8]) -> Result<()> {
sys::raw_BytestringSet(key, slice)
}
pub fn bytestring_set_exclusive(key: &StorageKey, slice: &[u8]) -> Result<()> {
sys::raw_BytestringSet(key, slice)?;
lock_after_write(key, true);
Ok(())
}
pub fn bytestring_get_sized<const N: usize>(
key: &StorageKey,
) -> Result<Option<[u8; N]>> {
let mut bytes_mu = [MaybeUninit::<u8>::uninit(); N];
let mut len = MaybeUninit::uninit();
sys::uninit_BytestringGet(key, &mut bytes_mu, &mut len)?;
let len = unsafe { len.assume_init() };
if len != N as u32 {
return Ok(None);
}
let bytes: [u8; N] =
unsafe { bytes_mu.map(|elt| MaybeUninit::assume_init(elt)) };
Ok(Some(bytes))
}
pub(crate) fn bytestring_read_into(
key: &StorageKey,
buf: &mut ScratchBuf,
) -> Result<Option<()>> {
let len = bytestring_get_len(key)? as usize;
buf.clear();
#[cfg(feature = "alloc")]
buf.reserve(len);
if len > buf.spare_capacity_mut().len() {
return Ok(None);
}
let mut written_len = MaybeUninit::uninit();
sys::uninit_BytestringGet(
key,
buf.spare_capacity_mut(),
&mut written_len,
)?;
debug_assert!(unsafe { written_len.assume_init() } as usize == len);
unsafe { buf.set_len(len) };
Ok(Some(()))
}
#[cfg(feature = "alloc")]
mod bytestring_get_alloc {
use super::*;
use alloc::boxed::Box;
pub fn bytestring_get(key: &StorageKey) -> Result<Box<[u8]>> {
let len = bytestring_get_len(key)?;
let mut array = Box::<[u8]>::new_uninit_slice(len as usize);
let mut written_len = MaybeUninit::uninit();
sys::uninit_BytestringGet(key, &mut array, &mut written_len)?;
debug_assert!(
unsafe { written_len.assume_init() } == len,
"Inconsistent bytestring size",
);
Ok(unsafe { array.assume_init() })
}
pub fn bytestring_try_get(key: &StorageKey) -> Result<Option<Box<[u8]>>> {
match bytestring_get(key) {
Ok(v) => Ok(Some(v)),
Err(e) if e.is_storage_key_not_exist() => Ok(None),
Err(e) => Err(e),
}
}
}
#[cfg(feature = "alloc")]
pub use bytestring_get_alloc::*;