From 10339daf09042e1c548e09619aee0ff8305cb617 Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Sat, 18 Apr 2020 16:35:38 +0800 Subject: [PATCH] blog: refactor: rewrite more transform as iterator operations --- src/blog.rs | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/src/blog.rs b/src/blog.rs index 7a36492..723e3a8 100644 --- a/src/blog.rs +++ b/src/blog.rs @@ -9,6 +9,7 @@ use crate::utils::*; use js_sys::{JsString, RegExp}; use pulldown_cmark::*; use serde::{Serialize, Deserialize}; +use std::future::Future; use std::vec::Vec; use wasm_bindgen::JsCast; use wasm_bindgen::closure::Closure; @@ -231,6 +232,22 @@ impl PostContentCache { } } + fn transform_tags<'ev>( + parser: impl 'ev + Iterator> + ) -> impl 'ev + Iterator>> { + parser.map(|mut ev| { + async { + match ev { + Event::Start(ref mut tag) | Event::End(ref mut tag) => { + Self::transform_tag(tag).await; + ev + }, + _ => ev + } + } + }) + } + fn transform_code_block_highlight<'iter, 'ev>( parser: impl Iterator> ) -> impl Iterator> { @@ -309,26 +326,20 @@ impl PostContentCache { // Despite the signature, this function BLOCKS // async only comes from digesting via SubtleCrypto pub async fn render(post: &Post) -> PostContentCache { - // We have to first collect all events into a vector - // because we need to asynchronously transform the events - // which could not be done through mapping on iterators - let mut parser: Vec = Parser::new_ext(&post.content, Options::all()).collect(); - for ev in parser.iter_mut() { - match ev { - Event::Start(tag) | Event::End(tag) => { - Self::transform_tag(tag).await; - }, - _ => () - }; - } - - // Now some pure iterator operations - let parser = parser.into_iter(); + let parser = Parser::new_ext(&post.content, Options::all()); // Apply code highlighting via Highlight.js let parser = Self::transform_code_block_highlight(parser); + // Apply async tag transform (resulting in an iterator of Futures) + let parser = Self::transform_tags(parser); + + // Await on every Future in the queue to convert them back as Events + let mut events: Vec = vec![]; + for ev in parser { + events.push(ev.await); + } let mut html_output = String::new(); - html::push_html(&mut html_output, parser); + html::push_html(&mut html_output, events.into_iter()); html_output = Self::transform_html(html_output); PostContentCache { uuid: post.uuid.clone(),