use sys;
use types::*;
pub struct Account<'a> {
key: Option<&'a str>,
}
impl<'a> Account<'a> {
pub fn sender() -> Account<'static> {
Account { key: None }
}
pub fn sender_id() -> String {
let mut buf: Vec<u8> = Vec::with_capacity(128);
unsafe {
buf.set_len(128);
let copied = ::sys::_sender_id(buf.as_mut_ptr(), buf.len());
buf.set_len(copied);
}
String::from_utf8(buf).unwrap()
}
pub fn load(key: &'a str) -> Account<'a> {
Account { key: Some(key) }
}
fn load_current(&self) -> ProcessResult<()> {
match self.key {
Some(key) => {
if unsafe { sys::_load_account(key.as_ptr(), key.len()) }
!= InternalProcessResult::Ok
{
Err(ProcessError::NotFound)
} else {
Ok(())
}
}
None => {
unsafe { sys::_load_sender() };
Ok(())
}
}
}
pub fn get(&self, key: &str) -> ProcessResult<Vec<u8>> {
self.load_current()?;
let key = key.as_bytes();
let value_len = unsafe { sys::_load_len(StoreId::Account, key.as_ptr(), key.len()) };
if value_len == 0 {
return Err(ProcessError::NotFound);
}
let mut ret: Vec<u8> = Vec::with_capacity(value_len);
unsafe { ret.set_len(value_len) };
unsafe { sys::_load(StoreId::Account, key.as_ptr(), key.len(), ret.as_mut_ptr()) };
Ok(ret)
}
pub fn get_string(&self, key: &str) -> ProcessResult<String> {
self.get(key)
.and_then(|v| String::from_utf8(v).map_err(|_| ProcessError::InvalidData))
}
pub fn get_u64(&self, key: &str) -> ProcessResult<u64> {
self.get(key).and_then(|v| {
if v.len() == 8 {
Ok(unsafe { *(v.as_ptr() as *const u64) })
} else {
Err(ProcessError::InvalidData)
}
})
}
pub fn set(&self, key: &str, value: &[u8]) -> ProcessResult<()> {
self.load_current()?;
let key = key.as_bytes();
unsafe {
sys::_store(
StoreId::Account,
key.as_ptr(),
key.len(),
value.as_ptr(),
value.len(),
)
}.into()
}
pub fn set_string(&self, key: &str, value: &str) -> ProcessResult<()> {
self.set(key, value.as_bytes())
}
pub fn set_u64(&self, key: &str, value: u64) -> ProcessResult<()> {
self.set(key, &unsafe {
::std::mem::transmute::<u64, [u8; 8]>(value)
})
}
}