From 5c25d628f59553c6a6af41e4e45d23dc336a37c8 Mon Sep 17 00:00:00 2001 From: avitex Date: Wed, 3 Mar 2021 13:38:15 +1100 Subject: [PATCH] refactor usage --- Cargo.toml | 27 ++++-- book/macros.tera | 56 ++++++------ book/observe/event.instance.tera | 8 +- book/react/action.instance.tera | 10 +-- book/react/stage.instance.tera | 6 +- book/source/intelligence.instance.tera | 6 +- book/source/provider.instance.tera | 4 +- book/source/requirement.instance.tera | 4 +- build.rs | 12 ++- src/lib.rs | 2 +- src/main.rs | 114 +++++++++++++++++++++---- src/{generator => render}/mdbook.rs | 93 ++++++++++++-------- src/{generator => render}/mod.rs | 24 +++--- 13 files changed, 248 insertions(+), 118 deletions(-) rename src/{generator => render}/mdbook.rs (79%) rename src/{generator => render}/mod.rs (77%) diff --git a/Cargo.toml b/Cargo.toml index 042e433..9027ab2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,24 +6,37 @@ edition = "2018" publish = false build = "build.rs" +[features] +default = ["cli"] +cli = ["structopt", "tokio/macros", "tokio/rt-multi-thread"] +mdbook-renderer = ["mdbook", "includedir", "includedir_codegen", "glob", "phf"] + +[[bin]] +name = "cyberstorm" +required-features = ["cli"] + [dependencies] zc = "0.4" +log = "0.4" serde = { version = "1.0", features = ["derive"] } toml = "0.5" async-trait = "0.1" strum = { version = "0.20", features = ["derive"] } roxmltree = "0.14" -tokio = { version = "1", features = ["rt-multi-thread", "fs", "macros"] } -validator = { version = "0.12", features = ["derive"] } +tokio = { version = "1", features = ["fs"] } thiserror = "1.0" tera = "1.6" anyhow = "1.0" regex = "1" lazy_static = "1" -structopt = "0.3" -phf = "0.8.0" -includedir = "0.6" +env_logger = "0.8" +chrono = "0.4" + +structopt = { version = "0.3", optional = true } +phf = { version = "0.8.0", optional = true } +includedir = { version = "0.6", optional = true } +mdbook = { version = "0.4", optional = true } [build-dependencies] -includedir_codegen = "0.6" -glob = "0.3" +includedir_codegen = { version = "0.6", optional = true } +glob = { version = "0.3", optional = true } diff --git a/book/macros.tera b/book/macros.tera index 9aecf59..cff55a7 100644 --- a/book/macros.tera +++ b/book/macros.tera @@ -1,3 +1,8 @@ +{% macro content(content) %} +{%- set trimmed = content | trim -%} +{%- if trimmed | length == 0 %}No description{% else %}{{ trimmed }}{% endif -%} +{% endmacro content %} + {% macro references(refs) %} {%- if refs | length == 0 %}No references{% endif -%} {%- for ref in refs -%} @@ -5,46 +10,41 @@ {% endfor -%} {% endmacro references %} -{% macro title(title, id) -%} -{{ title }} ([edit]({{ id | domain_id_link(for="edit") }})) -{%- endmacro details_next %} +{% macro doc_title(doc) -%} +{{ doc.name }} ([edit]({{ doc.id | domain_id_link(for="edit") }})) +{%- endmacro doc_title %} -{% macro details(id, name) -%} -| Title | {{ name }} | +{% macro doc_details(doc) -%} +| Title | {{ doc.name }} | |:---------------------------:|:------------------------| -{{ self::details_next(title="ID", value=id)}} -{%- endmacro details %} +{{ self::doc_details_next(title="ID", value=doc.id)}} +{%- endmacro doc_details %} -{% macro details_next(title, value) -%} +{% macro doc_details_next(title, value) -%} | **{{ title }}** | {{ value }} | -{%- endmacro details_next %} +{%- endmacro doc_details_next %} -{% macro details_authors(authors) -%} -{{ self::details_next(title="Authors", value=authors | join )}} -{%- endmacro details_next %} +{% macro doc_details_authors(authors) -%} +{{ self::doc_details_next(title="Authors", value=authors | join )}} +{%- endmacro doc_details_authors %} -{% macro details_tags(tags) -%} +{% macro doc_details_tags(tags) -%} {% if tags | length == 0 -%} -{{ self::details_next(title="Tags", value="No tags") }} +{{ self::doc_details_next(title="Tags", value="No tags") }} {%- else -%} -{{ self::details_next(title="Tags", value=tags | join) }} +{{ self::doc_details_next(title="Tags", value=tags | join) }} {%- endif %} -{%- endmacro details_next %} +{%- endmacro doc_details_tags %} -{% macro content(content) %} -{%- set trimmed = content | trim -%} -{%- if trimmed | length == 0 %}No description{% else %}{{ trimmed }}{% endif -%} -{% endmacro details_next %} - -{% macro name_and_id_link(value) -%} -{{ value["doc"]["name"] }} ([{{ value["id"] }}]({{ value["id"] | domain_id_link }})) -{%- endmacro name_and_id_link %} +{% macro doc_rich_link(doc) -%} +{{ doc.name }} ([{{ doc.id }}]({{ global(key="site_url")}}{{ doc.id | domain_id_link }})) +{%- endmacro doc_rich_link %} {% macro summary_table(instances) -%} | ID | Name | |:---------------------------:|:------------------------| {% for item in instances -%} -| [{{ item.id }}]({{ item.id | domain_id_link }}) | {{ item.name }} | +| [{{ item.id }}]({{ global(key="site_url") }}{{ item.id | domain_id_link }}) | {{ item.name }} | {% endfor %} {%- endmacro summary_table %} @@ -59,8 +59,8 @@ {%- endif -%} {%- if last_model != id_parts.model -%} {%- set_global last_model = id_parts.model %} -- [{{ id_parts.model | capitalize }}](.{{ item.id | domain_id_link(for="model") }}) +- [{{ id_parts.model | capitalize }}](./{{ item.id | domain_id_link(for="model") }}) {%- endif %} - - [{{ item.name }}](.{{ item.id | domain_id_link }}) + - [{{ item.name }}](./{{ item.id | domain_id_link }}) {%- endfor -%} -{% endmacro summary_list %} \ No newline at end of file +{% endmacro summary_list %} diff --git a/book/observe/event.instance.tera b/book/observe/event.instance.tera index d9e6ffd..a4a8649 100644 --- a/book/observe/event.instance.tera +++ b/book/observe/event.instance.tera @@ -1,12 +1,12 @@ {% import "macros.tera" as macros %} -# {{ macros::title(title=doc.name, id=id) }} +# {{ macros::doc_title(doc=doc) }} -{{ macros::details(id=id, name=doc.name) }} +{{ macros::doc_details(doc=doc) }} {%- if doc.WindowsEvent %} -{{ macros::details_next(title="Type", value="Windows event") }} +{{ macros::doc_details_next(title="Type", value="Windows event") }} {% endif -%} -{{ macros::details_next(title="Description", value=doc.description) }} +{{ macros::doc_details_next(title="Description", value=doc.description) }} ## Description diff --git a/book/react/action.instance.tera b/book/react/action.instance.tera index 6269b83..57be87d 100644 --- a/book/react/action.instance.tera +++ b/book/react/action.instance.tera @@ -1,12 +1,12 @@ {% import "macros.tera" as macros %} {% set stage = doc.stage | get_doc %} -# {{ macros::title(title=doc.name, id=id) }} +# {{ macros::doc_title(doc=doc) }} -{{ macros::details(id=id, name=doc.name) }} -{{ macros::details_next(title="Stage", value=macros::name_and_id_link(value=stage)) }} -{{ macros::details_next(title="Description", value=doc.description) }} -{{ macros::details_tags(tags=doc.tags) }} +{{ macros::doc_details(doc=doc) }} +{{ macros::doc_details_next(title="Stage", value=macros::doc_rich_link(doc=stage)) }} +{{ macros::doc_details_next(title="Description", value=doc.description) }} +{{ macros::doc_details_tags(tags=doc.tags) }} ## Description diff --git a/book/react/stage.instance.tera b/book/react/stage.instance.tera index 9dedbb4..2649043 100644 --- a/book/react/stage.instance.tera +++ b/book/react/stage.instance.tera @@ -1,9 +1,9 @@ {% import "macros.tera" as macros %} -# {{ macros::title(title=doc.name, id=id) }} +# {{ macros::doc_title(doc=doc) }} -{{ macros::details(id=id, name=doc.name) }} -{{ macros::details_next(title="Description", value=doc.description) }} +{{ macros::doc_details(doc=doc) }} +{{ macros::doc_details_next(title="Description", value=doc.description) }} ## Description diff --git a/book/source/intelligence.instance.tera b/book/source/intelligence.instance.tera index 739972b..bd5038a 100644 --- a/book/source/intelligence.instance.tera +++ b/book/source/intelligence.instance.tera @@ -1,9 +1,9 @@ {% import "macros.tera" as macros %} -# {{ macros::title(title=doc.name, id=id) }} +# {{ macros::doc_title(doc=doc) }} -{{ macros::details(id=id, name=doc.name) }} -{{ macros::details_next(title="Provider", value=doc.provider) }} +{{ macros::doc_details(doc=doc) }} +{{ macros::doc_details_next(title="Provider", value=doc.provider) }} ## Description diff --git a/book/source/provider.instance.tera b/book/source/provider.instance.tera index 1df6b32..51f8ef8 100644 --- a/book/source/provider.instance.tera +++ b/book/source/provider.instance.tera @@ -1,8 +1,8 @@ {% import "macros.tera" as macros %} -# {{ macros::title(title=doc.name, id=id) }} +# {{ macros::doc_title(doc=doc) }} -{{ macros::details(id=id, name=doc.name) }} +{{ macros::doc_details(doc=doc) }} ## Description diff --git a/book/source/requirement.instance.tera b/book/source/requirement.instance.tera index 1df6b32..51f8ef8 100644 --- a/book/source/requirement.instance.tera +++ b/book/source/requirement.instance.tera @@ -1,8 +1,8 @@ {% import "macros.tera" as macros %} -# {{ macros::title(title=doc.name, id=id) }} +# {{ macros::doc_title(doc=doc) }} -{{ macros::details(id=id, name=doc.name) }} +{{ macros::doc_details(doc=doc) }} ## Description diff --git a/build.rs b/build.rs index 2c08267..1f6902a 100644 --- a/build.rs +++ b/build.rs @@ -1,7 +1,13 @@ -use glob::glob; -use includedir_codegen::Compression; - fn main() { + #[cfg(feature = "mdbook-renderer")] + include_mdbook_templates(); +} + +#[cfg(feature = "mdbook-renderer")] +fn include_mdbook_templates() { + use glob::glob; + use includedir_codegen::Compression; + let mut templates = includedir_codegen::start("BASE_TEMPLATES"); for path_result in glob("book/**/*.tera").unwrap() { diff --git a/src/lib.rs b/src/lib.rs index df11e01..ce4ffff 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,5 +2,5 @@ mod util; pub mod document; pub mod domains; -pub mod generator; pub mod registry; +pub mod render; diff --git a/src/main.rs b/src/main.rs index 0264071..405a642 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,12 +1,18 @@ -use std::path::PathBuf; +use std::env; +use std::io::Write; +use std::path::{Path, PathBuf}; use std::str::FromStr; -use anyhow::{Context, Error}; +use anyhow::{anyhow, Context, Error}; +use chrono::Local; +use log::LevelFilter; use structopt::StructOpt; +use tokio::fs; -use cyberstorm::generator::mdbook::MDBookEngine; -use cyberstorm::generator::Generator; use cyberstorm::registry::{DirectoryRegistry, SupportedRegistry}; +#[cfg(feature = "mdbook-renderer")] +use cyberstorm::render::mdbook::MDBookEngine; +use cyberstorm::render::Renderer; #[derive(Debug, StructOpt)] #[structopt(name = "cyberstorm")] @@ -20,13 +26,19 @@ struct Opt { #[derive(Debug, StructOpt)] enum Cmd { - BuildMdbook(BuildMdbookOpt), + /// Renders the content into a mdBook. + #[cfg(feature = "mdbook-renderer")] + MdbookRender(MdbookRenderOpt), + /// Renders the content into a mdBook and builds it. + #[cfg(feature = "mdbook-renderer")] + MdbookBuild(MdbookRenderOpt), } #[derive(Debug, StructOpt)] -struct BuildMdbookOpt { - /// Path to the output MDBook directory. - #[structopt(parse(from_os_str))] +#[cfg(feature = "mdbook-renderer")] +struct MdbookRenderOpt { + /// Path to the output mdBook root or `book.toml`. + #[structopt(parse(from_os_str), default_value = "./book.toml")] book: PathBuf, } @@ -48,25 +60,97 @@ async fn run(opt: Opt) -> Result<(), Error> { RegistryOpt::Directory(path) => SupportedRegistry::Directory(DirectoryRegistry::new(path)), }; match &opt.cmd { - Cmd::BuildMdbook(build_opt) => build_mdbook(&opt, build_opt, ®istry).await, + #[cfg(feature = "mdbook-renderer")] + Cmd::MdbookRender(render_opt) => { + let (root, config) = load_mdbook_config(&render_opt.book).await?; + render_mdbook(®istry, &root, &config).await + } + #[cfg(feature = "mdbook-renderer")] + Cmd::MdbookBuild(render_opt) => { + let (root, config) = load_mdbook_config(&render_opt.book).await?; + render_mdbook(®istry, &root, &config).await?; + mdbook::MDBook::load_with_config(root, config)?.build() + } } } -async fn build_mdbook( - _opt: &Opt, - build_opt: &BuildMdbookOpt, +#[cfg(feature = "mdbook-renderer")] +async fn load_mdbook_config(book: &Path) -> Result<(PathBuf, mdbook::Config), Error> { + let (root, config_file) = book + .canonicalize() + .ok() + .and_then(|book| { + let (root, config) = if book.extension().is_some() { + (book.parent().unwrap().to_owned(), book.to_owned()) + } else { + let config_file = book.join("book.toml"); + (book, config_file) + }; + if config.is_file() { + Some((root, config)) + } else { + None + } + }) + .ok_or_else(|| { + anyhow!( + "expected mdbook config path (eg. `book.toml`) at `{}`", + book.display() + ) + })?; + + let config = fs::read_to_string(config_file) + .await + .context("failed to read mdbook configuration")? + .parse()?; + + Ok((root, config)) +} + +#[cfg(feature = "mdbook-renderer")] +async fn render_mdbook( registry: &SupportedRegistry, + root: &Path, + config: &mdbook::Config, ) -> Result<(), Error> { - let engine = MDBookEngine::new(&build_opt.book).context("failed to load mdbook engine")?; - Generator::new(engine, registry) + let engine = MDBookEngine::new(root, config); + Renderer::new(engine, registry) .generate() .await .context("failed to generate mdbook content") } +fn init_logger() { + let mut builder = env_logger::Builder::new(); + + builder.format(|formatter, record| { + writeln!( + formatter, + "{} [{}] ({}): {}", + Local::now().format("%Y-%m-%d %H:%M:%S"), + record.level(), + record.target(), + record.args() + ) + }); + + if let Ok(var) = env::var("RUST_LOG") { + builder.parse_filters(&var); + } else { + // if no RUST_LOG provided, default to logging at the Info level + builder.filter(None, LevelFilter::Info); + // Filter extraneous html5ever not-implemented messages + builder.filter(Some("html5ever"), LevelFilter::Error); + } + + builder.init(); +} + #[tokio::main] async fn main() { + init_logger(); + if let Err(err) = run(Opt::from_args()).await { - eprintln!("{:#}", err); + log::error!("{:#}", err); } } diff --git a/src/generator/mdbook.rs b/src/render/mdbook.rs similarity index 79% rename from src/generator/mdbook.rs rename to src/render/mdbook.rs index 0b1e206..95c6123 100644 --- a/src/generator/mdbook.rs +++ b/src/render/mdbook.rs @@ -5,6 +5,7 @@ use std::{io, mem}; use async_trait::async_trait; use lazy_static::lazy_static; +use mdbook::config::{Config as MDBookConfig, HtmlConfig}; use regex::Regex; use serde::Serialize; use tera::{Context, Map, Tera, Value}; @@ -18,7 +19,9 @@ use crate::domains::common::{DomainId, DomainModel, ModelId}; use crate::domains::GenericDocument; use crate::registry::{Registry, RegistryConfig}; -use crate::generator::{Engine, GeneratorError}; +use crate::render::{Engine, RendererError}; + +type DocumentMap = HashMap>; #[derive(Debug, Error)] pub enum MDBookEngineError { @@ -28,9 +31,9 @@ pub enum MDBookEngineError { Tera(#[from] tera::Error), } -impl From for GeneratorError { +impl From for RendererError { fn from(err: MDBookEngineError) -> Self { - GeneratorError::Engine(err.into()) + RendererError::Engine(err.into()) } } @@ -49,39 +52,50 @@ pub struct MDBookEngine { enum Inner { Start { src: PathBuf, + global: Map, }, LoadAndRender { src: PathBuf, + global: Map, templates: Tera, summary: Vec, - documents: HashMap, + documents: DocumentMap, }, Finish, } impl MDBookEngine { - pub fn new(src: &Path) -> Result { - Ok(Self { + pub fn new(root: &Path, config: &MDBookConfig) -> Self { + let mut global = Map::new(); + if let Ok(Some(HtmlConfig { site_url, .. })) = config.get_deserialized_opt("output.html") { + global.insert( + "site_url".to_owned(), + site_url.as_deref().unwrap_or("/").to_owned().into(), + ); + } + Self { inner: Inner::Start { - src: src.canonicalize()?, + src: root.join(&config.book.src), + global, }, - }) + } } } // (?Send) #[async_trait] impl Engine for MDBookEngine { - async fn start(&mut self, _registry: &R) -> Result<(), GeneratorError> + async fn start(&mut self, _registry: &R) -> Result<(), RendererError> where R: Registry, { - if let Inner::Start { src } = mem::replace(&mut self.inner, Inner::Finish) { + if let Inner::Start { src, global } = mem::replace(&mut self.inner, Inner::Finish) { let templates = load_templates(&src).await?; let documents = HashMap::new(); let summary = Vec::new(); self.inner = Inner::LoadAndRender { src, + global, templates, documents, summary, @@ -95,7 +109,7 @@ impl Engine for MDBookEngine { model_id: ModelId, doc: GenericDocument, _registry: &R, - ) -> Result<(), GeneratorError> + ) -> Result<(), RendererError> where R: Registry, { @@ -140,12 +154,13 @@ impl Engine for MDBookEngine { Ok(()) } - async fn finish(&mut self, registry: &R) -> Result<(), GeneratorError> + async fn finish(&mut self, registry: &R) -> Result<(), RendererError> where R: Registry, { if let Inner::LoadAndRender { src, + global, mut templates, documents, summary, @@ -154,7 +169,7 @@ impl Engine for MDBookEngine { let summary = Arc::new(summary); let documents = Arc::new(documents); let registry_config = registry.get_config().await?; - register_filters(&mut templates, documents.clone(), registry_config); + register_filters(&mut templates, documents.clone(), registry_config, global); render_indexes(&templates, &src, &summary).await?; render_summary(&templates, &src, &summary).await?; render_documents(&templates, &src, documents).await?; @@ -190,17 +205,17 @@ async fn load_templates(src: &Path) -> Result { fn save_domain_model( summary: &mut Vec, - documents: &mut HashMap, + documents: &mut DocumentMap, model_id: ModelId, doc: &Document, ) where M: DomainModel, { let id = DomainId::new(M::kind(), model_id); - let mut value = Map::new(); - value.insert("id".to_owned(), tera::to_value(&id).unwrap()); - value.insert("doc".to_owned(), tera::to_value(&doc).unwrap()); - documents.insert(id, value.into()); + if let Value::Object(mut document) = tera::to_value(&doc).unwrap() { + document.insert("id".to_owned(), tera::to_value(&id).unwrap()); + documents.insert(id, document); + } summary.push(SummaryItem { id, name: doc.meta.name().to_owned(), @@ -210,9 +225,9 @@ fn save_domain_model( async fn render_documents( templates: &Tera, src: &Path, - documents: Arc>, + documents: Arc, ) -> Result<(), MDBookEngineError> { - for (id, value) in documents.iter() { + for (id, document) in documents.iter() { let (domain, model) = id.kind.parts(); let model_path = format!("{}/{}", domain, model); let template_path = format!("{}.instance.tera", model_path); @@ -220,7 +235,8 @@ async fn render_documents( .join(model_path) .join(id.model_id.to_string()) .with_extension("md"); - let context = Context::from_value(value.clone())?; + let mut context = Context::new(); + context.insert("doc", &document); let contents = templates.render(&template_path, &context)?; fs::write(output_path, contents).await?; } @@ -284,11 +300,20 @@ async fn render_indexes( fn register_filters( tera: &mut Tera, - registry: Arc>, + documents: Arc, registry_config: Arc, + global: Map, ) { use tera::{try_get_value, Error}; + tera.register_function("global", move |args: &HashMap| { + if let Some(Value::String(key)) = args.get("key") { + Ok(global.get(key).cloned().unwrap_or(Value::Null)) + } else { + Err(Error::msg("expected `key` for `global` function")) + } + }); + fn parse_domain_id(value: &Value) -> Result { let id = try_get_value!("link", "value", String, value); id.parse() @@ -301,8 +326,8 @@ fn register_filters( let id = parse_domain_id(value)?; let (domain, model) = id.kind.parts(); let link = match args.get("for").and_then(|v| v.as_str()) { - None => format!("/{}/{}/{}.md", domain, model, id.model_id), - Some("model") => format!("/{}/{}.md", domain, model), + None => format!("{}/{}/{}.md", domain, model, id.model_id), + Some("model") => format!("{}/{}.md", domain, model), Some("edit") => registry_config.edit_link(id).map_err(Error::msg)?, Some(_) => { return Err(Error::msg( @@ -331,20 +356,15 @@ fn register_filters( "get_doc", move |value: &Value, _: &HashMap| { let id = parse_domain_id(value)?; - registry + documents .get(&id) .cloned() + .map(Value::Object) .ok_or_else(|| Error::msg(format_args!("unknown document id {}", id))) }, ); tera.register_filter("autolink", |value: &Value, _: &HashMap| { - let text = try_get_value!("autolink", "value", String, value); - - if text.is_empty() { - return Ok(Value::String(String::new())); - } - lazy_static! { static ref URL: Regex = Regex::new( r"(?ix) @@ -353,9 +373,12 @@ fn register_filters( ) .unwrap(); } - - let replaced = URL.replace_all(text.as_str(), "[$0]($0)").into_owned(); - - Ok(Value::String(replaced)) + let text = try_get_value!("autolink", "value", String, value); + let text = if text.is_empty() { + text + } else { + URL.replace_all(text.as_str(), "[$0]($0)").into_owned() + }; + Ok(Value::String(text)) }); } diff --git a/src/generator/mod.rs b/src/render/mod.rs similarity index 77% rename from src/generator/mod.rs rename to src/render/mod.rs index bd9187b..81da18e 100644 --- a/src/generator/mod.rs +++ b/src/render/mod.rs @@ -1,3 +1,4 @@ +#[cfg(feature = "mdbook-renderer")] pub mod mdbook; use async_trait::async_trait; @@ -9,19 +10,19 @@ use crate::domains::GenericDocument; use crate::registry::{Registry, RegistryError}; #[derive(Debug, Error)] -pub enum GeneratorError { +pub enum RendererError { #[error("{0}")] Engine(#[from] anyhow::Error), #[error("{0}")] Registry(#[from] RegistryError), } -pub struct Generator { +pub struct Renderer { engine: E, registry: R, } -impl Generator +impl Renderer where E: Engine, R: Registry, @@ -30,7 +31,8 @@ where Self { engine, registry } } - pub async fn generate(mut self) -> Result<(), GeneratorError> { + pub async fn generate(mut self) -> Result<(), RendererError> { + log::info!("Rendering of content has started"); self.engine.start(&self.registry).await?; macro_rules! push_documents { ($($kind:ident),+) => { @@ -62,10 +64,12 @@ where MitigatePlatform, MitigateConfiguration ); - self.engine.finish(&self.registry).await + self.engine.finish(&self.registry).await?; + log::info!("Rendering of content has finished"); + Ok(()) } - async fn get_documents(&self) -> Result)>, GeneratorError> + async fn get_documents(&self) -> Result)>, RendererError> where M: DomainModel, { @@ -76,13 +80,13 @@ where docs.sort_by_key(|(id, _)| *id); docs }) - .map_err(GeneratorError::Registry) + .map_err(RendererError::Registry) } } #[async_trait] pub trait Engine { - async fn start(&mut self, registry: &R) -> Result<(), GeneratorError> + async fn start(&mut self, registry: &R) -> Result<(), RendererError> where R: Registry; @@ -91,11 +95,11 @@ pub trait Engine { id: ModelId, doc: GenericDocument, registry: &R, - ) -> Result<(), GeneratorError> + ) -> Result<(), RendererError> where R: Registry; - async fn finish(&mut self, registry: &R) -> Result<(), GeneratorError> + async fn finish(&mut self, registry: &R) -> Result<(), RendererError> where R: Registry; }