From 5ca303ecadff190800dd55a5a5ae224dc28a3920 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Sat, 30 Mar 2019 20:51:09 +0100 Subject: [PATCH] =?UTF-8?q?Make=20things=20more=20consistent=20=E2=99=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/engine/mod.rs | 16 +++++++------- src/engine/size.rs | 5 ++++- src/export/pdf.rs | 2 +- src/font.rs | 55 +++++++++++++++++++++++++++------------------- src/lib.rs | 11 +++++----- src/parsing.rs | 26 +++++++--------------- src/syntax.rs | 2 +- src/utility.rs | 2 +- 8 files changed, 61 insertions(+), 58 deletions(-) diff --git a/src/engine/mod.rs b/src/engine/mod.rs index baad9bac8..daec2fbb7 100644 --- a/src/engine/mod.rs +++ b/src/engine/mod.rs @@ -10,10 +10,10 @@ pub use size::Size; /// The core typesetting engine, transforming an abstract syntax tree into a document. -pub(crate) struct Engine<'a> { +pub struct Engine<'t> { // Immutable - tree: &'a SyntaxTree<'a>, - ctx: &'a Context<'a>, + tree: &'t SyntaxTree<'t>, + ctx: &'t Context<'t>, // Mutable fonts: Vec, @@ -23,22 +23,22 @@ pub(crate) struct Engine<'a> { current_width: Size, } -impl<'a> Engine<'a> { +impl<'t> Engine<'t> { /// Create a new generator from a syntax tree. - pub fn new(tree: &'a SyntaxTree<'a>, context: &'a Context<'a>) -> Engine<'a> { + pub(crate) fn new(tree: &'t SyntaxTree<'t>, context: &'t Context<'t>) -> Engine<'t> { Engine { tree, ctx: context, - fonts: Vec::new(), + fonts: vec![], active_font: 0, - text_commands: Vec::new(), + text_commands: vec![], current_line: String::new(), current_width: Size::zero(), } } /// Generate the abstract document. - pub fn typeset(mut self) -> TypeResult { + pub(crate) fn typeset(mut self) -> TypeResult { // Load font defined by style let mut font = None; let filter = FontFilter::new(&self.ctx.style.font_families); diff --git a/src/engine/size.rs b/src/engine/size.rs index f66641c00..bf79a3c42 100644 --- a/src/engine/size.rs +++ b/src/engine/size.rs @@ -5,7 +5,7 @@ use std::ops::*; /// A general size (unit of length) type. -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, PartialEq, Default)] pub struct Size { /// The size in typographic points (1/72 inches). points: f32, @@ -62,6 +62,7 @@ impl Debug for Size { } impl PartialOrd for Size { + #[inline] fn partial_cmp(&self, other: &Size) -> Option { self.points.partial_cmp(&other.points) } @@ -70,12 +71,14 @@ impl PartialOrd for Size { impl Neg for Size { type Output = Size; + #[inline] fn neg(self) -> Size { Size { points: -self.points } } } impl Sum for Size { + #[inline] fn sum(iter: I) -> Size where I: Iterator { iter.fold(Size::zero(), Add::add) } diff --git a/src/export/pdf.rs b/src/export/pdf.rs index a2260f74e..91cd9cd82 100644 --- a/src/export/pdf.rs +++ b/src/export/pdf.rs @@ -40,7 +40,7 @@ struct PdfEngine<'d, W: Write> { } /// Offsets for the various groups of ids. -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, Eq, PartialEq)] struct Offsets { catalog: Ref, page_tree: Ref, diff --git a/src/font.rs b/src/font.rs index 298f0ffd5..c88d4578c 100644 --- a/src/font.rs +++ b/src/font.rs @@ -143,8 +143,8 @@ impl Font { loca: None, glyphs: Vec::with_capacity(chars.len()), chars, - records: Vec::new(), - body: Vec::new(), + records: vec![], + body: vec![], }; subsetter.subset(needed_tables, optional_tables) @@ -152,7 +152,7 @@ impl Font { } /// Font metrics relevant to the typesetting engine. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, PartialEq)] pub struct FontMetrics { /// Whether the font is italic. pub is_italic: bool, @@ -275,10 +275,10 @@ macro_rules! font_info { } /// Criteria to filter fonts. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq)] pub struct FontFilter<'a> { - /// A fallback list of font families we accept. The first family in this list, that also - /// satisfies the other conditions shall be returned. + /// A fallback list of font families to accept. The first family in this list, that also + /// satisfies the other conditions, shall be returned. pub families: &'a [FontFamily], /// If some, matches only italic/non-italic fonts, otherwise any. pub italic: Option, @@ -298,13 +298,6 @@ impl<'a> FontFilter<'a> { } } - /// Whether this filter matches the given info. - pub fn matches(&self, info: &FontInfo) -> bool { - self.italic.map(|i| i == info.italic).unwrap_or(true) - && self.bold.map(|i| i == info.bold).unwrap_or(true) - && self.families.iter().any(|family| info.families.contains(family)) - } - /// Set the italic value to something. pub fn italic(&mut self, italic: bool) -> &mut Self { self.italic = Some(italic); self @@ -314,6 +307,13 @@ impl<'a> FontFilter<'a> { pub fn bold(&mut self, bold: bool) -> &mut Self { self.bold = Some(bold); self } + + /// Whether this filter matches the given info. + pub fn matches(&self, info: &FontInfo) -> bool { + self.italic.map(|i| i == info.italic).unwrap_or(true) + && self.bold.map(|i| i == info.bold).unwrap_or(true) + && self.families.iter().any(|family| info.families.contains(family)) + } } /// A family of fonts (either generic or named). @@ -326,6 +326,7 @@ pub enum FontFamily { } /// A font provider serving fonts from a folder on the local file system. +#[derive(Debug)] pub struct FileSystemFontProvider { base: PathBuf, paths: Vec, @@ -346,29 +347,36 @@ impl FileSystemFontProvider { /// ("NotoSans-Italic.ttf", font_info!(["NotoSans", SansSerif], italic)), /// ]); /// ``` + #[inline] pub fn new(base: B, infos: I) -> FileSystemFontProvider where B: Into, I: IntoIterator, P: Into, { - let mut paths = Vec::new(); - let mut font_infos = Vec::new(); + // Find out how long the iterator is at least, to reserve the correct + // capacity for the vectors. + let iter = infos.into_iter(); + let min = iter.size_hint().0; - for (path, info) in infos.into_iter() { + // Split the iterator into two seperated vectors. + let mut paths = Vec::with_capacity(min); + let mut infos = Vec::with_capacity(min); + for (path, info) in iter { paths.push(path.into()); - font_infos.push(info); + infos.push(info); } FileSystemFontProvider { base: base.into(), paths, - infos: font_infos, + infos, } } } impl FontProvider for FileSystemFontProvider { + #[inline] fn get(&self, info: &FontInfo) -> Option> { let index = self.infos.iter().position(|i| i == info)?; let path = &self.paths[index]; @@ -376,16 +384,17 @@ impl FontProvider for FileSystemFontProvider { Some(Box::new(file) as Box) } + #[inline] fn available<'a>(&'a self) -> &'a [FontInfo] { &self.infos } } #[derive(Debug)] -struct Subsetter<'p> { +struct Subsetter<'d> { // Original font - font: &'p Font, - reader: OpenTypeReader>, + font: &'d Font, + reader: OpenTypeReader>, outlines: Outlines, tables: Vec, cmap: Option, @@ -399,7 +408,7 @@ struct Subsetter<'p> { body: Vec, } -impl<'p> Subsetter<'p> { +impl<'d> Subsetter<'d> { fn subset(mut self, needed_tables: I1, optional_tables: I2) -> FontResult where @@ -726,7 +735,7 @@ impl<'p> Subsetter<'p> { })) } - fn get_table_data(&self, tag: Tag) -> FontResult<&'p [u8]> { + fn get_table_data(&self, tag: Tag) -> FontResult<&'d [u8]> { let record = match self.tables.binary_search_by_key(&tag, |r| r.tag) { Ok(index) => &self.tables[index], Err(_) => return Err(FontError::MissingTable(tag.to_string())), diff --git a/src/lib.rs b/src/lib.rs index 44c7642e0..b9992b427 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,13 +2,14 @@ //! //! # Compilation //! - **Parsing:** The parsing step first transforms a plain string into an -//! [iterator of tokens](crate::parsing::Tokens). Then the parser operates on that to construct -//! a syntax tree. The structures describing the tree can be found in the [`syntax`] module. +//! [iterator of tokens](crate::parsing::Tokens). Then the [parser](crate::parsing::Parser) +//! operates on that to construct a syntax tree. The structures describing the tree can be found +//! in the [syntax] module. //! - **Typesetting:** The next step is to transform the syntax tree into a portable representation -//! of the typesetted document. Types for these can be found in the [`doc`] module. This +//! of the typesetted document. Types for these can be found in the [doc] module. This //! representation contains already the finished layout. //! - **Exporting:** The finished document can then be exported into supported formats. Submodules -//! for the supported formats are located in the [`export`] module. Currently the only supported +//! for the supported formats are located in the [export] module. Currently the only supported //! format is _PDF_. //! //! # Example @@ -82,7 +83,7 @@ impl<'p> Compiler<'p> { Compiler { context: Context { style: Style::default(), - font_providers: Vec::new(), + font_providers: vec![], } } } diff --git a/src/parsing.rs b/src/parsing.rs index 92eaae75d..4341ed4af 100644 --- a/src/parsing.rs +++ b/src/parsing.rs @@ -44,7 +44,6 @@ enum TokensState<'s> { } impl PartialEq for TokensState<'_> { - #[inline] fn eq(&self, other: &TokensState) -> bool { use TokensState as TS; @@ -184,26 +183,22 @@ impl<'s> Tokens<'s> { } /// Advance the iterator by one step. - #[inline] fn advance(&mut self) { self.words.next(); } /// Switch to the given state. - #[inline] fn switch(&mut self, mut state: TokensState<'s>) { swap(&mut state, &mut self.state); self.stack.push(state); } /// Go back to the top-of-stack state. - #[inline] fn unswitch(&mut self) { self.state = self.stack.pop().unwrap_or(TokensState::Body); } /// Advance and return the given token. - #[inline] fn consumed(&mut self, token: Token<'s>) -> Token<'s> { self.advance(); token @@ -211,8 +206,8 @@ impl<'s> Tokens<'s> { } /// Transforms token streams to syntax trees. -#[derive(Debug, Clone)] -pub struct Parser<'s, T> where T: Iterator> { +#[derive(Debug)] +pub struct Parser<'s, T> where T: Iterator> { tokens: Peekable, state: ParserState, stack: Vec>, @@ -220,7 +215,7 @@ pub struct Parser<'s, T> where T: Iterator> { } /// The state the parser is in. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, Eq, PartialEq)] enum ParserState { /// The base state of the parser. Body, @@ -228,9 +223,9 @@ enum ParserState { Function, } -impl<'s, T> Parser<'s, T> where T: Iterator> { +impl<'s, T> Parser<'s, T> where T: Iterator> { /// Create a new parser from a type that emits results of tokens. - pub fn new(tokens: T) -> Parser<'s, T> { + pub(crate) fn new(tokens: T) -> Parser<'s, T> { Parser { tokens: tokens.peekable(), state: ParserState::Body, @@ -240,13 +235,13 @@ impl<'s, T> Parser<'s, T> where T: Iterator> { } /// Parse into an abstract syntax tree. - pub fn parse(mut self) -> ParseResult> { + pub(crate) fn parse(mut self) -> ParseResult> { use ParserState as PS; while let Some(token) = self.tokens.next() { // Comment if token == Token::Hashtag { - self.skip_while(|t| *t != Token::Newline); + self.skip_while(|&t| t != Token::Newline); self.advance(); } @@ -314,13 +309,11 @@ impl<'s, T> Parser<'s, T> where T: Iterator> { } /// Advance the iterator by one step. - #[inline] fn advance(&mut self) { self.tokens.next(); } /// Skip tokens until the condition is met. - #[inline] fn skip_while(&mut self, f: F) where F: Fn(&Token) -> bool { while let Some(token) = self.tokens.peek() { if !f(token) { @@ -331,16 +324,14 @@ impl<'s, T> Parser<'s, T> where T: Iterator> { } /// Switch the state. - #[inline] fn switch(&mut self, state: ParserState) { self.state = state; } /// Append a node to the top-of-stack function or the main tree itself. - #[inline] fn append(&mut self, node: Node<'s>) { let tree = match self.stack.last_mut() { - Some(func) => func.body.get_or_insert_with(|| SyntaxTree::new()), + Some(func) => func.body.as_mut().unwrap(), None => &mut self.tree, }; @@ -348,7 +339,6 @@ impl<'s, T> Parser<'s, T> where T: Iterator> { } /// Gives a parsing error with a message. - #[inline] fn err>(&self, message: S) -> ParseResult { Err(ParseError { message: message.into() }) } diff --git a/src/syntax.rs b/src/syntax.rs index 56e116056..46b848323 100644 --- a/src/syntax.rs +++ b/src/syntax.rs @@ -2,7 +2,7 @@ /// A logical unit of the incoming text stream. -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum Token<'s> { /// One or more whitespace (non-newline) codepoints. Space, diff --git a/src/utility.rs b/src/utility.rs index efe519c41..675016ee5 100644 --- a/src/utility.rs +++ b/src/utility.rs @@ -49,7 +49,7 @@ pub struct Spline<'s, T> { } /// Represents either a splitted substring or a splinor. -#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum Splined<'s, T> { /// A substring. Value(&'s str),