remediate 0.2.1

Library for thinking and learning
Documentation
mod cards;
pub mod document;
use crate::{
    archive::Cast,
    loc, loc_root, root,
    workspace::{AsComponents, Component, IntoComponents, Root, Workspace, WorkspaceRoot},
    RemedyRoot,
};
use rkyv::{ser::serializers::AllocSerializer, ser::Serializer, Archive, Deserialize, Serialize};
use std::{
    collections::{BTreeMap, HashSet},
    rc::Rc,
    str::from_utf8,
};

pub use document::{Content, Group, Segment, Text};
use rkyv::de::deserializers::SharedDeserializeMap;

use self::document::Document;

root!(pub type DeckRoot: RemedyRoot = ["decks"]);

type Cards = BTreeMap<Rc<str>, Card>;

type DeckSerializer = AllocSerializer<1024>;

#[derive(Archive, Serialize, Deserialize, Debug)]
#[archive_attr(derive(Debug))]
pub struct Deck {
    cards: Cards,
}

impl Deck {
    pub fn cards(&self) -> &Cards {
        &self.cards
    }

    pub fn all<W: Workspace>(
        workspace: &W,
    ) -> impl Iterator<Item = (Self, Rc<[W::Component]>)> + '_ {
        workspace
            .descendants_from::<DeckRoot, _>(())
            .into_iter()
            .map(move |location| {
                (
                    Self::deserialize(workspace.read::<DeckRoot, _>(location.clone())),
                    location,
                )
            })
    }

    pub fn save<W: Workspace>(&self, workspace: &W, location: &[W::Component]) {
        let mut serializer = DeckSerializer::default();
        serializer.serialize_value(self).unwrap();

        let bytes = serializer.into_serializer().into_inner();
        workspace.write::<DeckRoot, _>(location, &bytes[..]);
    }

    pub fn parse<W: Workspace>(workspace: &W, location: &[W::Component]) -> Self {
        let input = workspace.read::<WorkspaceRoot, _>(location);
        let document = Document::parse(from_utf8(input.as_ref()).unwrap()).unwrap();
        document.into()
    }

    fn deserialize(bytes: Rc<[u8]>) -> Self {
        (bytes.cast() as Rc<ArchivedDeck>)
            .as_ref()
            .deserialize(&mut SharedDeserializeMap::new())
            .unwrap()
    }
}

impl From<Document> for Deck {
    fn from(value: Document) -> Self {
        let mut cards = Cards::new();
        for rem in value.rems().iter() {
            rem.insert_into(&mut cards, 0);
        }
        Self { cards }
    }
}

impl ArchivedDeck {
    pub fn get_card(&self, id: &str) -> Card {
        self.cards
            .get(id)
            .unwrap()
            .deserialize(&mut SharedDeserializeMap::new())
            .unwrap()
    }

    pub fn load<W: Workspace>(workspace: &W, location: &[W::Component]) -> Rc<Self> {
        workspace.read::<DeckRoot, _>(location).cast()
    }
}

type Rems = Vec<(usize, Vec<Content>)>;

#[derive(Archive, Serialize, Deserialize, Debug)]
#[archive_attr(derive(Debug))]
pub struct Card {
    rems: Rems,
}

impl Card {
    pub fn groups(&self) -> HashSet<Group> {
        let mut set = HashSet::new();
        for (_, rem) in self.rems.iter() {
            for group in rem.iter().filter_map(Content::group) {
                set.insert(group);
            }
        }
        set
    }

    pub fn rems(&self) -> &Rems {
        &self.rems
    }
}

impl Extend<(usize, Vec<Content>)> for Card {
    fn extend<T: IntoIterator<Item = (usize, Vec<Content>)>>(&mut self, iter: T) {
        self.rems.extend(iter);
    }
}

impl<const N: usize> From<[(usize, Vec<Content>); N]> for Card {
    fn from(value: [(usize, Vec<Content>); N]) -> Self {
        Card {
            rems: Vec::from(value),
        }
    }
}

pub type CardId = (Rc<str>, Group);