#![cfg(feature = "storage")]
use core::num::NonZeroU32;
use pipecircuit::storage::warp_table::{
Capacity, WarpId, WarpTable, WarpTableGetOutcome, WarpTableInsertAllOutcome,
WarpTableInsertOutcome, WarpTableInsertWithIdOutcome, WarpTableRow, WarpTableUpdateOutcome,
WarpTableUpsertOutcome,
};
#[cfg(feature = "secondary-indexes")]
use pipecircuit::storage::warp_table::{
RangeIndexKey, WarpTableRemoveOutcome, WarpTableRowRelocation,
};
#[derive(WarpTableRow)]
struct Pet {
name: &'static str,
age: u8,
}
#[derive(Debug, Eq, WarpTableRow, PartialEq)]
#[index(primary = u64)]
struct ImportedPet {
name: &'static str,
}
#[cfg(feature = "secondary-indexes")]
#[derive(WarpTableRow)]
struct CategorizedPet {
name: &'static str,
#[index(secondary, range)]
pub age: u8,
}
#[cfg(feature = "secondary-indexes")]
#[derive(WarpTableRow)]
#[index(primary = u64)]
struct ImportedCategorizedPet {
name: &'static str,
#[index(secondary)]
pub age: u8,
}
#[cfg(feature = "secondary-indexes")]
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, RangeIndexKey)]
struct Age(u8);
#[cfg(feature = "secondary-indexes")]
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, RangeIndexKey)]
struct Temperature {
degrees: i16,
}
#[cfg(feature = "secondary-indexes")]
#[derive(WarpTableRow)]
struct MeasuredPet {
name: &'static str,
#[index(range)]
age: Age,
#[index(range)]
temperature: Temperature,
}
#[cfg(feature = "secondary-indexes")]
#[derive(WarpTableRow)]
struct Owner {
name: &'static str,
}
#[cfg(feature = "secondary-indexes")]
#[derive(WarpTableRow)]
struct OwnedPet {
name: &'static str,
#[index(secondary)]
owner: WarpId<Owner>,
}
#[test]
fn default_ids_are_typed_generated_and_directly_available() -> Result<(), &'static str> {
let capacity = Capacity::new(NonZeroU32::new(2).ok_or("capacity was zero")?);
let mut pets =
WarpTable::<Pet>::try_new(capacity).map_err(|_| "pet storage was unavailable")?;
let WarpTableInsertOutcome::Inserted { key: luna_id, .. } = pets.insert(Pet {
name: "Luna",
age: 4,
}) else {
return Err("Luna could not be inserted");
};
assert_eq!(luna_id, WarpId::<Pet>::MIN);
let WarpTableGetOutcome::Present { row } = pets.get(luna_id) else {
return Err("Luna was unavailable");
};
assert_eq!(*row.id, luna_id);
assert_eq!(*row.name, "Luna");
assert_eq!(row.age, &4);
assert_eq!(
pets.update(luna_id, |mut pet| {
let previous = (*pet.name(), *pet.age());
*pet.name_mut() = "Luna II";
*pet.age_mut() = 5;
previous
}),
WarpTableUpdateOutcome::Updated {
key: luna_id,
row: 0,
output: ("Luna", 4),
}
);
let WarpTableGetOutcome::Present { row } = pets.get(luna_id) else {
return Err("updated Luna was unavailable");
};
assert_eq!((*row.name, *row.age), ("Luna II", 5));
Ok(())
}
#[test]
fn an_existing_primary_id_slots_in_explicitly() -> Result<(), &'static str> {
let capacity = Capacity::new(NonZeroU32::MIN);
let mut pets = WarpTable::<ImportedPet>::try_new(capacity)
.map_err(|_| "imported pet storage was unavailable")?;
let WarpTableInsertWithIdOutcome::Inserted { key, .. } =
pets.insert_with_id(42, ImportedPet { name: "Milo" })
else {
return Err("Milo could not be inserted");
};
assert_eq!(key, 42);
let WarpTableGetOutcome::Present { row, .. } = pets.get(42) else {
return Err("Milo was unavailable");
};
assert_eq!(*row.name, "Milo");
Ok(())
}
#[test]
fn upsert_inserts_replaces_at_capacity_and_returns_rejected_rows() -> Result<(), &'static str> {
let capacity = Capacity::new(NonZeroU32::MIN);
let mut pets = WarpTable::<ImportedPet>::try_new(capacity)
.map_err(|_| "imported pet storage was unavailable")?;
assert_eq!(
pets.upsert(42, ImportedPet { name: "Luna" }),
WarpTableUpsertOutcome::Inserted { key: 42, row: 0 }
);
assert_eq!(
pets.upsert(42, ImportedPet { name: "Luna II" }),
WarpTableUpsertOutcome::Replaced {
key: 42,
row: 0,
previous: ImportedPet { name: "Luna" },
}
);
assert_eq!(
pets.upsert(7, ImportedPet { name: "Milo" }),
WarpTableUpsertOutcome::Full {
key: 7,
rejected: ImportedPet { name: "Milo" },
}
);
let WarpTableGetOutcome::Present { row } = pets.get(42) else {
return Err("upserted pet was unavailable");
};
assert_eq!(*row.name, "Luna II");
Ok(())
}
#[cfg(feature = "secondary-indexes")]
#[test]
fn branded_ids_are_secondary_index_keys_across_tables() -> Result<(), &'static str> {
let capacity = Capacity::new(NonZeroU32::MIN);
let mut owners =
WarpTable::<Owner>::try_new(capacity).map_err(|_| "owner storage was unavailable")?;
let WarpTableInsertOutcome::Inserted { key: owner_id, .. } =
owners.insert(Owner { name: "Ken" })
else {
return Err("owner could not be inserted");
};
let mut pets =
WarpTable::<OwnedPet>::try_new(capacity).map_err(|_| "pet storage was unavailable")?;
let WarpTableInsertOutcome::Inserted { .. } = pets.insert(OwnedPet {
name: "Luna",
owner: owner_id,
}) else {
return Err("pet could not be inserted");
};
let mut matches = pets.query().find_owner(owner_id).rows();
let Some(pet) = matches.next() else {
return Err("owned pet was unavailable");
};
assert_eq!((*pet.name, *pet.owner), ("Luna", owner_id));
assert!(matches.next().is_none());
Ok(())
}
#[test]
fn bulk_insertion_observes_every_generated_id_and_rejected_row() -> Result<(), &'static str> {
let capacity = Capacity::new(NonZeroU32::new(2).ok_or("capacity was zero")?);
let mut pets =
WarpTable::<Pet>::try_new(capacity).map_err(|_| "pet storage was unavailable")?;
let mut inserted = Vec::new();
let mut rejected = Vec::new();
let outcome = pets.insert_all(
[
Pet {
name: "Luna",
age: 4,
},
Pet {
name: "Milo",
age: 7,
},
Pet {
name: "Suki",
age: 9,
},
],
|outcome| match outcome {
WarpTableInsertOutcome::Inserted { key, .. } => inserted.push(key),
WarpTableInsertOutcome::Full { rejected: pet }
| WarpTableInsertOutcome::IdentifiersExhausted { rejected: pet } => {
rejected.push(pet.name);
}
},
);
assert_eq!(outcome, WarpTableInsertAllOutcome::Completed);
assert_eq!(inserted.len(), 2);
assert_eq!(rejected, ["Suki"]);
assert_eq!(pets.len(), 2);
Ok(())
}
#[test]
fn bulk_caller_ids_preserve_duplicate_and_capacity_outcomes() -> Result<(), &'static str> {
let capacity = Capacity::new(NonZeroU32::new(2).ok_or("capacity was zero")?);
let mut pets = WarpTable::<ImportedPet>::try_new(capacity)
.map_err(|_| "imported pet storage was unavailable")?;
let mut inserted = Vec::new();
let mut rejected = Vec::new();
let outcome = pets.insert_all_with_id(
[
(42, ImportedPet { name: "Luna" }),
(42, ImportedPet { name: "Duplicate" }),
(7, ImportedPet { name: "Milo" }),
(9, ImportedPet { name: "Suki" }),
],
|outcome| match outcome {
WarpTableInsertWithIdOutcome::Inserted { key, .. } => inserted.push(key),
WarpTableInsertWithIdOutcome::AlreadyPresent {
key, rejected: pet, ..
}
| WarpTableInsertWithIdOutcome::Full { key, rejected: pet } => {
rejected.push((key, pet.name));
}
},
);
assert_eq!(outcome, WarpTableInsertAllOutcome::Completed);
assert_eq!(inserted, [42, 7]);
assert_eq!(rejected, [(42, "Duplicate"), (9, "Suki")]);
assert_eq!(pets.len(), 2);
Ok(())
}
#[test]
fn logical_rows_scan_in_dense_order_with_identity() -> Result<(), &'static str> {
let capacity = Capacity::new(NonZeroU32::new(2).ok_or("capacity was zero")?);
let mut pets =
WarpTable::<Pet>::try_new(capacity).map_err(|_| "pet storage was unavailable")?;
let WarpTableInsertOutcome::Inserted { key: luna_id, .. } = pets.insert(Pet {
name: "Luna",
age: 4,
}) else {
return Err("Luna could not be inserted");
};
let WarpTableInsertOutcome::Inserted { key: milo_id, .. } = pets.insert(Pet {
name: "Milo",
age: 7,
}) else {
return Err("Milo could not be inserted");
};
let mut rows = pets.rows();
assert_eq!(rows.len(), 2);
let Some(first) = rows.next() else {
return Err("first logical row was unavailable");
};
assert_eq!((*first.id, first.name, first.age), (luna_id, &"Luna", &4));
assert_eq!(rows.len(), 1);
let Some(second) = rows.next() else {
return Err("second logical row was unavailable");
};
assert_eq!(
(*second.id, second.name, second.age),
(milo_id, &"Milo", &7)
);
assert_eq!(rows.len(), 0);
assert!(rows.next().is_none());
assert!(rows.next().is_none());
Ok(())
}
#[cfg(feature = "secondary-indexes")]
#[test]
fn range_key_wrappers_preserve_their_inner_ordering() -> Result<(), &'static str> {
assert_eq!(Age::BITS, u8::BITS);
assert_eq!(Age(7).ordered_word(), 7);
assert!(Temperature { degrees: -1 }.ordered_word() < Temperature { degrees: 1 }.ordered_word());
let capacity = Capacity::new(NonZeroU32::new(2).ok_or("capacity was zero")?);
let mut pets = WarpTable::<MeasuredPet>::try_new(capacity)
.map_err(|_| "measured pet storage was unavailable")?;
for (name, age, degrees) in [("Luna", 4, -2), ("Milo", 7, 3)] {
let WarpTableInsertOutcome::Inserted { .. } = pets.insert(MeasuredPet {
name,
age: Age(age),
temperature: Temperature { degrees },
}) else {
return Err("measured pet could not be inserted");
};
}
let ages = pets
.query()
.find_age_in(Age(4)..=Age(6))
.map_err(|_| "age range was unavailable")?;
let Some(luna) = ages.rows().next() else {
return Err("Luna was absent from the wrapped range");
};
assert_eq!((*luna.name, *luna.age), ("Luna", Age(4)));
Ok(())
}
#[cfg(feature = "secondary-indexes")]
#[test]
fn a_secondary_field_generates_an_external_lookup_surface() -> Result<(), &'static str> {
let capacity = Capacity::new(NonZeroU32::MIN);
let mut pets = WarpTable::<CategorizedPet>::try_new(capacity)
.map_err(|_| "categorized pet storage was unavailable")?;
let WarpTableInsertOutcome::Inserted {
key,
row: dense_row,
} = pets.insert(CategorizedPet {
name: "Luna",
age: 4,
})
else {
return Err("categorized pet could not be inserted");
};
assert_eq!(dense_row, 0);
let selection = pets.query().find_age(4);
assert_eq!(selection.len(), 1);
let Some(row) = selection.rows().next() else {
return Err("age membership did not resolve to Luna");
};
assert_eq!(*row.id, key);
assert_eq!((row.name, row.age), (&"Luna", &4));
let ranged = pets
.query()
.find_age_in(3..5)
.map_err(|_| "age range index was inconsistent")?;
assert_eq!(ranged.len(), 1);
let WarpTableGetOutcome::Present { row, .. } = pets.get(key) else {
return Err("Luna was unavailable by primary key");
};
assert_eq!(row.name, &"Luna");
assert_eq!(row.age, &4);
Ok(())
}
#[cfg(feature = "secondary-indexes")]
#[test]
fn caller_owned_ids_flow_through_secondary_queries() -> Result<(), &'static str> {
let capacity = Capacity::new(NonZeroU32::new(2).ok_or("capacity was zero")?);
let mut pets = WarpTable::<ImportedCategorizedPet>::try_new(capacity)
.map_err(|_| "imported pet storage was unavailable")?;
for (id, name) in [(42, "Luna"), (9001, "Milo")] {
let WarpTableInsertWithIdOutcome::Inserted { key, .. } =
pets.insert_with_id(id, ImportedCategorizedPet { name, age: 4 })
else {
return Err("imported pet could not be inserted");
};
assert_eq!(key, id);
}
let selection = pets.query().find_age(4);
let mut rows = selection.rows();
assert_eq!(rows.size_hint(), (2, Some(2)));
#[cfg(target_pointer_width = "64")]
assert_eq!(rows.len(), 2);
let Some(row) = rows.next_back() else {
return Err("last imported pet was unavailable");
};
assert_eq!((*row.id, row.name), (9001, &"Milo"));
assert_eq!(rows.size_hint(), (1, Some(1)));
#[cfg(target_pointer_width = "64")]
assert_eq!(rows.len(), 1);
let Some(row) = rows.next() else {
return Err("first imported pet was unavailable");
};
assert_eq!((*row.id, row.name), (42, &"Luna"));
assert!(rows.next().is_none());
assert!(rows.next_back().is_none());
assert!(matches!(
pets.remove(42),
WarpTableRemoveOutcome::Removed {
key: 42,
relocation: WarpTableRowRelocation::Relocated {
key: 9001,
from: 1,
to: 0,
},
..
}
));
let selection = pets.query().find_age(4);
let Some(row) = selection.rows().next() else {
return Err("relocated imported pet was unavailable");
};
assert_eq!((*row.id, row.name), (9001, &"Milo"));
Ok(())
}