From a14b0b6a06dcb1e138f150f69c44f0f01299fcff Mon Sep 17 00:00:00 2001 From: Cosmic Horror Date: Tue, 16 May 2023 19:36:18 -0600 Subject: [PATCH 1/2] Make `ComrakExtensionOptions` non-exhaustive --- examples/s-expr.rs | 22 +++++++++++----------- src/main.rs | 31 +++++++++++++++++-------------- src/parser/mod.rs | 3 +++ 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/examples/s-expr.rs b/examples/s-expr.rs index c8a1341b..4d2e3efe 100644 --- a/examples/s-expr.rs +++ b/examples/s-expr.rs @@ -74,18 +74,18 @@ fn iter_nodes<'a, W: Write>( fn dump(source: &str) -> io::Result<()> { let arena = Arena::new(); + let mut extension = ExtensionOptions::default(); + extension.strikethrough = true; + extension.tagfilter = true; + extension.table = true; + extension.autolink = true; + extension.tasklist = true; + extension.superscript = true; + extension.footnotes = true; + extension.description_lists = true; + let opts = Options { - extension: ExtensionOptions { - strikethrough: true, - tagfilter: true, - table: true, - autolink: true, - tasklist: true, - superscript: true, - footnotes: true, - description_lists: true, - ..ExtensionOptions::default() - }, + extension, ..Options::default() }; diff --git a/src/main.rs b/src/main.rs index 8595f8bc..62c72476 100644 --- a/src/main.rs +++ b/src/main.rs @@ -194,21 +194,24 @@ fn main() -> Result<(), Box> { let exts = &cli.extensions; + let mut extension = ExtensionOptions::default(); + extension.strikethrough = exts.contains(&Extension::Strikethrough) || cli.gfm; + extension.tagfilter = exts.contains(&Extension::Tagfilter) || cli.gfm; + extension.table = exts.contains(&Extension::Table) || cli.gfm; + extension.autolink = exts.contains(&Extension::Autolink) || cli.gfm; + extension.tasklist = exts.contains(&Extension::Tasklist) || cli.gfm; + extension.superscript = exts.contains(&Extension::Superscript); + extension.header_ids = cli.header_ids; + extension.footnotes = exts.contains(&Extension::Footnotes); + extension.description_lists = exts.contains(&Extension::DescriptionLists); + extension.front_matter_delimiter = cli.front_matter_delimiter; + #[cfg(feature = "shortcodes")] + { + extension.shortcodes = cli.gemojis; + } + let options = Options { - extension: ExtensionOptions { - strikethrough: exts.contains(&Extension::Strikethrough) || cli.gfm, - tagfilter: exts.contains(&Extension::Tagfilter) || cli.gfm, - table: exts.contains(&Extension::Table) || cli.gfm, - autolink: exts.contains(&Extension::Autolink) || cli.gfm, - tasklist: exts.contains(&Extension::Tasklist) || cli.gfm, - superscript: exts.contains(&Extension::Superscript), - header_ids: cli.header_ids, - footnotes: exts.contains(&Extension::Footnotes), - description_lists: exts.contains(&Extension::DescriptionLists), - front_matter_delimiter: cli.front_matter_delimiter, - #[cfg(feature = "shortcodes")] - shortcodes: cli.gemojis, - }, + extension, parse: ParseOptions { smart: cli.smart, default_info_string: cli.default_info_string, diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 86c452b3..42f12806 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -150,6 +150,9 @@ pub struct Options { pub render: RenderOptions, } +// NOTE: The shortcodes feature adds a new field, so mark this as non-exhaustive since it's part of +// the public API +#[non_exhaustive] #[derive(Default, Debug, Clone)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] /// Options to select extensions. From 4ddd159acf88b05b1f917dad5838cb10188ac2b1 Mon Sep 17 00:00:00 2001 From: Asherah Connor Date: Sat, 17 Jun 2023 13:40:34 +1000 Subject: [PATCH 2/2] parser: mark all other options structs (except top-level) nonexhaustive --- fuzz/fuzz_targets/all_options.rs | 59 +++++++++++++++--------------- fuzz/fuzz_targets/cli_default.rs | 10 ++--- fuzz/fuzz_targets/gfm.rs | 26 ++++++------- fuzz/fuzz_targets/gfm_footnotes.rs | 28 +++++++------- fuzz/fuzz_targets/gfm_sourcepos.rs | 28 +++++++------- fuzz/fuzz_targets/quadratic.rs | 56 ++++++++++++++-------------- src/main.rs | 32 ++++++++-------- src/parser/mod.rs | 6 ++- 8 files changed, 122 insertions(+), 123 deletions(-) diff --git a/fuzz/fuzz_targets/all_options.rs b/fuzz/fuzz_targets/all_options.rs index 8cfdab6b..9efdb288 100644 --- a/fuzz/fuzz_targets/all_options.rs +++ b/fuzz/fuzz_targets/all_options.rs @@ -8,37 +8,36 @@ use comrak::{ }; fuzz_target!(|s: &str| { + let mut extension = ExtensionOptions::default(); + extension.strikethrough = true; + extension.tagfilter = true; + extension.table = true; + extension.autolink = true; + extension.tasklist = true; + extension.superscript = true; + extension.header_ids = Some("user-content-".to_string()); + extension.footnotes = true; + extension.description_lists = true; + extension.front_matter_delimiter = Some("---".to_string()); + extension.shortcodes = true; + + let mut parse = ParseOptions::default(); + parse.smart = true; + parse.default_info_string = Some("rust".to_string()); + parse.relaxed_tasklist_matching = true; + + let mut render = RenderOptions::default(); + render.hardbreaks = true; + render.github_pre_lang = true; + render.full_info_string = true; + render.width = 80; + render.unsafe_ = true; + render.escape = true; + render.list_style = ListStyleType::Star; + render.sourcepos = true; + markdown_to_html( s, - &Options { - extension: ExtensionOptions { - strikethrough: true, - tagfilter: true, - table: true, - autolink: true, - tasklist: true, - superscript: true, - header_ids: Some("user-content-".to_string()), - footnotes: true, - description_lists: true, - front_matter_delimiter: Some("---".to_string()), - shortcodes: true, - }, - parse: ParseOptions { - smart: true, - default_info_string: Some("rust".to_string()), - relaxed_tasklist_matching: true, - }, - render: RenderOptions { - hardbreaks: true, - github_pre_lang: true, - full_info_string: true, - width: 80, - unsafe_: true, - escape: true, - list_style: ListStyleType::Star, - sourcepos: true, - }, - }, + &Options { extension, parse, render }, ); }); diff --git a/fuzz/fuzz_targets/cli_default.rs b/fuzz/fuzz_targets/cli_default.rs index 37490dc2..91d703f9 100644 --- a/fuzz/fuzz_targets/cli_default.rs +++ b/fuzz/fuzz_targets/cli_default.rs @@ -4,19 +4,15 @@ use libfuzzer_sys::fuzz_target; use comrak::{ markdown_to_html_with_plugins, plugins::syntect::SyntectAdapter, Plugins, - RenderPlugins, }; // Note that we end up fuzzing Syntect here. fuzz_target!(|s: &str| { let adapter = SyntectAdapter::new("base16-ocean.dark"); - let plugins = Plugins { - render: RenderPlugins { - codefence_syntax_highlighter: Some(&adapter), - ..Default::default() - }, - }; + + let mut plugins = Plugins::default(); + plugins.render.codefence_syntax_highlighter = Some(&adapter); markdown_to_html_with_plugins(s, &Default::default(), &plugins); }); diff --git a/fuzz/fuzz_targets/gfm.rs b/fuzz/fuzz_targets/gfm.rs index 25e6ad2b..cb903506 100644 --- a/fuzz/fuzz_targets/gfm.rs +++ b/fuzz/fuzz_targets/gfm.rs @@ -9,23 +9,23 @@ use comrak::{markdown_to_html, ExtensionOptions, Options, RenderOptions}; // options are routinely used by Commonmarker users. fuzz_target!(|s: &str| { + let mut extension = ExtensionOptions::default(); + extension.strikethrough = true; + extension.tagfilter = true; + extension.table = true; + extension.autolink = true; + + let mut render = RenderOptions::default(); + render.hardbreaks = true; + render.github_pre_lang = true; + render.unsafe_ = true; + markdown_to_html( s, &Options { - extension: ExtensionOptions { - strikethrough: true, - tagfilter: true, - table: true, - autolink: true, - ..Default::default() - }, + extension, parse: Default::default(), - render: RenderOptions { - hardbreaks: true, - github_pre_lang: true, - unsafe_: true, - ..Default::default() - }, + render, }, ); }); diff --git a/fuzz/fuzz_targets/gfm_footnotes.rs b/fuzz/fuzz_targets/gfm_footnotes.rs index 1f456598..28484132 100644 --- a/fuzz/fuzz_targets/gfm_footnotes.rs +++ b/fuzz/fuzz_targets/gfm_footnotes.rs @@ -9,24 +9,24 @@ use comrak::{markdown_to_html, ExtensionOptions, Options, RenderOptions}; // options are routinely used by Commonmarker users. fuzz_target!(|s: &str| { + let mut extension = ExtensionOptions::default(); + extension.strikethrough = true; + extension.tagfilter = true; + extension.table = true; + extension.autolink = true; + extension.footnotes = true; + + let mut render = RenderOptions::default(); + render.hardbreaks = true; + render.github_pre_lang = true; + render.unsafe_ = true; + markdown_to_html( s, &Options { - extension: ExtensionOptions { - strikethrough: true, - tagfilter: true, - table: true, - autolink: true, - footnotes: true, - ..Default::default() - }, + extension, parse: Default::default(), - render: RenderOptions { - hardbreaks: true, - github_pre_lang: true, - unsafe_: true, - ..Default::default() - }, + render, }, ); }); diff --git a/fuzz/fuzz_targets/gfm_sourcepos.rs b/fuzz/fuzz_targets/gfm_sourcepos.rs index 736a47d8..23100715 100644 --- a/fuzz/fuzz_targets/gfm_sourcepos.rs +++ b/fuzz/fuzz_targets/gfm_sourcepos.rs @@ -9,24 +9,24 @@ use comrak::{markdown_to_html, ExtensionOptions, Options, RenderOptions}; // options are routinely used by Commonmarker users. fuzz_target!(|s: &str| { + let mut extension = ExtensionOptions::default(); + extension.strikethrough = true; + extension.tagfilter = true; + extension.table = true; + extension.autolink = true; + + let mut render = RenderOptions::default(); + render.hardbreaks = true; + render.github_pre_lang = true; + render.unsafe_ = true; + render.sourcepos = true; + markdown_to_html( s, &Options { - extension: ExtensionOptions { - strikethrough: true, - tagfilter: true, - table: true, - autolink: true, - ..Default::default() - }, + extension, parse: Default::default(), - render: RenderOptions { - hardbreaks: true, - github_pre_lang: true, - unsafe_: true, - sourcepos: true, - ..Default::default() - }, + render, }, ); }); diff --git a/fuzz/fuzz_targets/quadratic.rs b/fuzz/fuzz_targets/quadratic.rs index 0dfd2a1c..e4fa14a0 100644 --- a/fuzz/fuzz_targets/quadratic.rs +++ b/fuzz/fuzz_targets/quadratic.rs @@ -196,19 +196,19 @@ struct FuzzExtensionOptions { impl FuzzExtensionOptions { fn to_options(&self) -> ExtensionOptions { - ExtensionOptions { - strikethrough: self.strikethrough, - tagfilter: self.tagfilter, - table: self.table, - autolink: self.autolink, - tasklist: self.tasklist, - superscript: self.superscript, - footnotes: self.footnotes, - description_lists: self.description_lists, - shortcodes: self.shortcodes, - front_matter_delimiter: None, - header_ids: None, - } + let mut extension = ExtensionOptions::default(); + extension.strikethrough = self.strikethrough; + extension.tagfilter = self.tagfilter; + extension.table = self.table; + extension.autolink = self.autolink; + extension.tasklist = self.tasklist; + extension.superscript = self.superscript; + extension.footnotes = self.footnotes; + extension.description_lists = self.description_lists; + extension.shortcodes = self.shortcodes; + extension.front_matter_delimiter = None; + extension.header_ids = None; + extension } } @@ -220,11 +220,11 @@ struct FuzzParseOptions { impl FuzzParseOptions { fn to_options(&self) -> ParseOptions { - ParseOptions { - smart: self.smart, - default_info_string: None, - relaxed_tasklist_matching: self.relaxed_tasklist_matching, - } + let mut parse = ParseOptions::default(); + parse.smart = self.smart; + parse.default_info_string = None; + parse.relaxed_tasklist_matching = self.relaxed_tasklist_matching; + parse } } @@ -242,16 +242,16 @@ struct FuzzRenderOptions { impl FuzzRenderOptions { fn to_options(&self) -> RenderOptions { - RenderOptions { - hardbreaks: self.hardbreaks, - github_pre_lang: self.github_pre_lang, - full_info_string: self.full_info_string, - width: self.width, - unsafe_: self.unsafe_, - escape: self.escape, - list_style: self.list_style, - sourcepos: self.sourcepos, - } + let mut render = RenderOptions::default(); + render.hardbreaks = self.hardbreaks; + render.github_pre_lang = self.github_pre_lang; + render.full_info_string = self.full_info_string; + render.width = self.width; + render.unsafe_ = self.unsafe_; + render.escape = self.escape; + render.list_style = self.list_style; + render.sourcepos = self.sourcepos; + render } } diff --git a/src/main.rs b/src/main.rs index 62c72476..7debb127 100644 --- a/src/main.rs +++ b/src/main.rs @@ -210,23 +210,25 @@ fn main() -> Result<(), Box> { extension.shortcodes = cli.gemojis; } + let mut parse = ParseOptions::default(); + parse.smart = cli.smart; + parse.default_info_string = cli.default_info_string; + parse.relaxed_tasklist_matching = cli.relaxed_tasklist_character; + + let mut render = RenderOptions::default(); + render.hardbreaks = cli.hardbreaks; + render.github_pre_lang = cli.github_pre_lang || cli.gfm; + render.full_info_string = cli.full_info_string; + render.width = cli.width; + render.unsafe_ = cli.unsafe_; + render.escape = cli.escape; + render.list_style = cli.list_style.into(); + render.sourcepos = cli.sourcepos; + let options = Options { extension, - parse: ParseOptions { - smart: cli.smart, - default_info_string: cli.default_info_string, - relaxed_tasklist_matching: cli.relaxed_tasklist_character, - }, - render: RenderOptions { - hardbreaks: cli.hardbreaks, - github_pre_lang: cli.github_pre_lang || cli.gfm, - full_info_string: cli.full_info_string, - width: cli.width, - unsafe_: cli.unsafe_, - escape: cli.escape, - list_style: cli.list_style.into(), - sourcepos: cli.sourcepos, - }, + parse, + render, }; let syntax_highlighter: Option<&dyn SyntaxHighlighterAdapter>; diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 42f12806..53cc48e1 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -150,8 +150,6 @@ pub struct Options { pub render: RenderOptions, } -// NOTE: The shortcodes feature adds a new field, so mark this as non-exhaustive since it's part of -// the public API #[non_exhaustive] #[derive(Default, Debug, Clone)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] @@ -348,6 +346,7 @@ pub struct ExtensionOptions { pub shortcodes: bool, } +#[non_exhaustive] #[derive(Default, Debug, Clone)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] /// Options for parser functions. @@ -384,6 +383,7 @@ pub struct ParseOptions { pub relaxed_tasklist_matching: bool, } +#[non_exhaustive] #[derive(Default, Debug, Clone, Copy)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] /// Options for formatter functions. @@ -532,6 +532,7 @@ pub struct RenderOptions { pub sourcepos: bool, } +#[non_exhaustive] #[derive(Default, Debug)] /// Umbrella plugins struct. pub struct Plugins<'p> { @@ -539,6 +540,7 @@ pub struct Plugins<'p> { pub render: RenderPlugins<'p>, } +#[non_exhaustive] #[derive(Default)] /// Plugins for alternative rendering. pub struct RenderPlugins<'p> {