use ::{ NifEnv, NifTerm, NifResult, NifError, NifDecoder };
use ::wrapper::map;
pub fn map_new<'a>(env: NifEnv<'a>) -> NifTerm<'a> {
unsafe { NifTerm::new(env, map::map_new(env.as_c_arg())) }
}
impl<'a> NifTerm<'a> {
pub fn map_get(self, key: NifTerm) -> NifResult<NifTerm<'a>> {
let env = self.get_env();
match unsafe { map::get_map_value(env.as_c_arg(), self.as_c_arg(), key.as_c_arg()) } {
Some(value) => Ok(unsafe { NifTerm::new(env, value) }),
None => Err(NifError::BadArg),
}
}
pub fn map_size(self) -> NifResult<usize> {
let env = self.get_env();
unsafe { map::get_map_size(env.as_c_arg(), self.as_c_arg()).ok_or(NifError::BadArg) }
}
pub fn map_put(self, key: NifTerm<'a>, value: NifTerm<'a>) -> NifResult<NifTerm<'a>> {
let map_env = self.get_env();
assert!(map_env == key.get_env(), "key is from different environment as map");
assert!(map_env == value.get_env(), "value is from different environment as map");
match unsafe { map::map_put(map_env.as_c_arg(), self.as_c_arg(), key.as_c_arg(), value.as_c_arg()) } {
Some(inner) => Ok(unsafe { NifTerm::new(map_env, inner) }),
None => Err(NifError::BadArg),
}
}
pub fn map_remove(self, key: NifTerm<'a>) -> NifResult<NifTerm<'a>> {
let map_env = self.get_env();
assert!(map_env == key.get_env(), "key is from different environment as map");
match unsafe { map::map_remove(map_env.as_c_arg(), self.as_c_arg(), key.as_c_arg()) } {
Some(inner) => Ok(unsafe { NifTerm::new(map_env, inner) }),
None => Err(NifError::BadArg),
}
}
pub fn map_update(self, key: NifTerm<'a>, new_value: NifTerm<'a>) -> NifResult<NifTerm<'a>> {
let map_env = self.get_env();
assert!(map_env == key.get_env(), "key is from different environment as map");
assert!(map_env == new_value.get_env(), "value is from different environment as map");
match unsafe { map::map_update(map_env.as_c_arg(), self.as_c_arg(), key.as_c_arg(), new_value.as_c_arg()) } {
Some(inner) => Ok(unsafe { NifTerm::new(map_env, inner) }),
None => Err(NifError::BadArg),
}
}
}
pub struct NifMapIterator<'a> {
env: NifEnv<'a>,
iter: map::ErlNifMapIterator
}
impl<'a> NifMapIterator<'a> {
pub fn new(map: NifTerm<'a>) -> Option<NifMapIterator<'a>> {
let env = map.get_env();
unsafe {
map::map_iterator_create(env.as_c_arg(), map.as_c_arg())
}.map(|iter| NifMapIterator { env: env, iter: iter })
}
}
impl<'a> Drop for NifMapIterator<'a> {
fn drop(&mut self) {
unsafe {
map::map_iterator_destroy(self.env.as_c_arg(), &mut self.iter);
}
}
}
impl<'a> Iterator for NifMapIterator<'a> {
type Item = (NifTerm<'a>, NifTerm<'a>);
fn next(&mut self) -> Option<(NifTerm<'a>, NifTerm<'a>)> {
unsafe {
map::map_iterator_get_pair(self.env.as_c_arg(), &mut self.iter)
.map(|(key, value)| {
map::map_iterator_next(self.env.as_c_arg(), &mut self.iter);
(NifTerm::new(self.env, key),
NifTerm::new(self.env, value))
})
}
}
}
impl<'a> NifDecoder<'a> for NifMapIterator<'a> {
fn decode(term: NifTerm<'a>) -> NifResult<Self> {
match NifMapIterator::new(term) {
Some(iter) => Ok(iter),
None => Err(NifError::BadArg)
}
}
}