#![allow(incomplete_features)]
#![feature(generic_const_exprs)]
use multi_array_list::MultiArrayList;
#[derive(Clone, PartialEq, Eq, Debug)]
struct Point {
x: i32,
y: i32,
}
#[derive(Clone, PartialEq, Eq, Debug)]
struct Pizza {
radius: i32,
toppings: Vec<Topping>,
}
#[derive(Clone, PartialEq, Eq, Debug)]
#[repr(u8)]
enum Topping {
Tomato,
Mozzarella,
Anchovies,
}
#[test]
fn simple_type() {
let mut points = MultiArrayList::<Point>::new();
assert_eq!(0, points.len());
let point = Point { x: 47, y: 23 };
points.push(point.clone());
assert_eq!(1, points.len());
assert_eq!(Some(&point), points.pop().as_deref());
assert_eq!(None, points.pop());
assert_eq!(None, points.pop());
}
#[test]
fn monster() {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Monster {
anim: Animation,
kind: Kind,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Animation {
x: i32,
y: i32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
enum Kind {
Snake,
Wolf,
}
let mut monsters = MultiArrayList::<Monster>::new();
let m1 = Monster {
anim: Animation { x: 3, y: 2 },
kind: Kind::Wolf,
};
monsters.push(m1);
assert_eq!(1, monsters.len());
assert_eq!(1, monsters.capacity());
let m2 = Monster {
anim: Animation { x: 17, y: 98 },
kind: Kind::Snake,
};
monsters.push(m2);
assert_eq!(2, monsters.len());
assert_eq!(2, monsters.capacity());
let m = monsters.pop();
assert_eq!(Some(&m2), m.as_deref());
assert_eq!(1, monsters.len());
assert_eq!(2, monsters.capacity());
monsters.shrink_to_fit();
assert_eq!(1, monsters.len());
assert_eq!(1, monsters.capacity());
let m = monsters.pop();
assert_eq!(Some(&m1), m.as_deref());
assert_eq!(0, monsters.len());
assert_eq!(1, monsters.capacity());
let m = monsters.pop();
assert_eq!(None, m);
assert_eq!(1, monsters.capacity());
}
#[test]
fn nested() {
let mut order = MultiArrayList::<Pizza>::new();
assert_eq!(0, order.len());
let margherita = Pizza {
radius: 12,
toppings: vec![Topping::Tomato, Topping::Mozzarella],
};
order.push(margherita);
let napoli = Pizza {
radius: 12,
toppings: vec![Topping::Tomato, Topping::Mozzarella, Topping::Anchovies],
};
order.push(napoli);
let pizza = order.pop();
assert!(pizza.is_some());
}
#[test]
fn items() {
#[derive(Clone, PartialEq, Eq, Debug)]
struct Point {
x: i32,
y: i32,
cost: Vec<u32>,
}
let mut points = MultiArrayList::<Point>::new();
assert_eq!(0, points.len());
let mut cost = vec![17];
points.push(Point {
x: 1,
y: 0,
cost: cost.clone(),
});
cost.push(18);
points.push(Point {
x: 2,
y: 0,
cost: cost.clone(),
});
cost.push(19);
points.push(Point {
x: 3,
y: 0,
cost: cost.clone(),
});
cost.push(20);
points.push(Point {
x: 4,
y: 0,
cost: cost.clone(),
});
assert_eq!(4, points.len());
let point_x = points.items::<"x", i32>();
for (xval, exp) in point_x.zip(1..) {
assert_eq!(exp, *xval);
assert!(exp <= 4);
}
let costs = points.items::<"cost", Vec<u32>>();
let start = 17;
for (idx, cost) in costs.enumerate() {
assert_eq!(idx + 1, cost.len());
for (&c, exp) in cost.iter().zip(start..) {
assert_eq!(exp, c);
}
}
}
#[test]
fn iter() {
let mut points = MultiArrayList::<Point>::new();
assert_eq!(0, points.len());
assert_eq!(0, points.iter().count());
points.push(Point { x: 1, y: 0 });
points.push(Point { x: 2, y: 0 });
points.push(Point { x: 3, y: 0 });
points.push(Point { x: 4, y: 0 });
assert_eq!(4, points.len());
let it = points.iter();
for (pt, exp) in it.zip(1..) {
assert_eq!(exp, *pt.get::<"x", _>());
assert_eq!(0, *pt.get::<"y", _>());
}
}
#[test]
fn cheese() {
// Based on the example from https://github.com/lumol-org/soa-derive
#[allow(dead_code)]
struct Cheese {
pub smell: f64,
pub color: (f64, f64, f64),
pub with_mushrooms: bool,
pub name: String,
}
impl Cheese {
fn new(name: &str) -> Cheese {
Cheese {
smell: 0.2,
color: (0., 1.0, 0.5),
with_mushrooms: false,
name: name.to_string(),
}
}
}
let mut cheeses = MultiArrayList::new();
cheeses.push(Cheese::new("stilton"));
cheeses.push(Cheese::new("brie"));
for cheese in cheeses.iter() {
let name = cheese.get::<"name", String>();
assert!(!name.is_empty());
}
for cheese_name in cheeses.items::<"name", String>() {
assert!(!cheese_name.is_empty());
}
}
#[test]
fn mutable() {
let mut order = MultiArrayList::<Pizza>::new();
let margherita = Pizza {
radius: 12,
toppings: vec![Topping::Tomato],
};
order.push(margherita);
let napoli = Pizza {
radius: 12,
toppings: vec![Topping::Tomato, Topping::Anchovies],
};
order.push(napoli);
for toppings in order.items_mut::<"toppings", Vec<Topping>>() {
toppings.push(Topping::Mozzarella);
}
for item in order.iter() {
let toppings = item.get::<"toppings", Vec<Topping>>();
assert!(toppings.contains(&Topping::Mozzarella));
}
}
#[test]
fn bigger_alignment() {
#[derive(Debug, PartialEq, Eq)]
struct Integer {
x: u128,
}
let mut numbers = MultiArrayList::<Integer>::new();
let fortytwo = Integer { x: 42 };
numbers.push(fortytwo);
assert_eq!(Some(&Integer { x: 42 }), numbers.pop().as_deref());
}
#[test]
fn many_fields() {
#[derive(Debug, Default, PartialEq, Eq)]
struct Many {
x0: u32,
x1: u32,
x2: u32,
x3: u32,
x4: u32,
x5: u32,
x6: u32,
x7: u32,
x8: u32,
x9: u32,
}
let mut numbers = MultiArrayList::<Many>::new();
let mut fortytwo = Many::default();
fortytwo.x0 = 42;
numbers.push(fortytwo);
let mut expected = Many::default();
expected.x0 = 42;
assert_eq!(Some(&expected), numbers.pop().as_deref());
}