#![warn(missing_docs)]
use std::slice::Iter;
#[doc(hidden)]
pub use slotmap as __private;
#[doc(inline)]
pub use graphlink_macros::define_schema;
#[macro_export]
macro_rules! define_id {
($name:ident) => {
$crate::__private::new_key_type! {
pub struct $name;
}
};
}
/// An arena-allocated storage collection for a specific model.
#[derive(Debug, Clone)]
pub struct Collection<K: __private::Key, V> {
inner: __private::SlotMap<K, V>,
}
impl<K: __private::Key, V> Collection<K, V> {
pub fn new() -> Self {
Self {
inner: __private::SlotMap::with_key(),
}
}
pub fn insert(&mut self, value: V) -> K {
self.inner.insert(value)
}
pub fn remove(&mut self, key: K) -> Option<V> {
self.inner.remove(key)
}
pub fn get(&self, key: K) -> Option<&V> {
self.inner.get(key)
}
pub fn get_mut(&mut self, key: K) -> Option<&mut V> {
self.inner.get_mut(key)
}
}
impl<K: __private::Key, V> Default for Collection<K, V> {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct HasMany<K: __private::Key> {
children: Vec<K>,
}
impl<K: __private::Key> HasMany<K> {
pub fn new() -> Self {
Self {
children: Vec::new(),
}
}
pub fn iter(&self) -> Iter<'_, K> {
self.children.iter()
}
pub fn push(&mut self, id: K) {
self.children.push(id);
}
pub fn remove(&mut self, id: K) {
self.children.retain(|&x| x != id);
}
}
impl<K: __private::Key> Default for HasMany<K> {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct BelongsTo<K: __private::Key> {
parent_id: K,
}
impl<K: __private::Key> BelongsTo<K> {
pub fn new(parent_id: K) -> Self {
Self { parent_id }
}
pub fn id(&self) -> K {
self.parent_id
}
}
#[cfg(test)]
mod tests {
use super::*;
define_id!(TestId);
#[test]
fn test_collection_lifecycle() {
let mut collection: Collection<TestId, String> = Collection::new();
let id = collection.insert("Hello".to_string());
assert!(collection.get(id).is_some());
assert_eq!(collection.get(id).unwrap(), "Hello");
if let Some(val) = collection.get_mut(id) {
*val = "World".to_string();
}
assert_eq!(collection.get(id).unwrap(), "World");
let removed = collection.remove(id);
assert_eq!(removed.unwrap(), "World");
assert!(collection.get(id).is_none());
}
#[test]
fn test_has_many_management() {
let mut rel: HasMany<TestId> = HasMany::new();
let dummy_id = TestId::default();
rel.push(dummy_id);
assert_eq!(rel.iter().count(), 1);
rel.remove(dummy_id);
assert_eq!(rel.iter().count(), 0);
}
}