From 1f3b5262b80a2fbb4ea9e54c5fbad089bcfa9e38 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sun, 29 Oct 2023 21:19:30 -0400 Subject: [PATCH] Fix build by making the registry guarded by an ArcMutex. --- src/intermediate/definition.rs | 11 +-- src/intermediate/footnote_definition.rs | 10 +- src/intermediate/footnote_reference.rs | 6 +- src/intermediate/heading.rs | 4 +- src/intermediate/macros.rs | 14 +-- src/intermediate/mod.rs | 3 + src/intermediate/page.rs | 21 +++-- src/intermediate/paragraph.rs | 2 +- src/intermediate/plain_list.rs | 2 +- src/intermediate/plain_list_item.rs | 4 +- src/intermediate/quote_block.rs | 2 +- src/intermediate/registry.rs | 119 +++++++++++++----------- src/intermediate/regular_link.rs | 2 +- src/intermediate/section.rs | 2 +- src/intermediate/target.rs | 1 + 15 files changed, 113 insertions(+), 90 deletions(-) diff --git a/src/intermediate/definition.rs b/src/intermediate/definition.rs index 6e21bb6..4b58d8e 100644 --- a/src/intermediate/definition.rs +++ b/src/intermediate/definition.rs @@ -1,5 +1,7 @@ use std::path::Path; use std::path::PathBuf; +use std::sync::Arc; +use std::sync::Mutex; use tokio::task::JoinHandle; use walkdir::WalkDir; @@ -58,14 +60,11 @@ impl BlogPost { _ => {} }); + let registry = Arc::new(Mutex::new(registry)); let relative_to_post_dir_path = real_path.strip_prefix(post_dir)?; ret.push( - BlogPostPage::new( - relative_to_post_dir_path, - &mut registry, - parsed_document, - ) - .await?, + BlogPostPage::new(relative_to_post_dir_path, registry, parsed_document) + .await?, ); } ret diff --git a/src/intermediate/footnote_definition.rs b/src/intermediate/footnote_definition.rs index 6049f14..4d0ae61 100644 --- a/src/intermediate/footnote_definition.rs +++ b/src/intermediate/footnote_definition.rs @@ -1,7 +1,9 @@ use super::macros::intermediate; +use super::registry::register_footnote_definition; use super::registry::Registry; use super::IAstNode; use crate::error::CustomError; +use crate::intermediate::RefRegistry; #[derive(Debug, Clone)] pub(crate) struct IFootnoteDefinition {} @@ -12,9 +14,7 @@ intermediate!( original, registry, { - registry - .register_footnote_definition(original.label, &original.children) - .await?; + register_footnote_definition(registry, original.label, &original.children).await?; Ok(IFootnoteDefinition {}) } ); @@ -26,8 +26,8 @@ pub(crate) struct IRealFootnoteDefinition { } impl IRealFootnoteDefinition { - pub(crate) async fn new<'reg, 'orig, 'parse>( - registry: &'reg mut Registry<'orig, 'parse>, + pub(crate) async fn new<'orig, 'parse>( + registry: RefRegistry<'orig, 'parse>, footnote_id: usize, contents: Vec, ) -> Result { diff --git a/src/intermediate/footnote_reference.rs b/src/intermediate/footnote_reference.rs index aabd7e9..c63966b 100644 --- a/src/intermediate/footnote_reference.rs +++ b/src/intermediate/footnote_reference.rs @@ -1,4 +1,5 @@ use super::macros::intermediate; +use super::registry::get_footnote_reference_id; use super::registry::Registry; use crate::error::CustomError; @@ -9,9 +10,8 @@ pub(crate) struct IFootnoteReference { } intermediate!(IFootnoteReference, FootnoteReference, original, registry, { - let footnote_id = registry - .get_footnote_reference_id(original.label, &original.definition) - .await?; + let footnote_id = + get_footnote_reference_id(registry, original.label, &original.definition).await?; Ok(IFootnoteReference { footnote_id, duplicate_offset: 0, // TODO diff --git a/src/intermediate/heading.rs b/src/intermediate/heading.rs index 8236652..716545f 100644 --- a/src/intermediate/heading.rs +++ b/src/intermediate/heading.rs @@ -15,14 +15,14 @@ intermediate!(IHeading, Heading, original, registry, { let title = { let mut ret = Vec::new(); for obj in original.title.iter() { - ret.push(IObject::new(registry, obj).await?); + ret.push(IObject::new(registry.clone(), obj).await?); } ret }; let children = { let mut ret = Vec::new(); for obj in original.children.iter() { - ret.push(IDocumentElement::new(registry, obj).await?); + ret.push(IDocumentElement::new(registry.clone(), obj).await?); } ret }; diff --git a/src/intermediate/macros.rs b/src/intermediate/macros.rs index bd982e0..f7b6236 100644 --- a/src/intermediate/macros.rs +++ b/src/intermediate/macros.rs @@ -8,7 +8,7 @@ macro_rules! inoop { impl $istruct { pub(crate) async fn new<'reg, 'orig, 'parse>( - registry: &'reg mut Registry<'orig, 'parse>, + registry: crate::intermediate::RefRegistry<'orig, 'parse>, original: &'orig organic::types::$pstruct<'parse>, ) -> Result<$istruct, CustomError> { Ok($istruct {}) @@ -25,8 +25,8 @@ pub(crate) use inoop; macro_rules! intermediate { ($istruct:ident, $pstruct:ident, $original:ident, $registry:ident, $fnbody:tt) => { impl $istruct { - pub(crate) async fn new<'reg, 'orig, 'parse>( - registry: &'reg mut Registry<'orig, 'parse>, + pub(crate) async fn new<'orig, 'parse>( + registry: crate::intermediate::RefRegistry<'orig, 'parse>, original: &'orig organic::types::$pstruct<'parse>, ) -> Result<$istruct, CustomError> { let $original = original; @@ -45,10 +45,10 @@ pub(crate) use intermediate; macro_rules! iselector { ($istruct:ident, $pstruct:ident, $original:ident, $registry:ident, $fnbody:tt) => { impl $istruct { - pub(crate) fn new<'reg: 'orig, 'orig, 'parse, 'inp: 'reg + 'orig>( - registry: &'reg mut Registry<'orig, 'parse>, + pub(crate) fn new<'orig, 'parse>( + registry: crate::intermediate::RefRegistry<'orig, 'parse>, original: &'orig organic::types::$pstruct<'parse>, - ) -> BoxFuture<'inp, Result<$istruct, CustomError>> { + ) -> BoxFuture<'orig, Result<$istruct, CustomError>> { let $registry = registry; let $original = original; async move { $fnbody }.boxed() @@ -64,7 +64,7 @@ macro_rules! iitem { match $original { $( $penum(inner) => Ok($ienum( - $istruct::new($registry, inner).await?, + $istruct::new($registry.clone(), inner).await?, )), )* } diff --git a/src/intermediate/mod.rs b/src/intermediate/mod.rs index bd8e38a..f228fdb 100644 --- a/src/intermediate/mod.rs +++ b/src/intermediate/mod.rs @@ -124,3 +124,6 @@ pub(crate) use timestamp::ITimestamp; pub(crate) use underline::IUnderline; pub(crate) use verbatim::IVerbatim; pub(crate) use verse_block::IVerseBlock; + +pub(crate) type RefRegistry<'orig, 'parse> = + std::sync::Arc>>; diff --git a/src/intermediate/page.rs b/src/intermediate/page.rs index 957a1ad..404852e 100644 --- a/src/intermediate/page.rs +++ b/src/intermediate/page.rs @@ -7,6 +7,7 @@ use super::registry::Registry; use super::IDocumentElement; use super::IHeading; use super::ISection; +use super::RefRegistry; #[derive(Debug)] pub(crate) struct BlogPostPage { @@ -24,30 +25,34 @@ impl BlogPostPage { // TODO: Move path into the registry so I can give this a standard interface like the others. pub(crate) async fn new<'a, 'b, 'parse, P: Into>( path: P, - registry: &'a mut Registry<'b, 'parse>, + registry: RefRegistry<'b, 'parse>, document: &'b organic::types::Document<'parse>, ) -> Result { let path = path.into(); let mut children = Vec::new(); if let Some(section) = document.zeroth_section.as_ref() { children.push(IDocumentElement::Section( - ISection::new(registry, section).await?, + ISection::new(registry.clone(), section).await?, )); } for heading in document.children.iter() { children.push(IDocumentElement::Heading( - IHeading::new(registry, heading).await?, + IHeading::new(registry.clone(), heading).await?, )); } let footnotes = { - let footnote_definitions: Vec<_> = registry - .get_footnote_ids() - .map(|(id, def)| (id, def.clone())) - .collect(); + let footnote_definitions: Vec<_> = { + let registry = registry.lock().unwrap(); + let ret = registry + .get_footnote_ids() + .map(|(id, def)| (id, def.clone())) + .collect(); + ret + }; let mut ret = Vec::new(); for (id, def) in footnote_definitions.into_iter() { - ret.push(IRealFootnoteDefinition::new(registry, id, def).await?); + ret.push(IRealFootnoteDefinition::new(registry.clone(), id, def).await?); } ret }; diff --git a/src/intermediate/paragraph.rs b/src/intermediate/paragraph.rs index 90df531..675f22e 100644 --- a/src/intermediate/paragraph.rs +++ b/src/intermediate/paragraph.rs @@ -12,7 +12,7 @@ intermediate!(IParagraph, Paragraph, original, registry, { let children = { let mut ret = Vec::new(); for obj in original.children.iter() { - ret.push(IObject::new(registry, obj).await?); + ret.push(IObject::new(registry.clone(), obj).await?); } ret }; diff --git a/src/intermediate/plain_list.rs b/src/intermediate/plain_list.rs index 2b208a1..5a4e62b 100644 --- a/src/intermediate/plain_list.rs +++ b/src/intermediate/plain_list.rs @@ -13,7 +13,7 @@ intermediate!(IPlainList, PlainList, original, registry, { let children = { let mut ret = Vec::new(); for obj in original.children.iter() { - ret.push(IPlainListItem::new(registry, obj).await?); + ret.push(IPlainListItem::new(registry.clone(), obj).await?); } ret }; diff --git a/src/intermediate/plain_list_item.rs b/src/intermediate/plain_list_item.rs index 774c838..8bb03da 100644 --- a/src/intermediate/plain_list_item.rs +++ b/src/intermediate/plain_list_item.rs @@ -14,7 +14,7 @@ intermediate!(IPlainListItem, PlainListItem, original, registry, { let tag = { let mut ret = Vec::new(); for obj in original.tag.iter() { - ret.push(IObject::new(registry, obj).await?); + ret.push(IObject::new(registry.clone(), obj).await?); } ret }; @@ -22,7 +22,7 @@ intermediate!(IPlainListItem, PlainListItem, original, registry, { let children = { let mut ret = Vec::new(); for elem in original.children.iter() { - ret.push(IElement::new(registry, elem).await?); + ret.push(IElement::new(registry.clone(), elem).await?); } ret }; diff --git a/src/intermediate/quote_block.rs b/src/intermediate/quote_block.rs index 0a74a35..82ad4ed 100644 --- a/src/intermediate/quote_block.rs +++ b/src/intermediate/quote_block.rs @@ -12,7 +12,7 @@ intermediate!(IQuoteBlock, QuoteBlock, original, registry, { let children = { let mut ret = Vec::new(); for obj in original.children.iter() { - ret.push(IElement::new(registry, obj).await?); + ret.push(IElement::new(registry.clone(), obj).await?); } ret }; diff --git a/src/intermediate/registry.rs b/src/intermediate/registry.rs index 0a7861d..5890e68 100644 --- a/src/intermediate/registry.rs +++ b/src/intermediate/registry.rs @@ -1,5 +1,7 @@ use std::collections::HashMap; use std::marker::PhantomData; +use std::sync::Arc; +use std::sync::Mutex; // use super::ast_node::IntoIAstNode; use crate::error::CustomError; @@ -7,6 +9,7 @@ use organic::types::Element; use organic::types::Object; use super::ast_node::IAstNode; +use super::RefRegistry; type IdCounter = u16; @@ -40,63 +43,75 @@ impl<'orig, 'parse> Registry<'orig, 'parse> { .map(|(_label, definition)| definition) .enumerate() } +} - /// Get a 0-indexed ID for a footnote. - /// - /// This needs to be incremented to be 1-indexed for render. - pub(crate) async fn get_footnote_reference_id<'reg>( - &'reg mut self, - label: Option<&'parse str>, - definition: &'orig Vec>, - ) -> Result { - if let None = label { - // If it has no label then it must always get a new ID. - let contents = convert_reference_contents(self, definition).await?; - self.footnote_ids.push((None, contents)); - return Ok(self.footnote_ids.len() - 1); - } - - if let Some(existing_id) = self - .footnote_ids - .iter() - .position(|(id, _definition)| *id == label) - { - if !definition.is_empty() { - let contents = convert_reference_contents(self, definition).await?; - let entry = self - .footnote_ids - .get_mut(existing_id) - .expect("If-statement proves this to be Some."); - entry.1 = contents; - } - Ok(existing_id) - } else { - let contents = convert_reference_contents(self, definition).await?; - self.footnote_ids.push((label, contents)); - Ok(self.footnote_ids.len() - 1) - } +/// Get a 0-indexed ID for a footnote. +/// +/// This needs to be incremented to be 1-indexed for render. +pub(crate) async fn get_footnote_reference_id<'orig, 'parse>( + registry: RefRegistry<'orig, 'parse>, + label: Option<&'parse str>, + definition: &'orig Vec>, +) -> Result { + if let None = label { + // If it has no label then it must always get a new ID. + let contents = convert_reference_contents(registry.clone(), definition).await?; + let pos = { + let mut registry = registry.lock().unwrap(); + registry.footnote_ids.push((None, contents)); + registry.footnote_ids.len() - 1 + }; + return Ok(pos); } - /// Update the definition to a footnote but do not mark it as referenced. - pub(crate) async fn register_footnote_definition<'reg>( - &'reg mut self, - label: &'parse str, - definition: &'orig Vec>, - ) -> Result<(), CustomError> { - let contents = convert_definition_contents(self, definition).await?; - if let Some((_existing_id, existing_definition)) = self - .footnote_ids - .iter_mut() - .find(|(id, _definition)| *id == Some(label)) - { - *existing_definition = contents; + let existing_index = registry + .lock() + .unwrap() + .footnote_ids + .iter() + .position(|(id, _definition)| *id == label); + if let Some(existing_id) = existing_index { + if !definition.is_empty() { + let contents = convert_reference_contents(registry.clone(), definition).await?; + let mut registry = registry.lock().unwrap(); + let entry = registry + .footnote_ids + .get_mut(existing_id) + .expect("If-statement proves this to be Some."); + entry.1 = contents; } - Ok(()) + Ok(existing_id) + } else { + let contents = convert_reference_contents(registry.clone(), definition).await?; + let pos = { + let mut registry = registry.lock().unwrap(); + registry.footnote_ids.push((label, contents)); + registry.footnote_ids.len() - 1 + }; + Ok(pos) } } -async fn convert_reference_contents<'reg, 'orig, 'parse>( - registry: &'reg mut Registry<'orig, 'parse>, +/// Update the definition to a footnote but do not mark it as referenced. +pub(crate) async fn register_footnote_definition<'orig, 'parse>( + registry: RefRegistry<'orig, 'parse>, + label: &'parse str, + definition: &'orig Vec>, +) -> Result<(), CustomError> { + let contents = convert_definition_contents(registry.clone(), definition).await?; + let mut registry = registry.lock().unwrap(); + if let Some((_existing_id, existing_definition)) = registry + .footnote_ids + .iter_mut() + .find(|(id, _definition)| *id == Some(label)) + { + *existing_definition = contents; + } + Ok(()) +} + +async fn convert_reference_contents<'orig, 'parse>( + registry: RefRegistry<'orig, 'parse>, contents: &'orig Vec>, ) -> Result, CustomError> { let contents = { @@ -111,8 +126,8 @@ async fn convert_reference_contents<'reg, 'orig, 'parse>( Ok(contents) } -async fn convert_definition_contents<'reg, 'orig, 'parse>( - registry: &'reg mut Registry<'orig, 'parse>, +async fn convert_definition_contents<'orig, 'parse>( + registry: RefRegistry<'orig, 'parse>, contents: &'orig Vec>, ) -> Result, CustomError> { let contents = { diff --git a/src/intermediate/regular_link.rs b/src/intermediate/regular_link.rs index 8b8ada5..2e85bd7 100644 --- a/src/intermediate/regular_link.rs +++ b/src/intermediate/regular_link.rs @@ -13,7 +13,7 @@ intermediate!(IRegularLink, RegularLink, original, registry, { let children = { let mut ret = Vec::new(); for obj in original.children.iter() { - ret.push(IObject::new(registry, obj).await?); + ret.push(IObject::new(registry.clone(), obj).await?); } ret }; diff --git a/src/intermediate/section.rs b/src/intermediate/section.rs index dea8f2e..d095620 100644 --- a/src/intermediate/section.rs +++ b/src/intermediate/section.rs @@ -12,7 +12,7 @@ intermediate!(ISection, Section, original, registry, { let children = { let mut ret = Vec::new(); for elem in original.children.iter() { - ret.push(IElement::new(registry, elem).await?); + ret.push(IElement::new(registry.clone(), elem).await?); } ret }; diff --git a/src/intermediate/target.rs b/src/intermediate/target.rs index 138d491..c27eccc 100644 --- a/src/intermediate/target.rs +++ b/src/intermediate/target.rs @@ -9,6 +9,7 @@ pub(crate) struct ITarget { } intermediate!(ITarget, Target, original, registry, { + let mut registry = registry.lock().unwrap(); let id = registry.get_target(original.value); Ok(ITarget { id: id.clone(),