From eea3f66a93e210c9802822410fbe1466aaf50871 Mon Sep 17 00:00:00 2001 From: Pedro Arruda Date: Tue, 30 Jul 2024 15:42:10 -0300 Subject: [PATCH] impl decode for common types --- jyafn/src/layout/decode.rs | 159 ++++++++++++++++++++++++++++++++++++- 1 file changed, 156 insertions(+), 3 deletions(-) diff --git a/jyafn/src/layout/decode.rs b/jyafn/src/layout/decode.rs index 266b914..7710c55 100644 --- a/jyafn/src/layout/decode.rs +++ b/jyafn/src/layout/decode.rs @@ -1,3 +1,9 @@ +use std::collections::BTreeMap; +use std::rc::Rc; +use std::sync::Arc; + +use hashbrown::HashMap; + use crate::utils; use super::symbols::Sym; @@ -49,11 +55,158 @@ impl Decoder for ZeroDecoder { } } -impl Decode for f64 { +impl Decode for () { + fn build(layout: &Layout, _: &dyn Sym, _: &mut Visitor) -> Self { + match layout { + Layout::Unit => {} + _ => panic!("Bad layout for (): {layout:?}"), + } + } +} + +macro_rules! impl_decode_container { + ($container:ty) => { + impl Decode for $container { + fn build(layout: &Layout, symbols: &dyn Sym, visitor: &mut Visitor) -> Self { + Self::from(T::build(layout, symbols, visitor)) + } + } + }; +} + +impl_decode_container!(Box); +impl_decode_container!(Rc); +impl_decode_container!(Arc); + +macro_rules! impl_decode_scalar { + ($scalar:ty) => { + impl Decode for $scalar { + fn build(layout: &Layout, _: &dyn Sym, visitor: &mut Visitor) -> Self { + match layout { + Layout::Scalar => visitor.pop() as $scalar, + _ => panic!("Bad layout for {}: {layout:?}", stringify!($scalar)), + } + } + } + }; +} + +impl_decode_scalar!(i8); +impl_decode_scalar!(u8); +impl_decode_scalar!(i16); +impl_decode_scalar!(u16); +impl_decode_scalar!(i32); +impl_decode_scalar!(u32); +impl_decode_scalar!(i64); +impl_decode_scalar!(u64); +impl_decode_scalar!(isize); +impl_decode_scalar!(usize); +impl_decode_scalar!(f64); +impl_decode_scalar!(f32); + +impl Decode for bool { fn build(layout: &Layout, _: &dyn Sym, visitor: &mut Visitor) -> Self { match layout { - Layout::Scalar => visitor.pop(), - _ => panic!("Bad layout for f64: {layout:?}"), + Layout::Bool => match visitor.pop_int() { + 0 => false, + 1 => true, + i => panic!("Bad integer value for bool: {i}"), + }, + _ => panic!("Bad layout for bool: {layout:?}"), + } + } +} + +impl Decode for String { + fn build(layout: &Layout, symbols: &dyn Sym, visitor: &mut Visitor) -> Self { + match layout { + Layout::Symbol => { + let index = visitor.pop_int() as usize; + let Some(string) = symbols.get(index) else { + panic!("Symbol of index {index} not found") + }; + string.to_owned() + } + _ => panic!("Bad layout for String: {layout:?}"), + } + } +} + +impl Decode for Vec { + fn build(layout: &Layout, symbols: &dyn Sym, visitor: &mut Visitor) -> Self { + match layout { + Layout::List(layout, size) => (0..*size) + .map(|_| T::build(layout, symbols, visitor)) + .collect(), + _ => panic!("Bad layout for Vec<_>: {layout:?}"), + } + } +} + +macro_rules! impl_decode_tuple { + ($($n:tt: $typ:ident),*) => { + impl< $( $typ, )* > Decode for ( $( $typ, )* ) where $($typ: Decode),* { + fn build(layout: &Layout, symbols: &dyn Sym, visitor: &mut Visitor) -> Self { + match layout { + Layout::Tuple(fields) => { + ( + $({ + let Some(field_layout) = fields.get($n) else { + panic!("Missing field {} in tuple layout", $n) + }; + $typ::build(field_layout, symbols, visitor) + },)* + ) + }, + _ => panic!("Bad layout for tuple: {layout:?}"), + } + } + } + } +} + +impl_decode_tuple!(0: A); +impl_decode_tuple!(0: A, 1: B); +impl_decode_tuple!(0: A, 1: B, 2: C); +impl_decode_tuple!(0: A, 1: B, 2: C, 3: D); +impl_decode_tuple!(0: A, 1: B, 2: C, 3: D, 4: E); +impl_decode_tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F); +impl_decode_tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G); +impl_decode_tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H); +impl_decode_tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I); +impl_decode_tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J); +impl_decode_tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J, 10: K); + +impl Decode for HashMap { + fn build(layout: &Layout, symbols: &dyn Sym, visitor: &mut Visitor) -> Self { + match layout { + Layout::Struct(fields) => { + let mut decoded = HashMap::with_capacity(fields.0.len()); + + for (name, field) in &fields.0 { + decoded.insert(name.to_owned(), T::build(field, symbols, visitor)); + } + + decoded + } + _ => panic!("Bad layout for HashMap: {layout:?}"), + } + } +} + +impl Decode for BTreeMap { + fn build(layout: &Layout, symbols: &dyn Sym, visitor: &mut Visitor) -> Self { + match layout { + Layout::Struct(fields) => { + let mut decoded = BTreeMap::new(); + + for (name, field) in &fields.0 { + decoded.insert(name.to_owned(), T::build(field, symbols, visitor)); + } + + decoded + } + _ => panic!("Bad layout for BTreeMap: {layout:?}"), } } }