selene-core 0.5.0

selene-core is the backend for Selene, a local-first music player
Documentation
use std::convert::Infallible;

use lunar_lib::database::{
    CompareAndSwapTransaction, CustomTransactionError, DatabaseEntry, DatabaseError,
    TransactionError, Tree,
};

use crate::{
    database::{Createable, LibraryDb, collection_tree},
    library::collection::{
        Collectable, Collection, CollectionId, CollectionType, DynamicCollectionRules,
    },
};

impl DatabaseEntry for Collection {
    type Id = CollectionId;
    type EntryDb = LibraryDb;

    const VERSION_NUMBER: u32 = 1;

    fn tree(db: &Self::EntryDb) -> Tree {
        collection_tree(db)
    }

    fn id(&self) -> Self::Id {
        self.id
    }

    fn read_only(&self) -> bool {
        self.read_only
    }
}

#[derive(Debug, Clone)]
pub struct CollectionCreateArgs {
    name: String,
    collection_type: CollectionType,
}

impl CollectionCreateArgs {
    pub fn new(name: impl Into<String>) -> Self {
        Self {
            name: name.into(),
            collection_type: CollectionType::Static {
                collectables: Vec::new(),
            },
        }
    }

    pub fn with_items(mut self, items: Vec<Collectable>) -> Self {
        self.collection_type = CollectionType::Static {
            collectables: items,
        };
        self
    }

    pub fn with_rules(mut self, rules: Vec<DynamicCollectionRules>) -> Self {
        self.collection_type = CollectionType::Dynamic { rules };
        self
    }
}

impl Createable for Collection {
    type CreateArgs = CollectionCreateArgs;
    type Err = Infallible;

    fn tx_create(
        cas_tx: &mut CompareAndSwapTransaction<Self::EntryDb>,
        args: Self::CreateArgs,
    ) -> Result<Self, CustomTransactionError<Self::Err>> {
        let mut collection = Collection::new_static(args.name).map_err(|err| {
            TransactionError::Database(DatabaseError::InvalidInput(err.to_string()))
        })?;

        if cas_tx.tx_get(collection.id())?.is_some() {
            return Err(TransactionError::Database(DatabaseError::AlreadyInDatabase).into());
        }

        collection.items = args.collection_type;

        Ok(collection)
    }
}