transaction-processor 0.0.1

Write transaction processors for Wavelet in Rust.
Documentation
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)
        })
    }
}