mirror of
https://github.com/typst/typst
synced 2025-05-13 20:46:23 +08:00
Convert single-field structs to tuple structs
This commit is contained in:
parent
cb0aab3cfa
commit
9462fb17b3
@ -11,19 +11,17 @@ use crate::diag::StrResult;
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! array {
|
||||
($value:expr; $count:expr) => {
|
||||
$crate::eval::Array::from_vec(vec![$crate::eval::Value::from($value); $count])
|
||||
$crate::eval::Array::from_vec(vec![$value.into(); $count])
|
||||
};
|
||||
|
||||
($($value:expr),* $(,)?) => {
|
||||
$crate::eval::Array::from_vec(vec![$($crate::eval::Value::from($value)),*])
|
||||
$crate::eval::Array::from_vec(vec![$($value.into()),*])
|
||||
};
|
||||
}
|
||||
|
||||
/// An array of values with clone-on-write value semantics.
|
||||
#[derive(Default, Clone, PartialEq)]
|
||||
pub struct Array {
|
||||
vec: Rc<Vec<Value>>,
|
||||
}
|
||||
pub struct Array(Rc<Vec<Value>>);
|
||||
|
||||
impl Array {
|
||||
/// Create a new, empty array.
|
||||
@ -33,24 +31,24 @@ impl Array {
|
||||
|
||||
/// Create a new array from a vector of values.
|
||||
pub fn from_vec(vec: Vec<Value>) -> Self {
|
||||
Self { vec: Rc::new(vec) }
|
||||
Self(Rc::new(vec))
|
||||
}
|
||||
|
||||
/// Whether the array is empty.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.vec.is_empty()
|
||||
self.0.is_empty()
|
||||
}
|
||||
|
||||
/// The length of the array.
|
||||
pub fn len(&self) -> i64 {
|
||||
self.vec.len() as i64
|
||||
self.0.len() as i64
|
||||
}
|
||||
|
||||
/// Borrow the value at the given index.
|
||||
pub fn get(&self, index: i64) -> StrResult<&Value> {
|
||||
usize::try_from(index)
|
||||
.ok()
|
||||
.and_then(|i| self.vec.get(i))
|
||||
.and_then(|i| self.0.get(i))
|
||||
.ok_or_else(|| out_of_bounds(index, self.len()))
|
||||
}
|
||||
|
||||
@ -59,19 +57,19 @@ impl Array {
|
||||
let len = self.len();
|
||||
usize::try_from(index)
|
||||
.ok()
|
||||
.and_then(move |i| Rc::make_mut(&mut self.vec).get_mut(i))
|
||||
.and_then(move |i| Rc::make_mut(&mut self.0).get_mut(i))
|
||||
.ok_or_else(|| out_of_bounds(index, len))
|
||||
}
|
||||
|
||||
/// Push a value to the end of the array.
|
||||
pub fn push(&mut self, value: Value) {
|
||||
Rc::make_mut(&mut self.vec).push(value);
|
||||
Rc::make_mut(&mut self.0).push(value);
|
||||
}
|
||||
|
||||
/// Clear the array.
|
||||
pub fn clear(&mut self) {
|
||||
if Rc::strong_count(&mut self.vec) == 1 {
|
||||
Rc::make_mut(&mut self.vec).clear();
|
||||
if Rc::strong_count(&mut self.0) == 1 {
|
||||
Rc::make_mut(&mut self.0).clear();
|
||||
} else {
|
||||
*self = Self::new();
|
||||
}
|
||||
@ -79,14 +77,14 @@ impl Array {
|
||||
|
||||
/// Iterate over references to the contained values.
|
||||
pub fn iter(&self) -> std::slice::Iter<Value> {
|
||||
self.vec.iter()
|
||||
self.0.iter()
|
||||
}
|
||||
|
||||
/// Repeat this array `n` times.
|
||||
pub fn repeat(&self, n: i64) -> StrResult<Self> {
|
||||
let count = usize::try_from(n)
|
||||
.ok()
|
||||
.and_then(|n| self.vec.len().checked_mul(n))
|
||||
.and_then(|n| self.0.len().checked_mul(n))
|
||||
.ok_or_else(|| format!("cannot repeat this array {} times", n))?;
|
||||
|
||||
Ok(self.iter().cloned().cycle().take(count).collect())
|
||||
@ -101,7 +99,7 @@ fn out_of_bounds(index: i64, len: i64) -> String {
|
||||
|
||||
impl Debug for Array {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.debug_list().entries(self.vec.iter()).finish()
|
||||
f.debug_list().entries(self.0.iter()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,7 +108,7 @@ impl Display for Array {
|
||||
f.write_char('(')?;
|
||||
for (i, value) in self.iter().enumerate() {
|
||||
Display::fmt(value, f)?;
|
||||
if i + 1 < self.vec.len() {
|
||||
if i + 1 < self.0.len() {
|
||||
f.write_str(", ")?;
|
||||
}
|
||||
}
|
||||
@ -132,7 +130,7 @@ impl Add for Array {
|
||||
|
||||
impl AddAssign for Array {
|
||||
fn add_assign(&mut self, rhs: Array) {
|
||||
match Rc::try_unwrap(rhs.vec) {
|
||||
match Rc::try_unwrap(rhs.0) {
|
||||
Ok(vec) => self.extend(vec),
|
||||
Err(rc) => self.extend(rc.iter().cloned()),
|
||||
}
|
||||
@ -141,13 +139,13 @@ impl AddAssign for Array {
|
||||
|
||||
impl FromIterator<Value> for Array {
|
||||
fn from_iter<T: IntoIterator<Item = Value>>(iter: T) -> Self {
|
||||
Array { vec: Rc::new(iter.into_iter().collect()) }
|
||||
Self(Rc::new(iter.into_iter().collect()))
|
||||
}
|
||||
}
|
||||
|
||||
impl Extend<Value> for Array {
|
||||
fn extend<T: IntoIterator<Item = Value>>(&mut self, iter: T) {
|
||||
Rc::make_mut(&mut self.vec).extend(iter);
|
||||
Rc::make_mut(&mut self.0).extend(iter);
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,7 +154,7 @@ impl IntoIterator for Array {
|
||||
type IntoIter = std::vec::IntoIter<Value>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
match Rc::try_unwrap(self.vec) {
|
||||
match Rc::try_unwrap(self.0) {
|
||||
Ok(vec) => vec.into_iter(),
|
||||
Err(rc) => (*rc).clone().into_iter(),
|
||||
}
|
||||
|
@ -13,16 +13,14 @@ macro_rules! dict {
|
||||
($($key:expr => $value:expr),* $(,)?) => {{
|
||||
#[allow(unused_mut)]
|
||||
let mut map = std::collections::BTreeMap::new();
|
||||
$(map.insert($crate::eval::Str::from($key), $crate::eval::Value::from($value));)*
|
||||
$(map.insert($key.into(), $value.into());)*
|
||||
$crate::eval::Dict::from_map(map)
|
||||
}};
|
||||
}
|
||||
|
||||
/// A dictionary from strings to values with clone-on-write value semantics.
|
||||
#[derive(Default, Clone, PartialEq)]
|
||||
pub struct Dict {
|
||||
map: Rc<BTreeMap<Str, Value>>,
|
||||
}
|
||||
pub struct Dict(Rc<BTreeMap<Str, Value>>);
|
||||
|
||||
impl Dict {
|
||||
/// Create a new, empty dictionary.
|
||||
@ -32,22 +30,22 @@ impl Dict {
|
||||
|
||||
/// Create a new dictionary from a mapping of strings to values.
|
||||
pub fn from_map(map: BTreeMap<Str, Value>) -> Self {
|
||||
Self { map: Rc::new(map) }
|
||||
Self(Rc::new(map))
|
||||
}
|
||||
|
||||
/// Whether the dictionary is empty.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.map.is_empty()
|
||||
self.0.is_empty()
|
||||
}
|
||||
|
||||
/// The number of pairs in the dictionary.
|
||||
pub fn len(&self) -> i64 {
|
||||
self.map.len() as i64
|
||||
self.0.len() as i64
|
||||
}
|
||||
|
||||
/// Borrow the value the given `key` maps to.
|
||||
pub fn get(&self, key: Str) -> StrResult<&Value> {
|
||||
self.map.get(&key).ok_or_else(|| missing_key(&key))
|
||||
self.0.get(&key).ok_or_else(|| missing_key(&key))
|
||||
}
|
||||
|
||||
/// Mutably borrow the value the given `key` maps to.
|
||||
@ -55,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.map).entry(key.into()).or_default()
|
||||
Rc::make_mut(&mut self.0).entry(key.into()).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.map).insert(key.into(), value);
|
||||
Rc::make_mut(&mut self.0).insert(key.into(), value);
|
||||
}
|
||||
|
||||
/// Clear the dictionary.
|
||||
pub fn clear(&mut self) {
|
||||
if Rc::strong_count(&mut self.map) == 1 {
|
||||
Rc::make_mut(&mut self.map).clear();
|
||||
if Rc::strong_count(&mut self.0) == 1 {
|
||||
Rc::make_mut(&mut self.0).clear();
|
||||
} else {
|
||||
*self = Self::new();
|
||||
}
|
||||
@ -74,7 +72,7 @@ impl Dict {
|
||||
|
||||
/// Iterate over pairs of references to the contained keys and values.
|
||||
pub fn iter(&self) -> std::collections::btree_map::Iter<Str, Value> {
|
||||
self.map.iter()
|
||||
self.0.iter()
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,7 +92,7 @@ impl Display for Dict {
|
||||
f.write_str(key)?;
|
||||
f.write_str(": ")?;
|
||||
Display::fmt(value, f)?;
|
||||
if i + 1 < self.map.len() {
|
||||
if i + 1 < self.0.len() {
|
||||
f.write_str(", ")?;
|
||||
}
|
||||
}
|
||||
@ -104,7 +102,7 @@ impl Display for Dict {
|
||||
|
||||
impl Debug for Dict {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.debug_map().entries(self.map.iter()).finish()
|
||||
f.debug_map().entries(self.0.iter()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,7 +117,7 @@ impl Add for Dict {
|
||||
|
||||
impl AddAssign for Dict {
|
||||
fn add_assign(&mut self, rhs: Dict) {
|
||||
match Rc::try_unwrap(rhs.map) {
|
||||
match Rc::try_unwrap(rhs.0) {
|
||||
Ok(map) => self.extend(map),
|
||||
Err(rc) => self.extend(rc.iter().map(|(k, v)| (k.clone(), v.clone()))),
|
||||
}
|
||||
@ -128,13 +126,13 @@ impl AddAssign for Dict {
|
||||
|
||||
impl FromIterator<(Str, Value)> for Dict {
|
||||
fn from_iter<T: IntoIterator<Item = (Str, Value)>>(iter: T) -> Self {
|
||||
Dict { map: Rc::new(iter.into_iter().collect()) }
|
||||
Self(Rc::new(iter.into_iter().collect()))
|
||||
}
|
||||
}
|
||||
|
||||
impl Extend<(Str, Value)> for Dict {
|
||||
fn extend<T: IntoIterator<Item = (Str, Value)>>(&mut self, iter: T) {
|
||||
Rc::make_mut(&mut self.map).extend(iter);
|
||||
Rc::make_mut(&mut self.0).extend(iter);
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,7 +141,7 @@ impl IntoIterator for Dict {
|
||||
type IntoIter = std::collections::btree_map::IntoIter<Str, Value>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
match Rc::try_unwrap(self.map) {
|
||||
match Rc::try_unwrap(self.0) {
|
||||
Ok(map) => map.into_iter(),
|
||||
Err(rc) => (*rc).clone().into_iter(),
|
||||
}
|
||||
|
@ -8,12 +8,10 @@ use crate::util::EcoString;
|
||||
|
||||
/// An evaluatable function.
|
||||
#[derive(Clone)]
|
||||
pub struct Function {
|
||||
repr: Rc<Repr<Func>>,
|
||||
}
|
||||
pub struct Function(Rc<Inner<Func>>);
|
||||
|
||||
/// The unsized representation behind the [`Rc`].
|
||||
struct Repr<T: ?Sized> {
|
||||
/// The unsized structure behind the [`Rc`].
|
||||
struct Inner<T: ?Sized> {
|
||||
name: Option<EcoString>,
|
||||
func: T,
|
||||
}
|
||||
@ -26,17 +24,17 @@ impl Function {
|
||||
where
|
||||
F: Fn(&mut EvalContext, &mut Arguments) -> TypResult<Value> + 'static,
|
||||
{
|
||||
Self { repr: Rc::new(Repr { name, func }) }
|
||||
Self(Rc::new(Inner { name, func }))
|
||||
}
|
||||
|
||||
/// The name of the function.
|
||||
pub fn name(&self) -> Option<&EcoString> {
|
||||
self.repr.name.as_ref()
|
||||
self.0.name.as_ref()
|
||||
}
|
||||
|
||||
/// Call the function in the context with the arguments.
|
||||
pub fn call(&self, ctx: &mut EvalContext, args: &mut Arguments) -> TypResult<Value> {
|
||||
(&self.repr.func)(ctx, args)
|
||||
(&self.0.func)(ctx, args)
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,14 +51,14 @@ impl Display for Function {
|
||||
|
||||
impl Debug for Function {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.debug_struct("Function").field("name", &self.repr.name).finish()
|
||||
f.debug_struct("Function").field("name", &self.0.name).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Function {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
// We cast to thin pointers for comparison.
|
||||
Rc::as_ptr(&self.repr) as *const () == Rc::as_ptr(&other.repr) as *const ()
|
||||
Rc::as_ptr(&self.0) as *const () == Rc::as_ptr(&other.0) as *const ()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -376,7 +376,7 @@ impl Eval for CallExpr {
|
||||
}
|
||||
|
||||
Value::Func(func) => {
|
||||
let point = || Tracepoint::Call(func.name().map(Into::into));
|
||||
let point = || Tracepoint::Call(func.name().map(ToString::to_string));
|
||||
let value = func.call(ctx, &mut args).trace(point, self.span)?;
|
||||
args.finish()?;
|
||||
Ok(value)
|
||||
|
@ -7,9 +7,7 @@ use crate::util::EcoString;
|
||||
|
||||
/// A string value with inline storage and clone-on-write semantics.
|
||||
#[derive(Default, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct Str {
|
||||
string: EcoString,
|
||||
}
|
||||
pub struct Str(EcoString);
|
||||
|
||||
impl Str {
|
||||
/// Create a new, empty string.
|
||||
@ -19,17 +17,17 @@ impl Str {
|
||||
|
||||
/// Whether the string is empty.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.string.is_empty()
|
||||
self.0.is_empty()
|
||||
}
|
||||
|
||||
/// The length of the string in bytes.
|
||||
pub fn len(&self) -> i64 {
|
||||
self.string.len() as i64
|
||||
self.0.len() as i64
|
||||
}
|
||||
|
||||
/// Borrow this as a string slice.
|
||||
pub fn as_str(&self) -> &str {
|
||||
self.string.as_str()
|
||||
self.0.as_str()
|
||||
}
|
||||
|
||||
/// Return an iterator over the chars as strings.
|
||||
@ -41,10 +39,10 @@ impl Str {
|
||||
pub fn repeat(&self, n: i64) -> StrResult<Self> {
|
||||
let n = usize::try_from(n)
|
||||
.ok()
|
||||
.and_then(|n| self.string.len().checked_mul(n).map(|_| n))
|
||||
.and_then(|n| self.0.len().checked_mul(n).map(|_| n))
|
||||
.ok_or_else(|| format!("cannot repeat this string {} times", n))?;
|
||||
|
||||
Ok(self.string.repeat(n).into())
|
||||
Ok(self.0.repeat(n).into())
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,7 +65,7 @@ impl Display for Str {
|
||||
|
||||
impl Debug for Str {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
Debug::fmt(&self.string, f)
|
||||
Debug::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,7 +73,7 @@ impl Deref for Str {
|
||||
type Target = str;
|
||||
|
||||
fn deref(&self) -> &str {
|
||||
self.string.deref()
|
||||
self.0.deref()
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,48 +88,48 @@ impl Add for Str {
|
||||
|
||||
impl AddAssign for Str {
|
||||
fn add_assign(&mut self, rhs: Self) {
|
||||
self.string.push_str(rhs.as_str());
|
||||
self.0.push_str(rhs.as_str());
|
||||
}
|
||||
}
|
||||
|
||||
impl From<char> for Str {
|
||||
fn from(c: char) -> Self {
|
||||
Self { string: c.into() }
|
||||
Self(c.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Str {
|
||||
fn from(string: &str) -> Self {
|
||||
Self { string: string.into() }
|
||||
fn from(s: &str) -> Self {
|
||||
Self(s.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for Str {
|
||||
fn from(string: String) -> Self {
|
||||
Self { string: string.into() }
|
||||
fn from(s: String) -> Self {
|
||||
Self(s.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<EcoString> for Str {
|
||||
fn from(string: EcoString) -> Self {
|
||||
Self { string }
|
||||
fn from(s: EcoString) -> Self {
|
||||
Self(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&EcoString> for Str {
|
||||
fn from(string: &EcoString) -> Self {
|
||||
Self { string: string.clone() }
|
||||
fn from(s: &EcoString) -> Self {
|
||||
Self(s.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Str> for EcoString {
|
||||
fn from(string: Str) -> Self {
|
||||
string.string
|
||||
fn from(s: Str) -> Self {
|
||||
s.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Str> for EcoString {
|
||||
fn from(string: &Str) -> Self {
|
||||
string.string.clone()
|
||||
fn from(s: &Str) -> Self {
|
||||
s.0.clone()
|
||||
}
|
||||
}
|
||||
|
@ -12,31 +12,29 @@ use crate::util::EcoString;
|
||||
|
||||
/// A template value: `[*Hi* there]`.
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct Template {
|
||||
nodes: Rc<Vec<TemplateNode>>,
|
||||
}
|
||||
pub struct Template(Rc<Vec<TemplateNode>>);
|
||||
|
||||
impl Template {
|
||||
/// Create a new template from a vector of nodes.
|
||||
pub fn new(nodes: Vec<TemplateNode>) -> Self {
|
||||
Self { nodes: Rc::new(nodes) }
|
||||
Self(Rc::new(nodes))
|
||||
}
|
||||
|
||||
/// Iterate over the contained template nodes.
|
||||
pub fn iter(&self) -> std::slice::Iter<TemplateNode> {
|
||||
self.nodes.iter()
|
||||
self.0.iter()
|
||||
}
|
||||
|
||||
/// Repeat this template `n` times.
|
||||
pub fn repeat(&self, n: i64) -> StrResult<Self> {
|
||||
let count = usize::try_from(n)
|
||||
.ok()
|
||||
.and_then(|n| self.nodes.len().checked_mul(n))
|
||||
.and_then(|n| self.0.len().checked_mul(n))
|
||||
.ok_or_else(|| format!("cannot repeat this template {} times", n))?;
|
||||
|
||||
Ok(Self {
|
||||
nodes: Rc::new(self.iter().cloned().cycle().take(count).collect()),
|
||||
})
|
||||
Ok(Self(Rc::new(
|
||||
self.iter().cloned().cycle().take(count).collect(),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,7 +46,7 @@ impl Display for Template {
|
||||
|
||||
impl PartialEq for Template {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
Rc::ptr_eq(&self.nodes, &other.nodes)
|
||||
Rc::ptr_eq(&self.0, &other.0)
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,8 +61,8 @@ impl Add for Template {
|
||||
|
||||
impl AddAssign for Template {
|
||||
fn add_assign(&mut self, rhs: Template) {
|
||||
let sink = Rc::make_mut(&mut self.nodes);
|
||||
match Rc::try_unwrap(rhs.nodes) {
|
||||
let sink = Rc::make_mut(&mut self.0);
|
||||
match Rc::try_unwrap(rhs.0) {
|
||||
Ok(source) => sink.extend(source),
|
||||
Err(rc) => sink.extend(rc.iter().cloned()),
|
||||
}
|
||||
@ -75,7 +73,7 @@ impl Add<Str> for Template {
|
||||
type Output = Self;
|
||||
|
||||
fn add(mut self, rhs: Str) -> Self::Output {
|
||||
Rc::make_mut(&mut self.nodes).push(TemplateNode::Str(rhs.into()));
|
||||
Rc::make_mut(&mut self.0).push(TemplateNode::Str(rhs.into()));
|
||||
self
|
||||
}
|
||||
}
|
||||
@ -84,7 +82,7 @@ impl Add<Template> for Str {
|
||||
type Output = Template;
|
||||
|
||||
fn add(self, mut rhs: Template) -> Self::Output {
|
||||
Rc::make_mut(&mut rhs.nodes).insert(0, TemplateNode::Str(self.into()));
|
||||
Rc::make_mut(&mut rhs.0).insert(0, TemplateNode::Str(self.into()));
|
||||
rhs
|
||||
}
|
||||
}
|
||||
@ -154,6 +152,12 @@ impl TemplateFunc {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for TemplateFunc {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.debug_struct("TemplateFunc").finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for TemplateFunc {
|
||||
type Target = dyn Fn(&mut ExecContext);
|
||||
|
||||
@ -161,9 +165,3 @@ impl Deref for TemplateFunc {
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for TemplateFunc {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.debug_struct("TemplateFunc").finish()
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ impl ExecContext {
|
||||
|
||||
/// Push a word space into the active paragraph.
|
||||
pub fn push_word_space(&mut self) {
|
||||
self.stack.par.push_soft(self.make_text_node(" "));
|
||||
self.stack.par.push_soft(self.make_text_node(' '));
|
||||
}
|
||||
|
||||
/// Push any node into the active paragraph.
|
||||
@ -107,7 +107,7 @@ impl ExecContext {
|
||||
|
||||
/// Apply a forced line break.
|
||||
pub fn linebreak(&mut self) {
|
||||
self.stack.par.push_hard(self.make_text_node("\n"));
|
||||
self.stack.par.push_hard(self.make_text_node('\n'));
|
||||
}
|
||||
|
||||
/// Apply a forced paragraph break.
|
||||
|
@ -106,8 +106,7 @@ impl ExecWithMap for ListItem {
|
||||
impl ExecWithMap for EnumItem {
|
||||
fn exec_with_map(&self, ctx: &mut ExecContext, map: &ExprMap) {
|
||||
let mut label = EcoString::new();
|
||||
write!(&mut label, "{}", self.number.unwrap_or(1)).unwrap();
|
||||
label.push('.');
|
||||
write!(&mut label, "{}.", self.number.unwrap_or(1)).unwrap();
|
||||
exec_item(ctx, label, &self.body, map);
|
||||
}
|
||||
}
|
||||
@ -115,7 +114,7 @@ impl ExecWithMap for EnumItem {
|
||||
fn exec_item(ctx: &mut ExecContext, label: EcoString, body: &SyntaxTree, map: &ExprMap) {
|
||||
let label = ctx.exec_stack(|ctx| ctx.push_text(label));
|
||||
let body = ctx.exec_tree_stack(body, map);
|
||||
let stack = StackNode {
|
||||
ctx.push_into_stack(StackNode {
|
||||
dirs: Gen::new(ctx.state.dirs.main, ctx.state.dirs.cross),
|
||||
aspect: None,
|
||||
children: vec![
|
||||
@ -123,9 +122,7 @@ fn exec_item(ctx: &mut ExecContext, label: EcoString, body: &SyntaxTree, map: &E
|
||||
StackChild::Spacing(ctx.state.font.size / 2.0),
|
||||
StackChild::Any(body.into(), Gen::default()),
|
||||
],
|
||||
};
|
||||
|
||||
ctx.push_into_stack(stack);
|
||||
});
|
||||
}
|
||||
|
||||
impl Exec for Value {
|
||||
|
@ -91,7 +91,7 @@ impl Default for PageState {
|
||||
fn default() -> Self {
|
||||
let paper = PAPER_A4;
|
||||
Self {
|
||||
class: paper.class,
|
||||
class: paper.class(),
|
||||
size: paper.size(),
|
||||
margins: Sides::splat(None),
|
||||
}
|
||||
@ -171,19 +171,16 @@ impl FontState {
|
||||
|
||||
/// The resolved family iterator.
|
||||
pub fn families(&self) -> impl Iterator<Item = &str> + Clone {
|
||||
let head = if self.monospace {
|
||||
self.families.monospace.as_slice()
|
||||
} else {
|
||||
&[]
|
||||
};
|
||||
let head = self
|
||||
.monospace
|
||||
.then(|| self.families.monospace.as_slice())
|
||||
.unwrap_or_default();
|
||||
|
||||
let core = self.families.list.iter().flat_map(move |family: &FontFamily| {
|
||||
match family {
|
||||
FontFamily::Named(name) => std::slice::from_ref(name),
|
||||
FontFamily::Serif => &self.families.serif,
|
||||
FontFamily::SansSerif => &self.families.sans_serif,
|
||||
FontFamily::Monospace => &self.families.monospace,
|
||||
}
|
||||
let core = self.families.list.iter().flat_map(move |family| match family {
|
||||
FontFamily::Named(name) => std::slice::from_ref(name),
|
||||
FontFamily::Serif => &self.families.serif,
|
||||
FontFamily::SansSerif => &self.families.sans_serif,
|
||||
FontFamily::Monospace => &self.families.monospace,
|
||||
});
|
||||
|
||||
head.iter()
|
||||
|
@ -3,15 +3,12 @@ use decorum::N64;
|
||||
|
||||
/// An angle.
|
||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct Angle {
|
||||
/// The angle in raw units.
|
||||
raw: N64,
|
||||
}
|
||||
pub struct Angle(N64);
|
||||
|
||||
impl Angle {
|
||||
/// The zero angle.
|
||||
pub fn zero() -> Self {
|
||||
Self { raw: N64::from(0.0) }
|
||||
Self(N64::from(0.0))
|
||||
}
|
||||
|
||||
/// Create an angle from a number of radians.
|
||||
@ -26,7 +23,7 @@ impl Angle {
|
||||
|
||||
/// Create an angle from a number of raw units.
|
||||
pub fn raw(raw: f64) -> Self {
|
||||
Self { raw: N64::from(raw) }
|
||||
Self(N64::from(raw))
|
||||
}
|
||||
|
||||
/// Convert this to a number of radians.
|
||||
@ -41,12 +38,12 @@ impl Angle {
|
||||
|
||||
/// Get the value of this angle in raw units.
|
||||
pub fn to_raw(self) -> f64 {
|
||||
self.raw.into()
|
||||
self.0.into()
|
||||
}
|
||||
|
||||
/// Create an angle from a value in a unit.
|
||||
pub fn with_unit(val: f64, unit: AngularUnit) -> Self {
|
||||
Self { raw: N64::from(val * unit.raw_scale()) }
|
||||
Self(N64::from(val * unit.raw_scale()))
|
||||
}
|
||||
|
||||
/// Get the value of this length in unit.
|
||||
@ -80,7 +77,7 @@ impl Neg for Angle {
|
||||
type Output = Self;
|
||||
|
||||
fn neg(self) -> Self {
|
||||
Self { raw: -self.raw }
|
||||
Self(-self.0)
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,7 +85,7 @@ impl Add for Angle {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, other: Self) -> Self {
|
||||
Self { raw: self.raw + other.raw }
|
||||
Self(self.0 + other.0)
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,7 +95,7 @@ impl Mul<f64> for Angle {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, other: f64) -> Self {
|
||||
Self { raw: self.raw * other }
|
||||
Self(self.0 * other)
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,7 +111,7 @@ impl Div<f64> for Angle {
|
||||
type Output = Self;
|
||||
|
||||
fn div(self, other: f64) -> Self {
|
||||
Self { raw: self.raw / other }
|
||||
Self(self.0 / other)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,20 +7,17 @@ use super::*;
|
||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct Length {
|
||||
/// The length in raw units.
|
||||
raw: N64,
|
||||
}
|
||||
pub struct Length(N64);
|
||||
|
||||
impl Length {
|
||||
/// The zero length.
|
||||
pub fn zero() -> Self {
|
||||
Self { raw: N64::from(0.0) }
|
||||
Self(N64::from(0.0))
|
||||
}
|
||||
|
||||
/// The inifinite length.
|
||||
pub fn inf() -> Self {
|
||||
Self { raw: N64::from(f64::INFINITY) }
|
||||
Self(N64::from(f64::INFINITY))
|
||||
}
|
||||
|
||||
/// Create a length from a number of points.
|
||||
@ -45,7 +42,7 @@ impl Length {
|
||||
|
||||
/// Create a length from a number of raw units.
|
||||
pub fn raw(raw: f64) -> Self {
|
||||
Self { raw: N64::from(raw) }
|
||||
Self(N64::from(raw))
|
||||
}
|
||||
|
||||
/// Convert this to a number of points.
|
||||
@ -70,12 +67,12 @@ impl Length {
|
||||
|
||||
/// Get the value of this length in raw units.
|
||||
pub fn to_raw(self) -> f64 {
|
||||
self.raw.into()
|
||||
self.0.into()
|
||||
}
|
||||
|
||||
/// Create a length from a value in a unit.
|
||||
pub fn with_unit(val: f64, unit: LengthUnit) -> Self {
|
||||
Self { raw: N64::from(val * unit.raw_scale()) }
|
||||
Self(N64::from(val * unit.raw_scale()))
|
||||
}
|
||||
|
||||
/// Get the value of this length in unit.
|
||||
@ -83,9 +80,24 @@ impl Length {
|
||||
self.to_raw() / unit.raw_scale()
|
||||
}
|
||||
|
||||
/// Whether the length is zero.
|
||||
pub fn is_zero(self) -> bool {
|
||||
self.0 == 0.0
|
||||
}
|
||||
|
||||
/// Whether the length is finite.
|
||||
pub fn is_finite(self) -> bool {
|
||||
self.0.into_inner().is_finite()
|
||||
}
|
||||
|
||||
/// Whether the length is infinite.
|
||||
pub fn is_infinite(self) -> bool {
|
||||
self.0.into_inner().is_infinite()
|
||||
}
|
||||
|
||||
/// The minimum of this and another length.
|
||||
pub fn min(self, other: Self) -> Self {
|
||||
Self { raw: self.raw.min(other.raw) }
|
||||
Self(self.0.min(other.0))
|
||||
}
|
||||
|
||||
/// Set to the minimum of this and another length.
|
||||
@ -95,7 +107,7 @@ impl Length {
|
||||
|
||||
/// The maximum of this and another length.
|
||||
pub fn max(self, other: Self) -> Self {
|
||||
Self { raw: self.raw.max(other.raw) }
|
||||
Self(self.0.max(other.0))
|
||||
}
|
||||
|
||||
/// Set to the maximum of this and another length.
|
||||
@ -105,28 +117,13 @@ impl Length {
|
||||
|
||||
/// Whether the other length fits into this one (i.e. is smaller).
|
||||
pub fn fits(self, other: Self) -> bool {
|
||||
self.raw + 1e-6 >= other.raw
|
||||
self.0 + 1e-6 >= other.0
|
||||
}
|
||||
|
||||
/// Compares two lengths for whether they are approximately equal.
|
||||
pub fn approx_eq(self, other: Self) -> bool {
|
||||
self == other || (self - other).to_raw().abs() < 1e-6
|
||||
}
|
||||
|
||||
/// Whether the length is zero.
|
||||
pub fn is_zero(self) -> bool {
|
||||
self.raw == 0.0
|
||||
}
|
||||
|
||||
/// Whether the length is finite.
|
||||
pub fn is_finite(self) -> bool {
|
||||
self.raw.into_inner().is_finite()
|
||||
}
|
||||
|
||||
/// Whether the length is infinite.
|
||||
pub fn is_infinite(self) -> bool {
|
||||
self.raw.into_inner().is_infinite()
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Length {
|
||||
@ -156,7 +153,7 @@ impl Neg for Length {
|
||||
type Output = Self;
|
||||
|
||||
fn neg(self) -> Self {
|
||||
Self { raw: -self.raw }
|
||||
Self(-self.0)
|
||||
}
|
||||
}
|
||||
|
||||
@ -164,7 +161,7 @@ impl Add for Length {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, other: Self) -> Self {
|
||||
Self { raw: self.raw + other.raw }
|
||||
Self(self.0 + other.0)
|
||||
}
|
||||
}
|
||||
|
||||
@ -174,7 +171,7 @@ impl Mul<f64> for Length {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, other: f64) -> Self {
|
||||
Self { raw: self.raw * other }
|
||||
Self(self.0 * other)
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,7 +187,7 @@ impl Div<f64> for Length {
|
||||
type Output = Self;
|
||||
|
||||
fn div(self, other: f64) -> Self {
|
||||
Self { raw: self.raw / other }
|
||||
Self(self.0 / other)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ pub fn page(_: &mut EvalContext, args: &mut Arguments) -> TypResult<Value> {
|
||||
let state = ctx.state.page_mut();
|
||||
|
||||
if let Some(paper) = paper {
|
||||
state.class = paper.class;
|
||||
state.class = paper.class();
|
||||
state.size = paper.size();
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ use crate::geom::{Length, Linear, Relative, Sides, Size};
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub struct Paper {
|
||||
/// The broad class this paper belongs to.
|
||||
pub class: PaperClass,
|
||||
class: PaperClass,
|
||||
/// The width of the paper in millimeters.
|
||||
width: f64,
|
||||
/// The height of the paper in millimeters.
|
||||
@ -19,6 +19,11 @@ impl Paper {
|
||||
parse_paper(name)
|
||||
}
|
||||
|
||||
/// The class of the paper.
|
||||
pub fn class(self) -> PaperClass {
|
||||
self.class
|
||||
}
|
||||
|
||||
/// The size of the paper.
|
||||
pub fn size(self) -> Size {
|
||||
Size::new(Length::mm(self.width), Length::mm(self.height))
|
||||
|
@ -39,12 +39,6 @@ impl Ident {
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for Ident {
|
||||
fn as_ref(&self) -> &str {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Ident {
|
||||
type Target = str;
|
||||
|
||||
@ -53,6 +47,12 @@ impl Deref for Ident {
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for Ident {
|
||||
fn as_ref(&self) -> &str {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether a string is a valid identifier.
|
||||
pub fn is_ident(string: &str) -> bool {
|
||||
let mut chars = string.chars();
|
||||
|
@ -163,6 +163,24 @@ impl EcoString {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for EcoString {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for EcoString {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
Display::fmt(self.as_str(), f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for EcoString {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
Debug::fmt(self.as_str(), f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for EcoString {
|
||||
type Target = str;
|
||||
|
||||
@ -183,24 +201,6 @@ impl Deref for EcoString {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for EcoString {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for EcoString {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
Display::fmt(self.as_str(), f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for EcoString {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
Debug::fmt(self.as_str(), f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for EcoString {}
|
||||
|
||||
impl PartialEq for EcoString {
|
||||
@ -301,12 +301,6 @@ impl From<EcoString> for String {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&EcoString> for String {
|
||||
fn from(s: &EcoString) -> Self {
|
||||
s.as_str().to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
Loading…
x
Reference in New Issue
Block a user