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<BaseAnyHolder>) {
let (residual, p): (_, Record) = exchange::simple_record(input).finish().unwrap();
dbg!(&p);
assert_eq!(residual, "");
let a: PlaceHolder<BaseAnyHolder> = 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::<BaseAnyHolder>::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::<BaseAnyHolder>::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::<BaseHolder>::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::<Sub1Holder>::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();
let any1 = EntityTable::<BaseAnyHolder>::get_owned(&table, 1).unwrap();
assert_eq!(any1, BaseAny::Base(Box::new(Base { x: 1.0 })));
let any2 = EntityTable::<BaseAnyHolder>::get_owned(&table, 2).unwrap();
assert_eq!(
any2,
BaseAny::Sub1(Box::new(Sub1 {
base: Base { x: 1.0 },
y1: 2.0
}))
);
let any3 = EntityTable::<BaseAnyHolder>::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();
let any1 = EntityTable::<BaseAnyHolder>::get_owned(&table, 1).unwrap();
assert_eq!(any1.as_ref(), &Base { x: 1.0 });
let any2 = EntityTable::<BaseAnyHolder>::get_owned(&table, 2).unwrap();
assert_eq!(any2.as_ref(), &Base { x: 1.0 });
let sub2 = EntityTable::<Sub1Holder>::get_owned(&table, 2).unwrap();
assert_eq!(sub2.as_ref(), &Base { x: 1.0 });
let any3 = EntityTable::<BaseAnyHolder>::get_owned(&table, 3).unwrap();
assert_eq!(any3.as_ref(), &Base { x: 1.0 });
let sub3 = EntityTable::<Sub2Holder>::get_owned(&table, 3).unwrap();
assert_eq!(sub3.as_ref(), &Base { x: 1.0 });
}