From 63c274e7f6aa3a8c3f43abb91935ec924a186f73 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Mon, 15 Nov 2021 16:59:49 +0100 Subject: [PATCH] Make clippy happier and remove `Str` --- src/eval/array.rs | 2 +- src/eval/dict.rs | 40 +++++----- src/eval/function.rs | 11 ++- src/eval/mod.rs | 19 +++-- src/eval/ops.rs | 16 +++- src/eval/str.rs | 164 ----------------------------------------- src/eval/template.rs | 13 ++-- src/eval/value.rs | 26 +++---- src/eval/walk.rs | 18 ++--- src/export/pdf.rs | 10 +-- src/export/subset.rs | 6 +- src/font.rs | 24 ------ src/lib.rs | 5 +- src/library/deco.rs | 4 +- src/library/grid.rs | 11 ++- src/library/image.rs | 2 +- src/library/mod.rs | 6 +- src/library/pad.rs | 2 +- src/library/page.rs | 3 +- src/library/par.rs | 2 +- src/library/spacing.rs | 3 +- src/library/stack.rs | 3 +- src/library/text.rs | 152 ++++++++++++++++---------------------- src/library/utility.rs | 14 ++-- src/loading/fs.rs | 2 +- src/parse/parser.rs | 14 ++-- src/parse/scanner.rs | 2 +- src/parse/tokens.rs | 28 +++---- src/style/mod.rs | 64 ++++++++++++---- src/syntax/ast.rs | 8 +- src/syntax/mod.rs | 4 +- src/syntax/span.rs | 5 ++ src/util/eco_string.rs | 83 ++++++++++++++++++++- src/util/mod.rs | 1 + 34 files changed, 340 insertions(+), 427 deletions(-) delete mode 100644 src/eval/str.rs diff --git a/src/eval/array.rs b/src/eval/array.rs index f6adee6d8..912aa3c04 100644 --- a/src/eval/array.rs +++ b/src/eval/array.rs @@ -70,7 +70,7 @@ impl Array { /// Clear the array. pub fn clear(&mut self) { - if Rc::strong_count(&mut self.0) == 1 { + if Rc::strong_count(&self.0) == 1 { Rc::make_mut(&mut self.0).clear(); } else { *self = Self::new(); diff --git a/src/eval/dict.rs b/src/eval/dict.rs index e7a46b400..0d7198e1e 100644 --- a/src/eval/dict.rs +++ b/src/eval/dict.rs @@ -4,9 +4,9 @@ use std::iter::FromIterator; use std::ops::{Add, AddAssign}; use std::rc::Rc; -use super::{Str, Value}; +use super::Value; use crate::diag::StrResult; -use crate::util::RcExt; +use crate::util::{EcoString, RcExt}; /// Create a new [`Dict`] from key-value pairs. #[allow(unused_macros)] @@ -21,7 +21,7 @@ macro_rules! dict { /// A dictionary from strings to values with clone-on-write value semantics. #[derive(Default, Clone, PartialEq)] -pub struct Dict(Rc>); +pub struct Dict(Rc>); impl Dict { /// Create a new, empty dictionary. @@ -30,7 +30,7 @@ impl Dict { } /// Create a new dictionary from a mapping of strings to values. - pub fn from_map(map: BTreeMap) -> Self { + pub fn from_map(map: BTreeMap) -> Self { Self(Rc::new(map)) } @@ -45,7 +45,7 @@ impl Dict { } /// Borrow the value the given `key` maps to. - pub fn get(&self, key: Str) -> StrResult<&Value> { + pub fn get(&self, key: EcoString) -> StrResult<&Value> { self.0.get(&key).ok_or_else(|| missing_key(&key)) } @@ -53,18 +53,18 @@ impl Dict { /// /// This inserts the key with [`None`](Value::None) as the value if not /// present so far. - pub fn get_mut(&mut self, key: Str) -> &mut Value { - Rc::make_mut(&mut self.0).entry(key.into()).or_default() + pub fn get_mut(&mut self, key: EcoString) -> &mut Value { + Rc::make_mut(&mut self.0).entry(key).or_default() } /// Insert a mapping from the given `key` to the given `value`. - pub fn insert(&mut self, key: Str, value: Value) { - Rc::make_mut(&mut self.0).insert(key.into(), value); + pub fn insert(&mut self, key: EcoString, value: Value) { + Rc::make_mut(&mut self.0).insert(key, value); } /// Clear the dictionary. pub fn clear(&mut self) { - if Rc::strong_count(&mut self.0) == 1 { + if Rc::strong_count(&self.0) == 1 { Rc::make_mut(&mut self.0).clear(); } else { *self = Self::new(); @@ -72,14 +72,14 @@ impl Dict { } /// Iterate over pairs of references to the contained keys and values. - pub fn iter(&self) -> std::collections::btree_map::Iter { + pub fn iter(&self) -> std::collections::btree_map::Iter { self.0.iter() } } /// The missing key access error message. #[cold] -fn missing_key(key: &Str) -> String { +fn missing_key(key: &EcoString) -> String { format!("dictionary does not contain key: {:?}", key) } @@ -119,21 +119,21 @@ impl AddAssign for Dict { } } -impl Extend<(Str, Value)> for Dict { - fn extend>(&mut self, iter: T) { +impl Extend<(EcoString, Value)> for Dict { + fn extend>(&mut self, iter: T) { Rc::make_mut(&mut self.0).extend(iter); } } -impl FromIterator<(Str, Value)> for Dict { - fn from_iter>(iter: T) -> Self { +impl FromIterator<(EcoString, Value)> for Dict { + fn from_iter>(iter: T) -> Self { Self(Rc::new(iter.into_iter().collect())) } } impl IntoIterator for Dict { - type Item = (Str, Value); - type IntoIter = std::collections::btree_map::IntoIter; + type Item = (EcoString, Value); + type IntoIter = std::collections::btree_map::IntoIter; fn into_iter(self) -> Self::IntoIter { Rc::take(self.0).into_iter() @@ -141,8 +141,8 @@ impl IntoIterator for Dict { } impl<'a> IntoIterator for &'a Dict { - type Item = (&'a Str, &'a Value); - type IntoIter = std::collections::btree_map::Iter<'a, Str, Value>; + type Item = (&'a EcoString, &'a Value); + type IntoIter = std::collections::btree_map::Iter<'a, EcoString, Value>; fn into_iter(self) -> Self::IntoIter { self.iter() diff --git a/src/eval/function.rs b/src/eval/function.rs index cbbc0b366..c83d8b2b2 100644 --- a/src/eval/function.rs +++ b/src/eval/function.rs @@ -1,7 +1,7 @@ use std::fmt::{self, Debug, Formatter, Write}; use std::rc::Rc; -use super::{Cast, EvalContext, Str, Value}; +use super::{Cast, EvalContext, Value}; use crate::diag::{At, TypResult}; use crate::syntax::{Span, Spanned}; use crate::util::EcoString; @@ -52,7 +52,10 @@ impl Debug for Function { impl PartialEq for Function { fn eq(&self, other: &Self) -> bool { // We cast to thin pointers for comparison. - Rc::as_ptr(&self.0) as *const () == Rc::as_ptr(&other.0) as *const () + std::ptr::eq( + Rc::as_ptr(&self.0) as *const (), + Rc::as_ptr(&other.0) as *const (), + ) } } @@ -71,7 +74,7 @@ pub struct Arg { /// The span of the whole argument. pub span: Span, /// The name of the argument (`None` for positional arguments). - pub name: Option, + pub name: Option, /// The value of the argument. pub value: Spanned, } @@ -173,7 +176,7 @@ impl Args { } /// Reinterpret these arguments as actually being a dictionary key. - pub fn into_key(self) -> TypResult { + pub fn into_key(self) -> TypResult { self.into_castable("key") } diff --git a/src/eval/mod.rs b/src/eval/mod.rs index fda2184e6..1ff497e89 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -5,8 +5,6 @@ mod array; #[macro_use] mod dict; #[macro_use] -mod str; -#[macro_use] mod value; mod capture; mod function; @@ -15,7 +13,6 @@ mod scope; mod template; mod walk; -pub use self::str::*; pub use array::*; pub use capture::*; pub use dict::*; @@ -31,6 +28,8 @@ use std::io; use std::mem; use std::path::PathBuf; +use unicode_segmentation::UnicodeSegmentation; + use crate::diag::{At, Error, StrResult, Trace, Tracepoint, TypResult}; use crate::geom::{Angle, Fractional, Length, Relative}; use crate::image::ImageStore; @@ -38,7 +37,7 @@ use crate::loading::Loader; use crate::source::{SourceId, SourceStore}; use crate::syntax::ast::*; use crate::syntax::{Span, Spanned}; -use crate::util::RefMutExt; +use crate::util::{EcoString, RefMutExt}; use crate::Context; /// Evaluate a parsed source file into a module. @@ -210,7 +209,7 @@ impl Eval for Lit { LitKind::Angle(v, unit) => Value::Angle(Angle::with_unit(v, unit)), LitKind::Percent(v) => Value::Relative(Relative::new(v / 100.0)), LitKind::Fractional(v) => Value::Fractional(Fractional::new(v)), - LitKind::Str(ref v) => Value::Str(v.into()), + LitKind::Str(ref v) => Value::Str(v.clone()), }) } } @@ -239,7 +238,7 @@ impl Eval for DictExpr { fn eval(&self, ctx: &mut EvalContext) -> TypResult { self.items() - .map(|x| Ok((x.name().take().into(), x.expr().eval(ctx)?))) + .map(|x| Ok((x.name().take(), x.expr().eval(ctx)?))) .collect() } } @@ -401,7 +400,7 @@ impl Eval for CallArgs { CallArg::Named(named) => { items.push(Arg { span, - name: Some(named.name().take().into()), + name: Some(named.name().take()), value: Spanned::new(named.expr().eval(ctx)?, named.expr().span()), }); } @@ -600,7 +599,7 @@ impl Eval for ForExpr { match (key, value, iter) { (None, v, Value::Str(string)) => { - iter!(for (v => value) in string.iter()); + iter!(for (v => value) in string.graphemes(true)); } (None, v, Value::Array(array)) => { iter!(for (v => value) in array.into_iter()); @@ -629,7 +628,7 @@ impl Eval for ImportExpr { fn eval(&self, ctx: &mut EvalContext) -> TypResult { let path = self.path(); - let resolved = path.eval(ctx)?.cast::().at(path.span())?; + let resolved = path.eval(ctx)?.cast::().at(path.span())?; let file = ctx.import(&resolved, path.span())?; let module = &ctx.modules[&file]; @@ -659,7 +658,7 @@ impl Eval for IncludeExpr { fn eval(&self, ctx: &mut EvalContext) -> TypResult { let path = self.path(); - let resolved = path.eval(ctx)?.cast::().at(path.span())?; + let resolved = path.eval(ctx)?.cast::().at(path.span())?; let file = ctx.import(&resolved, path.span())?; let module = &ctx.modules[&file]; Ok(Value::Template(module.template.clone())) diff --git a/src/eval/ops.rs b/src/eval/ops.rs index 732bfb143..e40fa78de 100644 --- a/src/eval/ops.rs +++ b/src/eval/ops.rs @@ -1,7 +1,9 @@ use std::cmp::Ordering; +use std::convert::TryFrom; use super::Value; use crate::diag::StrResult; +use crate::util::EcoString; use Value::*; /// Bail with a type mismatch error. @@ -150,8 +152,8 @@ pub fn mul(lhs: Value, rhs: Value) -> StrResult { (Fractional(a), Float(b)) => Fractional(a * b), (Int(a), Fractional(b)) => Fractional(a as f64 * b), - (Str(a), Int(b)) => Str(a.repeat(b)?), - (Int(a), Str(b)) => Str(b.repeat(a)?), + (Str(a), Int(b)) => Str(repeat_str(a, b)?), + (Int(a), Str(b)) => Str(repeat_str(b, a)?), (Array(a), Int(b)) => Array(a.repeat(b)?), (Int(a), Array(b)) => Array(b.repeat(a)?), (Template(a), Int(b)) => Template(a.repeat(b)?), @@ -161,6 +163,16 @@ pub fn mul(lhs: Value, rhs: Value) -> StrResult { }) } +/// Repeat a string a number of times. +fn repeat_str(string: EcoString, n: i64) -> StrResult { + let n = usize::try_from(n) + .ok() + .and_then(|n| string.len().checked_mul(n).map(|_| n)) + .ok_or_else(|| format!("cannot repeat this string {} times", n))?; + + Ok(string.repeat(n)) +} + /// Compute the quotient of two values. pub fn div(lhs: Value, rhs: Value) -> StrResult { Ok(match (lhs, rhs) { diff --git a/src/eval/str.rs b/src/eval/str.rs deleted file mode 100644 index 800d17093..000000000 --- a/src/eval/str.rs +++ /dev/null @@ -1,164 +0,0 @@ -use std::borrow::Borrow; -use std::convert::TryFrom; -use std::fmt::{self, Debug, Formatter, Write}; -use std::ops::{Add, AddAssign, Deref}; - -use unicode_segmentation::UnicodeSegmentation; - -use crate::diag::StrResult; -use crate::util::EcoString; - -/// Create a new [`Str`] from a format string. -macro_rules! format_str { - ($($tts:tt)*) => {{ - use std::fmt::Write; - let mut s = $crate::eval::Str::new(); - write!(s, $($tts)*).unwrap(); - s - }}; -} - -/// A string value with inline storage and clone-on-write semantics. -#[derive(Default, Clone, Eq, PartialEq, Ord, PartialOrd)] -pub struct Str(EcoString); - -impl Str { - /// Create a new, empty string. - pub fn new() -> Self { - Self::default() - } - - /// Whether the string is empty. - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } - - /// The length of the string in bytes. - pub fn len(&self) -> i64 { - self.0.len() as i64 - } - - /// Borrow this as a string slice. - pub fn as_str(&self) -> &str { - self.0.as_str() - } - - /// Return an iterator over the grapheme clusters as strings. - pub fn iter(&self) -> impl Iterator + '_ { - self.graphemes(true).map(Into::into) - } - - /// Repeat this string `n` times. - pub fn repeat(&self, n: i64) -> StrResult { - let n = usize::try_from(n) - .ok() - .and_then(|n| self.0.len().checked_mul(n).map(|_| n)) - .ok_or_else(|| format!("cannot repeat this string {} times", n))?; - - Ok(self.0.repeat(n).into()) - } -} - -impl Deref for Str { - type Target = str; - - fn deref(&self) -> &str { - self.0.deref() - } -} - -impl Debug for Str { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - f.write_char('"')?; - for c in self.chars() { - match c { - '\\' => f.write_str(r"\\")?, - '"' => f.write_str(r#"\""#)?, - '\n' => f.write_str(r"\n")?, - '\r' => f.write_str(r"\r")?, - '\t' => f.write_str(r"\t")?, - _ => f.write_char(c)?, - } - } - f.write_char('"') - } -} - -impl Add for Str { - type Output = Self; - - fn add(mut self, rhs: Self) -> Self::Output { - self += rhs; - self - } -} - -impl AddAssign for Str { - fn add_assign(&mut self, rhs: Self) { - self.0.push_str(rhs.as_str()); - } -} - -impl Write for Str { - fn write_str(&mut self, s: &str) -> fmt::Result { - self.0.write_str(s) - } - - fn write_char(&mut self, c: char) -> fmt::Result { - self.0.write_char(c) - } -} - -impl AsRef for Str { - fn as_ref(&self) -> &str { - self - } -} - -impl Borrow for Str { - fn borrow(&self) -> &str { - self - } -} - -impl From for Str { - fn from(c: char) -> Self { - Self(c.into()) - } -} - -impl From<&str> for Str { - fn from(s: &str) -> Self { - Self(s.into()) - } -} - -impl From for Str { - fn from(s: String) -> Self { - Self(s.into()) - } -} - -impl From for Str { - fn from(s: EcoString) -> Self { - Self(s) - } -} - -impl From<&EcoString> for Str { - fn from(s: &EcoString) -> Self { - Self(s.clone()) - } -} - -impl From for EcoString { - fn from(s: Str) -> Self { - s.0 - } -} - -impl From<&Str> for EcoString { - fn from(s: &Str) -> Self { - s.0.clone() - } -} diff --git a/src/eval/template.rs b/src/eval/template.rs index 2622a1f06..181046389 100644 --- a/src/eval/template.rs +++ b/src/eval/template.rs @@ -5,7 +5,6 @@ use std::mem; use std::ops::{Add, AddAssign}; use std::rc::Rc; -use super::Str; use crate::diag::StrResult; use crate::geom::{Align, Dir, GenAxis, Length, Linear, Sides, Size}; use crate::layout::{BlockLevel, BlockNode, InlineLevel, InlineNode, PageNode}; @@ -214,20 +213,20 @@ impl AddAssign for Template { } } -impl Add for Template { +impl Add for Template { type Output = Self; - fn add(mut self, rhs: Str) -> Self::Output { - Rc::make_mut(&mut self.0).push(TemplateNode::Text(rhs.into())); + fn add(mut self, rhs: EcoString) -> Self::Output { + Rc::make_mut(&mut self.0).push(TemplateNode::Text(rhs)); self } } -impl Add