From 4139c98917164d2c52e3a89f35ec980da64daa95 Mon Sep 17 00:00:00 2001 From: trivernis Date: Sun, 30 Aug 2020 18:43:15 +0200 Subject: [PATCH] Add BibRef manager, entries and anchors --- .idea/discord.xml | 6 +++ src/lib.rs | 18 +++++++- src/references/anchor.rs | 64 +++++++++++++++++++++++++++++ src/references/bib_reference.rs | 13 ++++++ src/references/mod.rs | 3 ++ src/references/reference_manager.rs | 23 +++++++++++ 6 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 .idea/discord.xml create mode 100644 src/references/anchor.rs create mode 100644 src/references/bib_reference.rs create mode 100644 src/references/mod.rs create mode 100644 src/references/reference_manager.rs diff --git a/.idea/discord.xml b/.idea/discord.xml new file mode 100644 index 0000000..cd711a0 --- /dev/null +++ b/.idea/discord.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 31e1bb2..f03d154 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,21 @@ +pub mod references; + #[cfg(test)] mod tests { + use crate::references::reference_manager::BibRefManager; + use crate::references::bib_reference::BibRef; + #[test] - fn it_works() { - assert_eq!(2 + 2, 4); + fn it_inserts_and_flattens() { + let manager = BibRefManager::new(); + let root_anchor = manager.root_anchor(); + let mut root_anchor = root_anchor.lock().unwrap(); + root_anchor.insert(BibRef::new("test".to_string())); + let child_anchor = root_anchor.create_anchor(); + child_anchor.lock().unwrap().insert(BibRef::new("test2".to_string())); + child_anchor.lock().unwrap().insert(BibRef::new("test3".to_string())); + root_anchor.flatten(); + + assert_eq!(root_anchor.references().len(), 3) } } diff --git a/src/references/anchor.rs b/src/references/anchor.rs new file mode 100644 index 0000000..adca40b --- /dev/null +++ b/src/references/anchor.rs @@ -0,0 +1,64 @@ +use crate::references::bib_reference::BibRef; +use std::sync::{Arc, Mutex}; + +/// A bib list anchor that can be used to concurrently insert entries into a list +#[derive(Clone, Debug)] +pub struct BibListAnchor { + entries: Vec, +} + +/// Enum that represents a single entry of a bib list +#[derive(Clone, Debug)] +enum BibListEntry { + Ref(BibRef), + Anchor(Arc>), +} + +impl BibListAnchor { + /// Creates a new empty BibListAnchor. + pub fn new() -> Self { + Self { + entries: Vec::new(), + } + } + + /// Inserts a reference at the current position + pub fn insert(&mut self, bib_ref: BibRef) { + self.entries.push(BibListEntry::Ref(bib_ref)) + } + + /// Creates a new anchor at the current position and inserts it into the entry vec. + pub fn create_anchor(&mut self) -> Arc> { + let anchor = Arc::new(Mutex::new(BibListAnchor::new())); + self.entries.push(BibListEntry::Anchor(Arc::clone(&anchor))); + + anchor + } + + /// Flattens the inner entry structure by inserting the elements of child anchors for every + /// anchor in the vector + pub fn flatten(&mut self) { + let mut new_entries = Vec::with_capacity(self.entries.len()); + self.entries.iter_mut().for_each(|e| { + match e { + BibListEntry::Anchor(a) => { + let mut anchor = a.lock().unwrap(); + anchor.flatten(); + new_entries.append(&mut anchor.entries); + } + BibListEntry::Ref(bib_ref) => new_entries.push(BibListEntry::Ref(bib_ref.clone())) + } + }); + + self.entries = new_entries; + } + + /// Returns all references that are contained in the entry list + pub fn references(&self) -> Vec { + self.entries.iter().filter_map(|e| if let BibListEntry::Ref(r) = e { + Some(r.clone()) + } else { + None + }).collect() + } +} \ No newline at end of file diff --git a/src/references/bib_reference.rs b/src/references/bib_reference.rs new file mode 100644 index 0000000..854139e --- /dev/null +++ b/src/references/bib_reference.rs @@ -0,0 +1,13 @@ +#[derive(Clone, Debug)] +pub struct BibRef { + key: String, +} + +impl BibRef { + /// Creates a new BibRef with a given key + pub fn new(key: String) -> Self { + Self { + key + } + } +} \ No newline at end of file diff --git a/src/references/mod.rs b/src/references/mod.rs new file mode 100644 index 0000000..653240e --- /dev/null +++ b/src/references/mod.rs @@ -0,0 +1,3 @@ +pub mod reference_manager; +pub mod bib_reference; +pub mod anchor; \ No newline at end of file diff --git a/src/references/reference_manager.rs b/src/references/reference_manager.rs new file mode 100644 index 0000000..3b8b133 --- /dev/null +++ b/src/references/reference_manager.rs @@ -0,0 +1,23 @@ +use std::sync::{Arc, Mutex}; +use crate::references::anchor::BibListAnchor; + +/// The root manager for references that should be used for further reference operations that +/// go beyond insertion. +#[derive(Clone, Debug)] +pub struct BibRefManager { + root_anchor: Arc>, +} + +impl BibRefManager { + /// Creates a new BibRefManager with an empty root anchor + pub fn new() -> Self { + Self { + root_anchor: Arc::new(Mutex::new(BibListAnchor::new())) + } + } + + /// Returns the BibRefManagers root anchor that. + pub fn root_anchor(&self) -> Arc> { + Arc::clone(&self.root_anchor) + } +} \ No newline at end of file