1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
use ::{ NifEnv, NifError, NifTerm, NifResult, }; #[macro_use] pub mod atom; pub mod binary; pub mod list; pub mod map; pub mod primitive; pub mod string; pub mod tuple; pub mod pid; pub mod elixir_struct; pub trait NifEncoder { fn encode<'a>(&self, env: NifEnv<'a>) -> NifTerm<'a>; } pub trait NifDecoder<'a>: Sized+'a { fn decode(term: NifTerm<'a>) -> NifResult<Self>; } impl<'a> NifEncoder for NifTerm<'a> { fn encode<'b>(&self, env: NifEnv<'b>) -> NifTerm<'b> { self.in_env(env) } } impl<'a> NifDecoder<'a> for NifTerm<'a> { fn decode(term: NifTerm<'a>) -> NifResult<Self> { Ok(term) } } impl<'a, T> NifEncoder for &'a T where T: NifEncoder { fn encode<'c>(&self, env: NifEnv<'c>) -> NifTerm<'c> { <T as NifEncoder>::encode(self, env) } } impl<T> NifEncoder for Option<T> where T: NifEncoder { fn encode<'c>(&self, env: NifEnv<'c>) -> NifTerm<'c> { match *self { Some(ref value) => value.encode(env), None => atom::nil().encode(env), } } } impl<'a, T> NifDecoder<'a> for Option<T> where T: NifDecoder<'a> { fn decode(term: NifTerm<'a>) -> NifResult<Self> { if let Ok(term) = term.decode::<T>() { Ok(Some(term)) } else { let decoded_atom: atom::NifAtom = term.decode()?; if decoded_atom == atom::nil() { Ok(None) } else { Err(NifError::BadArg) } } } } impl<T, E> NifEncoder for Result<T, E> where T: NifEncoder, E: NifEncoder { fn encode<'c>(&self, env: NifEnv<'c>) -> NifTerm<'c> { match *self { Ok(ref value) => (atom::ok().encode(env), value.encode(env)).encode(env), Err(ref err) => (atom::error().encode(env), err.encode(env)).encode(env), } } } impl<'a, T, E> NifDecoder<'a> for Result<T, E> where T: NifDecoder<'a>, E: NifDecoder<'a> { fn decode(term: NifTerm<'a>) -> NifResult<Self> { let (decoded_atom, inner_term): (atom::NifAtom, NifTerm) = term.decode()?; if decoded_atom == atom::ok() { let ok_value: T = inner_term.decode()?; Ok(Ok(ok_value)) } else if decoded_atom == atom::error() { let err_value: E = inner_term.decode()?; Ok(Err(err_value)) } else { Err(NifError::BadArg) } } }