mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Make things more consistent ♻
This commit is contained in:
parent
adfd7dd073
commit
5ca303ecad
@ -10,10 +10,10 @@ pub use size::Size;
|
|||||||
|
|
||||||
|
|
||||||
/// The core typesetting engine, transforming an abstract syntax tree into a document.
|
/// The core typesetting engine, transforming an abstract syntax tree into a document.
|
||||||
pub(crate) struct Engine<'a> {
|
pub struct Engine<'t> {
|
||||||
// Immutable
|
// Immutable
|
||||||
tree: &'a SyntaxTree<'a>,
|
tree: &'t SyntaxTree<'t>,
|
||||||
ctx: &'a Context<'a>,
|
ctx: &'t Context<'t>,
|
||||||
|
|
||||||
// Mutable
|
// Mutable
|
||||||
fonts: Vec<Font>,
|
fonts: Vec<Font>,
|
||||||
@ -23,22 +23,22 @@ pub(crate) struct Engine<'a> {
|
|||||||
current_width: Size,
|
current_width: Size,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Engine<'a> {
|
impl<'t> Engine<'t> {
|
||||||
/// Create a new generator from a syntax tree.
|
/// 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 {
|
Engine {
|
||||||
tree,
|
tree,
|
||||||
ctx: context,
|
ctx: context,
|
||||||
fonts: Vec::new(),
|
fonts: vec![],
|
||||||
active_font: 0,
|
active_font: 0,
|
||||||
text_commands: Vec::new(),
|
text_commands: vec![],
|
||||||
current_line: String::new(),
|
current_line: String::new(),
|
||||||
current_width: Size::zero(),
|
current_width: Size::zero(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate the abstract document.
|
/// Generate the abstract document.
|
||||||
pub fn typeset(mut self) -> TypeResult<Document> {
|
pub(crate) fn typeset(mut self) -> TypeResult<Document> {
|
||||||
// Load font defined by style
|
// Load font defined by style
|
||||||
let mut font = None;
|
let mut font = None;
|
||||||
let filter = FontFilter::new(&self.ctx.style.font_families);
|
let filter = FontFilter::new(&self.ctx.style.font_families);
|
||||||
|
@ -5,7 +5,7 @@ use std::ops::*;
|
|||||||
|
|
||||||
|
|
||||||
/// A general size (unit of length) type.
|
/// A general size (unit of length) type.
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq, Default)]
|
||||||
pub struct Size {
|
pub struct Size {
|
||||||
/// The size in typographic points (1/72 inches).
|
/// The size in typographic points (1/72 inches).
|
||||||
points: f32,
|
points: f32,
|
||||||
@ -62,6 +62,7 @@ impl Debug for Size {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PartialOrd for Size {
|
impl PartialOrd for Size {
|
||||||
|
#[inline]
|
||||||
fn partial_cmp(&self, other: &Size) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &Size) -> Option<Ordering> {
|
||||||
self.points.partial_cmp(&other.points)
|
self.points.partial_cmp(&other.points)
|
||||||
}
|
}
|
||||||
@ -70,12 +71,14 @@ impl PartialOrd for Size {
|
|||||||
impl Neg for Size {
|
impl Neg for Size {
|
||||||
type Output = Size;
|
type Output = Size;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn neg(self) -> Size {
|
fn neg(self) -> Size {
|
||||||
Size { points: -self.points }
|
Size { points: -self.points }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sum for Size {
|
impl Sum for Size {
|
||||||
|
#[inline]
|
||||||
fn sum<I>(iter: I) -> Size where I: Iterator<Item=Size> {
|
fn sum<I>(iter: I) -> Size where I: Iterator<Item=Size> {
|
||||||
iter.fold(Size::zero(), Add::add)
|
iter.fold(Size::zero(), Add::add)
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ struct PdfEngine<'d, W: Write> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Offsets for the various groups of ids.
|
/// Offsets for the various groups of ids.
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
struct Offsets {
|
struct Offsets {
|
||||||
catalog: Ref,
|
catalog: Ref,
|
||||||
page_tree: Ref,
|
page_tree: Ref,
|
||||||
|
55
src/font.rs
55
src/font.rs
@ -143,8 +143,8 @@ impl Font {
|
|||||||
loca: None,
|
loca: None,
|
||||||
glyphs: Vec::with_capacity(chars.len()),
|
glyphs: Vec::with_capacity(chars.len()),
|
||||||
chars,
|
chars,
|
||||||
records: Vec::new(),
|
records: vec![],
|
||||||
body: Vec::new(),
|
body: vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
subsetter.subset(needed_tables, optional_tables)
|
subsetter.subset(needed_tables, optional_tables)
|
||||||
@ -152,7 +152,7 @@ impl Font {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Font metrics relevant to the typesetting engine.
|
/// Font metrics relevant to the typesetting engine.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
pub struct FontMetrics {
|
pub struct FontMetrics {
|
||||||
/// Whether the font is italic.
|
/// Whether the font is italic.
|
||||||
pub is_italic: bool,
|
pub is_italic: bool,
|
||||||
@ -275,10 +275,10 @@ macro_rules! font_info {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Criteria to filter fonts.
|
/// Criteria to filter fonts.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
pub struct FontFilter<'a> {
|
pub struct FontFilter<'a> {
|
||||||
/// A fallback list of font families we accept. The first family in this list, that also
|
/// A fallback list of font families to accept. The first family in this list, that also
|
||||||
/// satisfies the other conditions shall be returned.
|
/// satisfies the other conditions, shall be returned.
|
||||||
pub families: &'a [FontFamily],
|
pub families: &'a [FontFamily],
|
||||||
/// If some, matches only italic/non-italic fonts, otherwise any.
|
/// If some, matches only italic/non-italic fonts, otherwise any.
|
||||||
pub italic: Option<bool>,
|
pub italic: Option<bool>,
|
||||||
@ -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.
|
/// Set the italic value to something.
|
||||||
pub fn italic(&mut self, italic: bool) -> &mut Self {
|
pub fn italic(&mut self, italic: bool) -> &mut Self {
|
||||||
self.italic = Some(italic); self
|
self.italic = Some(italic); self
|
||||||
@ -314,6 +307,13 @@ impl<'a> FontFilter<'a> {
|
|||||||
pub fn bold(&mut self, bold: bool) -> &mut Self {
|
pub fn bold(&mut self, bold: bool) -> &mut Self {
|
||||||
self.bold = Some(bold); 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).
|
/// 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.
|
/// A font provider serving fonts from a folder on the local file system.
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct FileSystemFontProvider {
|
pub struct FileSystemFontProvider {
|
||||||
base: PathBuf,
|
base: PathBuf,
|
||||||
paths: Vec<PathBuf>,
|
paths: Vec<PathBuf>,
|
||||||
@ -346,29 +347,36 @@ impl FileSystemFontProvider {
|
|||||||
/// ("NotoSans-Italic.ttf", font_info!(["NotoSans", SansSerif], italic)),
|
/// ("NotoSans-Italic.ttf", font_info!(["NotoSans", SansSerif], italic)),
|
||||||
/// ]);
|
/// ]);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[inline]
|
||||||
pub fn new<B, I, P>(base: B, infos: I) -> FileSystemFontProvider
|
pub fn new<B, I, P>(base: B, infos: I) -> FileSystemFontProvider
|
||||||
where
|
where
|
||||||
B: Into<PathBuf>,
|
B: Into<PathBuf>,
|
||||||
I: IntoIterator<Item = (P, FontInfo)>,
|
I: IntoIterator<Item = (P, FontInfo)>,
|
||||||
P: Into<PathBuf>,
|
P: Into<PathBuf>,
|
||||||
{
|
{
|
||||||
let mut paths = Vec::new();
|
// Find out how long the iterator is at least, to reserve the correct
|
||||||
let mut font_infos = Vec::new();
|
// 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());
|
paths.push(path.into());
|
||||||
font_infos.push(info);
|
infos.push(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
FileSystemFontProvider {
|
FileSystemFontProvider {
|
||||||
base: base.into(),
|
base: base.into(),
|
||||||
paths,
|
paths,
|
||||||
infos: font_infos,
|
infos,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FontProvider for FileSystemFontProvider {
|
impl FontProvider for FileSystemFontProvider {
|
||||||
|
#[inline]
|
||||||
fn get(&self, info: &FontInfo) -> Option<Box<dyn FontData>> {
|
fn get(&self, info: &FontInfo) -> Option<Box<dyn FontData>> {
|
||||||
let index = self.infos.iter().position(|i| i == info)?;
|
let index = self.infos.iter().position(|i| i == info)?;
|
||||||
let path = &self.paths[index];
|
let path = &self.paths[index];
|
||||||
@ -376,16 +384,17 @@ impl FontProvider for FileSystemFontProvider {
|
|||||||
Some(Box::new(file) as Box<FontData>)
|
Some(Box::new(file) as Box<FontData>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn available<'a>(&'a self) -> &'a [FontInfo] {
|
fn available<'a>(&'a self) -> &'a [FontInfo] {
|
||||||
&self.infos
|
&self.infos
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Subsetter<'p> {
|
struct Subsetter<'d> {
|
||||||
// Original font
|
// Original font
|
||||||
font: &'p Font,
|
font: &'d Font,
|
||||||
reader: OpenTypeReader<Cursor<&'p [u8]>>,
|
reader: OpenTypeReader<Cursor<&'d [u8]>>,
|
||||||
outlines: Outlines,
|
outlines: Outlines,
|
||||||
tables: Vec<TableRecord>,
|
tables: Vec<TableRecord>,
|
||||||
cmap: Option<CharMap>,
|
cmap: Option<CharMap>,
|
||||||
@ -399,7 +408,7 @@ struct Subsetter<'p> {
|
|||||||
body: Vec<u8>,
|
body: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'p> Subsetter<'p> {
|
impl<'d> Subsetter<'d> {
|
||||||
fn subset<I1, S1, I2, S2>(mut self, needed_tables: I1, optional_tables: I2)
|
fn subset<I1, S1, I2, S2>(mut self, needed_tables: I1, optional_tables: I2)
|
||||||
-> FontResult<Font>
|
-> FontResult<Font>
|
||||||
where
|
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) {
|
let record = match self.tables.binary_search_by_key(&tag, |r| r.tag) {
|
||||||
Ok(index) => &self.tables[index],
|
Ok(index) => &self.tables[index],
|
||||||
Err(_) => return Err(FontError::MissingTable(tag.to_string())),
|
Err(_) => return Err(FontError::MissingTable(tag.to_string())),
|
||||||
|
11
src/lib.rs
11
src/lib.rs
@ -2,13 +2,14 @@
|
|||||||
//!
|
//!
|
||||||
//! # Compilation
|
//! # Compilation
|
||||||
//! - **Parsing:** The parsing step first transforms a plain string into an
|
//! - **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
|
//! [iterator of tokens](crate::parsing::Tokens). Then the [parser](crate::parsing::Parser)
|
||||||
//! a syntax tree. The structures describing the tree can be found in the [`syntax`] module.
|
//! 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
|
//! - **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.
|
//! representation contains already the finished layout.
|
||||||
//! - **Exporting:** The finished document can then be exported into supported formats. Submodules
|
//! - **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_.
|
//! format is _PDF_.
|
||||||
//!
|
//!
|
||||||
//! # Example
|
//! # Example
|
||||||
@ -82,7 +83,7 @@ impl<'p> Compiler<'p> {
|
|||||||
Compiler {
|
Compiler {
|
||||||
context: Context {
|
context: Context {
|
||||||
style: Style::default(),
|
style: Style::default(),
|
||||||
font_providers: Vec::new(),
|
font_providers: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,6 @@ enum TokensState<'s> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for TokensState<'_> {
|
impl PartialEq for TokensState<'_> {
|
||||||
#[inline]
|
|
||||||
fn eq(&self, other: &TokensState) -> bool {
|
fn eq(&self, other: &TokensState) -> bool {
|
||||||
use TokensState as TS;
|
use TokensState as TS;
|
||||||
|
|
||||||
@ -184,26 +183,22 @@ impl<'s> Tokens<'s> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Advance the iterator by one step.
|
/// Advance the iterator by one step.
|
||||||
#[inline]
|
|
||||||
fn advance(&mut self) {
|
fn advance(&mut self) {
|
||||||
self.words.next();
|
self.words.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Switch to the given state.
|
/// Switch to the given state.
|
||||||
#[inline]
|
|
||||||
fn switch(&mut self, mut state: TokensState<'s>) {
|
fn switch(&mut self, mut state: TokensState<'s>) {
|
||||||
swap(&mut state, &mut self.state);
|
swap(&mut state, &mut self.state);
|
||||||
self.stack.push(state);
|
self.stack.push(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Go back to the top-of-stack state.
|
/// Go back to the top-of-stack state.
|
||||||
#[inline]
|
|
||||||
fn unswitch(&mut self) {
|
fn unswitch(&mut self) {
|
||||||
self.state = self.stack.pop().unwrap_or(TokensState::Body);
|
self.state = self.stack.pop().unwrap_or(TokensState::Body);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Advance and return the given token.
|
/// Advance and return the given token.
|
||||||
#[inline]
|
|
||||||
fn consumed(&mut self, token: Token<'s>) -> Token<'s> {
|
fn consumed(&mut self, token: Token<'s>) -> Token<'s> {
|
||||||
self.advance();
|
self.advance();
|
||||||
token
|
token
|
||||||
@ -211,8 +206,8 @@ impl<'s> Tokens<'s> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Transforms token streams to syntax trees.
|
/// Transforms token streams to syntax trees.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug)]
|
||||||
pub struct Parser<'s, T> where T: Iterator<Item = Token<'s>> {
|
pub struct Parser<'s, T> where T: Iterator<Item=Token<'s>> {
|
||||||
tokens: Peekable<T>,
|
tokens: Peekable<T>,
|
||||||
state: ParserState,
|
state: ParserState,
|
||||||
stack: Vec<Function<'s>>,
|
stack: Vec<Function<'s>>,
|
||||||
@ -220,7 +215,7 @@ pub struct Parser<'s, T> where T: Iterator<Item = Token<'s>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The state the parser is in.
|
/// The state the parser is in.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
enum ParserState {
|
enum ParserState {
|
||||||
/// The base state of the parser.
|
/// The base state of the parser.
|
||||||
Body,
|
Body,
|
||||||
@ -228,9 +223,9 @@ enum ParserState {
|
|||||||
Function,
|
Function,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s, T> Parser<'s, T> where T: Iterator<Item = Token<'s>> {
|
impl<'s, T> Parser<'s, T> where T: Iterator<Item=Token<'s>> {
|
||||||
/// Create a new parser from a type that emits results of tokens.
|
/// 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 {
|
Parser {
|
||||||
tokens: tokens.peekable(),
|
tokens: tokens.peekable(),
|
||||||
state: ParserState::Body,
|
state: ParserState::Body,
|
||||||
@ -240,13 +235,13 @@ impl<'s, T> Parser<'s, T> where T: Iterator<Item = Token<'s>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Parse into an abstract syntax tree.
|
/// Parse into an abstract syntax tree.
|
||||||
pub fn parse(mut self) -> ParseResult<SyntaxTree<'s>> {
|
pub(crate) fn parse(mut self) -> ParseResult<SyntaxTree<'s>> {
|
||||||
use ParserState as PS;
|
use ParserState as PS;
|
||||||
|
|
||||||
while let Some(token) = self.tokens.next() {
|
while let Some(token) = self.tokens.next() {
|
||||||
// Comment
|
// Comment
|
||||||
if token == Token::Hashtag {
|
if token == Token::Hashtag {
|
||||||
self.skip_while(|t| *t != Token::Newline);
|
self.skip_while(|&t| t != Token::Newline);
|
||||||
self.advance();
|
self.advance();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -314,13 +309,11 @@ impl<'s, T> Parser<'s, T> where T: Iterator<Item = Token<'s>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Advance the iterator by one step.
|
/// Advance the iterator by one step.
|
||||||
#[inline]
|
|
||||||
fn advance(&mut self) {
|
fn advance(&mut self) {
|
||||||
self.tokens.next();
|
self.tokens.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Skip tokens until the condition is met.
|
/// Skip tokens until the condition is met.
|
||||||
#[inline]
|
|
||||||
fn skip_while<F>(&mut self, f: F) where F: Fn(&Token) -> bool {
|
fn skip_while<F>(&mut self, f: F) where F: Fn(&Token) -> bool {
|
||||||
while let Some(token) = self.tokens.peek() {
|
while let Some(token) = self.tokens.peek() {
|
||||||
if !f(token) {
|
if !f(token) {
|
||||||
@ -331,16 +324,14 @@ impl<'s, T> Parser<'s, T> where T: Iterator<Item = Token<'s>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Switch the state.
|
/// Switch the state.
|
||||||
#[inline]
|
|
||||||
fn switch(&mut self, state: ParserState) {
|
fn switch(&mut self, state: ParserState) {
|
||||||
self.state = state;
|
self.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Append a node to the top-of-stack function or the main tree itself.
|
/// Append a node to the top-of-stack function or the main tree itself.
|
||||||
#[inline]
|
|
||||||
fn append(&mut self, node: Node<'s>) {
|
fn append(&mut self, node: Node<'s>) {
|
||||||
let tree = match self.stack.last_mut() {
|
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,
|
None => &mut self.tree,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -348,7 +339,6 @@ impl<'s, T> Parser<'s, T> where T: Iterator<Item = Token<'s>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Gives a parsing error with a message.
|
/// Gives a parsing error with a message.
|
||||||
#[inline]
|
|
||||||
fn err<R, S: Into<String>>(&self, message: S) -> ParseResult<R> {
|
fn err<R, S: Into<String>>(&self, message: S) -> ParseResult<R> {
|
||||||
Err(ParseError { message: message.into() })
|
Err(ParseError { message: message.into() })
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/// A logical unit of the incoming text stream.
|
/// A logical unit of the incoming text stream.
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
pub enum Token<'s> {
|
pub enum Token<'s> {
|
||||||
/// One or more whitespace (non-newline) codepoints.
|
/// One or more whitespace (non-newline) codepoints.
|
||||||
Space,
|
Space,
|
||||||
|
@ -49,7 +49,7 @@ pub struct Spline<'s, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Represents either a splitted substring or a splinor.
|
/// 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> {
|
pub enum Splined<'s, T> {
|
||||||
/// A substring.
|
/// A substring.
|
||||||
Value(&'s str),
|
Value(&'s str),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user