use nom::Finish; use ruststep::{ast::*, parser::exchange, tables::*}; use serde::Deserialize; use std::str::FromStr; espr_derive::inline_express!( r#" SCHEMA test_schema; ENTITY base SUPERTYPE OF (ONEOF (sub1, sub2)); x: REAL; END_ENTITY; ENTITY sub1 SUBTYPE OF (base); y1: REAL; END_ENTITY; ENTITY sub2 SUBTYPE OF (base); y2: REAL; END_ENTITY; END_SCHEMA; "# ); use test_schema::*; const EXAMPLE: &str = r#" DATA; #1 = BASE(1.0); #2 = SUB_1(BASE((1.0)), 2.0); #3 = SUB_2(#1, 4.0); ENDSEC; "#; #[test] fn deserialize_base() { let (residual, p): (_, Record) = exchange::simple_record("BASE(1.0)").finish().unwrap(); dbg!(&p); assert_eq!(residual, ""); let a: BaseHolder = Deserialize::deserialize(&p).unwrap(); dbg!(&a); assert_eq!(a, BaseHolder { x: 1.0 }); } #[test] fn deserialize_sub1() { test( "SUB_1(BASE((1.0)), 2.0)", Sub1Holder { base: BaseHolder { x: 1.0 }.into(), y1: 2.0, }, ); test( "SUB_1(#3, 2.0)", Sub1Holder { base: Name::Entity(3).into(), y1: 2.0, }, ); fn test(input: &str, answer: Sub1Holder) { let (residual, p): (_, Record) = exchange::simple_record(input).finish().unwrap(); dbg!(&p); assert_eq!(residual, ""); let a: Sub1Holder = Deserialize::deserialize(&p).unwrap(); dbg!(&a); assert_eq!(a, answer); } } #[test] fn deserialize_base_any() { test( "SUB_1(BASE((1.0)), 2.0)", BaseAnyHolder::Sub1(Box::new(Sub1Holder { base: BaseHolder { x: 1.0 }.into(), y1: 2.0, })), ); test( "SUB_1(#3, 2.0)", BaseAnyHolder::Sub1(Box::new(Sub1Holder { base: Name::Entity(3).into(), y1: 2.0, })), ); fn test(input: &str, answer: BaseAnyHolder) { let (residual, p): (_, Record) = exchange::simple_record(input).finish().unwrap(); dbg!(&p); assert_eq!(residual, ""); let a: BaseAnyHolder = Deserialize::deserialize(&p).unwrap(); dbg!(&a); assert_eq!(a, answer); } } #[test] fn deserialize_base_any_placeholder() { test( "SUB_1(BASE((1.0)), 2.0)", PlaceHolder::Owned(BaseAnyHolder::Sub1(Box::new(Sub1Holder { base: BaseHolder { x: 1.0 }.into(), y1: 2.0, }))), ); test( "SUB_1(#3, 2.0)", PlaceHolder::Owned(BaseAnyHolder::Sub1(Box::new(Sub1Holder { base: Name::Entity(3).into(), y1: 2.0, }))), ); fn test(input: &str, answer: PlaceHolder) { let (residual, p): (_, Record) = exchange::simple_record(input).finish().unwrap(); dbg!(&p); assert_eq!(residual, ""); let a: PlaceHolder = Deserialize::deserialize(&p).unwrap(); dbg!(&a); assert_eq!(a, answer); } } #[test] fn into_base_any() { test( "SUB_1(BASE((1.0)), 2.0)", BaseAny::Sub1(Box::new(Sub1 { base: Base { x: 1.0 }, y1: 2.0, })), ); test( "SUB_1(#1, 2.0)", BaseAny::Sub1(Box::new(Sub1 { base: Base { x: 1.0 }, y1: 2.0, })), ); fn test(input: &str, answer: BaseAny) { let table = Tables::from_str(EXAMPLE).unwrap(); let (residual, p): (_, Record) = exchange::simple_record(input).finish().unwrap(); dbg!(&p); assert_eq!(residual, ""); let holder = PlaceHolder::::deserialize(&p).unwrap(); dbg!(&holder); let owned = holder.into_owned(&table).unwrap(); dbg!(&owned); assert_eq!(owned, answer); } } #[test] fn lookup_base_any() { test( Parameter::Ref(Name::Entity(1)), BaseAny::Base(Box::new(Base { x: 1.0 })), ); test( Parameter::Ref(Name::Entity(2)), BaseAny::Sub1(Box::new(Sub1 { base: Base { x: 1.0 }, y1: 2.0, })), ); test( Parameter::Ref(Name::Entity(3)), BaseAny::Sub2(Box::new(Sub2 { base: Base { x: 1.0 }, y2: 4.0, })), ); fn test(p: Parameter, answer: BaseAny) { let table = Tables::from_str(EXAMPLE).unwrap(); let holder = PlaceHolder::::deserialize(&p).unwrap(); dbg!(&holder); let owned = holder.into_owned(&table).unwrap(); dbg!(&owned); assert_eq!(owned, answer); } } #[test] fn get_owned_base() { let table = Tables::from_str(EXAMPLE).unwrap(); let base = EntityTable::::get_owned(&table, 1).unwrap(); assert_eq!(base, Base { x: 1.0 }); } #[test] fn get_owned_sub1() { let table = Tables::from_str(EXAMPLE).unwrap(); let sub1 = EntityTable::::get_owned(&table, 2).unwrap(); assert_eq!( sub1, Sub1 { base: Base { x: 1.0 }, y1: 2.0 } ); } #[test] fn get_owned_any() { let table = Tables::from_str(EXAMPLE).unwrap(); // #1 = BASE(1.0); let any1 = EntityTable::::get_owned(&table, 1).unwrap(); assert_eq!(any1, BaseAny::Base(Box::new(Base { x: 1.0 }))); // #2 = SUB_1(BASE((1.0)), 2.0); let any2 = EntityTable::::get_owned(&table, 2).unwrap(); assert_eq!( any2, BaseAny::Sub1(Box::new(Sub1 { base: Base { x: 1.0 }, y1: 2.0 })) ); // #3 = SUB_2(#1, 4.0); let any3 = EntityTable::::get_owned(&table, 3).unwrap(); assert_eq!( any3, BaseAny::Sub2(Box::new(Sub2 { base: Base { x: 1.0 }, y2: 4.0 })) ); } #[test] fn as_ref_base_any() { let table = Tables::from_str(EXAMPLE).unwrap(); // #1 = BASE(1.0); let any1 = EntityTable::::get_owned(&table, 1).unwrap(); assert_eq!(any1.as_ref(), &Base { x: 1.0 }); // #2 = SUB_1(BASE((1.0)), 2.0); let any2 = EntityTable::::get_owned(&table, 2).unwrap(); assert_eq!(any2.as_ref(), &Base { x: 1.0 }); let sub2 = EntityTable::::get_owned(&table, 2).unwrap(); assert_eq!(sub2.as_ref(), &Base { x: 1.0 }); // #3 = SUB_2(#1, 4.0); let any3 = EntityTable::::get_owned(&table, 3).unwrap(); assert_eq!(any3.as_ref(), &Base { x: 1.0 }); let sub3 = EntityTable::::get_owned(&table, 3).unwrap(); assert_eq!(sub3.as_ref(), &Base { x: 1.0 }); }