summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-01-31 16:06:44 +0100
committerLaurenz <laurmaedje@gmail.com>2022-01-31 16:47:00 +0100
commit20b1a38414101f842a6d9201133a5aaaa45a7cec (patch)
tree2365453d4dfdebfa11d618baad1a36c65b62d7c7 /src
parentfa57d86ed981373b66804972147bf59cab920e6b (diff)
Switch from `Rc` to `Arc`
Diffstat (limited to 'src')
-rw-r--r--src/eval/array.rs26
-rw-r--r--src/eval/capture.rs4
-rw-r--r--src/eval/dict.rs24
-rw-r--r--src/eval/function.rs12
-rw-r--r--src/eval/node.rs4
-rw-r--r--src/eval/scope.rs8
-rw-r--r--src/eval/styles.rs12
-rw-r--r--src/eval/value.rs16
-rw-r--r--src/export/pdf.rs8
-rw-r--r--src/font.rs20
-rw-r--r--src/frame.rs10
-rw-r--r--src/image.rs6
-rw-r--r--src/layout/constraints.rs8
-rw-r--r--src/layout/incremental.rs14
-rw-r--r--src/layout/mod.rs41
-rw-r--r--src/lib.rs16
-rw-r--r--src/library/align.rs4
-rw-r--r--src/library/columns.rs2
-rw-r--r--src/library/flow.rs10
-rw-r--r--src/library/grid.rs6
-rw-r--r--src/library/heading.rs4
-rw-r--r--src/library/hidden.rs4
-rw-r--r--src/library/image.rs2
-rw-r--r--src/library/link.rs5
-rw-r--r--src/library/list.rs4
-rw-r--r--src/library/mod.rs2
-rw-r--r--src/library/pad.rs4
-rw-r--r--src/library/page.rs2
-rw-r--r--src/library/par.rs14
-rw-r--r--src/library/place.rs4
-rw-r--r--src/library/shape.rs6
-rw-r--r--src/library/stack.rs8
-rw-r--r--src/library/table.rs2
-rw-r--r--src/library/text.rs6
-rw-r--r--src/library/transform.rs6
-rw-r--r--src/loading/fs.rs8
-rw-r--r--src/loading/mem.rs8
-rw-r--r--src/parse/incremental.rs8
-rw-r--r--src/parse/mod.rs4
-rw-r--r--src/parse/tokens.rs12
-rw-r--r--src/source.rs10
-rw-r--r--src/syntax/mod.rs18
-rw-r--r--src/util/eco_string.rs32
-rw-r--r--src/util/mod.rs8
44 files changed, 218 insertions, 214 deletions
diff --git a/src/eval/array.rs b/src/eval/array.rs
index 912aa3c0..45f6fcc7 100644
--- a/src/eval/array.rs
+++ b/src/eval/array.rs
@@ -3,11 +3,11 @@ use std::convert::TryFrom;
use std::fmt::{self, Debug, Formatter, Write};
use std::iter::FromIterator;
use std::ops::{Add, AddAssign};
-use std::rc::Rc;
+use std::sync::Arc;
use super::Value;
use crate::diag::StrResult;
-use crate::util::RcExt;
+use crate::util::ArcExt;
/// Create a new [`Array`] from values.
#[allow(unused_macros)]
@@ -23,7 +23,7 @@ macro_rules! array {
/// An array of values with clone-on-write value semantics.
#[derive(Default, Clone, PartialEq)]
-pub struct Array(Rc<Vec<Value>>);
+pub struct Array(Arc<Vec<Value>>);
impl Array {
/// Create a new, empty array.
@@ -33,7 +33,7 @@ impl Array {
/// Create a new array from a vector of values.
pub fn from_vec(vec: Vec<Value>) -> Self {
- Self(Rc::new(vec))
+ Self(Arc::new(vec))
}
/// Whether the array is empty.
@@ -59,19 +59,19 @@ impl Array {
let len = self.len();
usize::try_from(index)
.ok()
- .and_then(move |i| Rc::make_mut(&mut self.0).get_mut(i))
+ .and_then(move |i| Arc::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.0).push(value);
+ Arc::make_mut(&mut self.0).push(value);
}
/// Clear the array.
pub fn clear(&mut self) {
- if Rc::strong_count(&self.0) == 1 {
- Rc::make_mut(&mut self.0).clear();
+ if Arc::strong_count(&self.0) == 1 {
+ Arc::make_mut(&mut self.0).clear();
} else {
*self = Self::new();
}
@@ -87,7 +87,7 @@ impl Array {
/// Returns an error if two values could not be compared.
pub fn sorted(mut self) -> StrResult<Self> {
let mut result = Ok(());
- Rc::make_mut(&mut self.0).sort_by(|a, b| {
+ Arc::make_mut(&mut self.0).sort_by(|a, b| {
a.partial_cmp(b).unwrap_or_else(|| {
if result.is_ok() {
result = Err(format!(
@@ -146,7 +146,7 @@ impl Add for Array {
impl AddAssign for Array {
fn add_assign(&mut self, rhs: Array) {
- match Rc::try_unwrap(rhs.0) {
+ match Arc::try_unwrap(rhs.0) {
Ok(vec) => self.extend(vec),
Err(rc) => self.extend(rc.iter().cloned()),
}
@@ -155,13 +155,13 @@ impl AddAssign for Array {
impl Extend<Value> for Array {
fn extend<T: IntoIterator<Item = Value>>(&mut self, iter: T) {
- Rc::make_mut(&mut self.0).extend(iter);
+ Arc::make_mut(&mut self.0).extend(iter);
}
}
impl FromIterator<Value> for Array {
fn from_iter<T: IntoIterator<Item = Value>>(iter: T) -> Self {
- Self(Rc::new(iter.into_iter().collect()))
+ Self(Arc::new(iter.into_iter().collect()))
}
}
@@ -170,7 +170,7 @@ impl IntoIterator for Array {
type IntoIter = std::vec::IntoIter<Value>;
fn into_iter(self) -> Self::IntoIter {
- Rc::take(self.0).into_iter()
+ Arc::take(self.0).into_iter()
}
}
diff --git a/src/eval/capture.rs b/src/eval/capture.rs
index e47831df..8585776a 100644
--- a/src/eval/capture.rs
+++ b/src/eval/capture.rs
@@ -1,4 +1,4 @@
-use std::rc::Rc;
+use std::sync::Arc;
use super::{Scope, Scopes, Value};
use crate::syntax::ast::{ClosureParam, Expr, Ident, Imports, TypedNode};
@@ -35,7 +35,7 @@ impl<'a> CapturesVisitor<'a> {
pub fn capture(&mut self, ident: Ident) {
if self.internal.get(&ident).is_none() {
if let Some(slot) = self.external.get(&ident) {
- self.captures.def_slot(ident.take(), Rc::clone(slot));
+ self.captures.def_slot(ident.take(), Arc::clone(slot));
}
}
}
diff --git a/src/eval/dict.rs b/src/eval/dict.rs
index 0d7198e1..2ce3c3f9 100644
--- a/src/eval/dict.rs
+++ b/src/eval/dict.rs
@@ -2,11 +2,11 @@ use std::collections::BTreeMap;
use std::fmt::{self, Debug, Formatter, Write};
use std::iter::FromIterator;
use std::ops::{Add, AddAssign};
-use std::rc::Rc;
+use std::sync::Arc;
use super::Value;
use crate::diag::StrResult;
-use crate::util::{EcoString, RcExt};
+use crate::util::{ArcExt, EcoString};
/// 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<BTreeMap<EcoString, Value>>);
+pub struct Dict(Arc<BTreeMap<EcoString, Value>>);
impl Dict {
/// Create a new, empty dictionary.
@@ -31,7 +31,7 @@ impl Dict {
/// Create a new dictionary from a mapping of strings to values.
pub fn from_map(map: BTreeMap<EcoString, Value>) -> Self {
- Self(Rc::new(map))
+ Self(Arc::new(map))
}
/// Whether the dictionary is empty.
@@ -54,18 +54,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: EcoString) -> &mut Value {
- Rc::make_mut(&mut self.0).entry(key).or_default()
+ Arc::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: EcoString, value: Value) {
- Rc::make_mut(&mut self.0).insert(key, value);
+ Arc::make_mut(&mut self.0).insert(key, value);
}
/// Clear the dictionary.
pub fn clear(&mut self) {
- if Rc::strong_count(&self.0) == 1 {
- Rc::make_mut(&mut self.0).clear();
+ if Arc::strong_count(&self.0) == 1 {
+ Arc::make_mut(&mut self.0).clear();
} else {
*self = Self::new();
}
@@ -112,7 +112,7 @@ impl Add for Dict {
impl AddAssign for Dict {
fn add_assign(&mut self, rhs: Dict) {
- match Rc::try_unwrap(rhs.0) {
+ match Arc::try_unwrap(rhs.0) {
Ok(map) => self.extend(map),
Err(rc) => self.extend(rc.iter().map(|(k, v)| (k.clone(), v.clone()))),
}
@@ -121,13 +121,13 @@ impl AddAssign for Dict {
impl Extend<(EcoString, Value)> for Dict {
fn extend<T: IntoIterator<Item = (EcoString, Value)>>(&mut self, iter: T) {
- Rc::make_mut(&mut self.0).extend(iter);
+ Arc::make_mut(&mut self.0).extend(iter);
}
}
impl FromIterator<(EcoString, Value)> for Dict {
fn from_iter<T: IntoIterator<Item = (EcoString, Value)>>(iter: T) -> Self {
- Self(Rc::new(iter.into_iter().collect()))
+ Self(Arc::new(iter.into_iter().collect()))
}
}
@@ -136,7 +136,7 @@ impl IntoIterator for Dict {
type IntoIter = std::collections::btree_map::IntoIter<EcoString, Value>;
fn into_iter(self) -> Self::IntoIter {
- Rc::take(self.0).into_iter()
+ Arc::take(self.0).into_iter()
}
}
diff --git a/src/eval/function.rs b/src/eval/function.rs
index 931a90a0..0edc1e78 100644
--- a/src/eval/function.rs
+++ b/src/eval/function.rs
@@ -1,5 +1,5 @@
use std::fmt::{self, Debug, Formatter, Write};
-use std::rc::Rc;
+use std::sync::Arc;
use super::{Cast, EvalContext, Value};
use crate::diag::{At, TypResult};
@@ -8,9 +8,9 @@ use crate::util::EcoString;
/// An evaluatable function.
#[derive(Clone)]
-pub struct Function(Rc<Inner<Func>>);
+pub struct Function(Arc<Inner<Func>>);
-/// The unsized structure behind the [`Rc`].
+/// The unsized structure behind the [`Arc`].
struct Inner<T: ?Sized> {
name: Option<EcoString>,
func: T,
@@ -24,7 +24,7 @@ impl Function {
where
F: Fn(&mut EvalContext, &mut Args) -> TypResult<Value> + 'static,
{
- Self(Rc::new(Inner { name, func }))
+ Self(Arc::new(Inner { name, func }))
}
/// The name of the function.
@@ -53,8 +53,8 @@ impl PartialEq for Function {
fn eq(&self, other: &Self) -> bool {
// We cast to thin pointers for comparison.
std::ptr::eq(
- Rc::as_ptr(&self.0) as *const (),
- Rc::as_ptr(&other.0) as *const (),
+ Arc::as_ptr(&self.0) as *const (),
+ Arc::as_ptr(&other.0) as *const (),
)
}
}
diff --git a/src/eval/node.rs b/src/eval/node.rs
index d909fc7d..665550b0 100644
--- a/src/eval/node.rs
+++ b/src/eval/node.rs
@@ -71,7 +71,7 @@ impl Node {
/// Create an inline-level node.
pub fn inline<T>(node: T) -> Self
where
- T: Layout + Debug + Hash + 'static,
+ T: Layout + Debug + Hash + Sync + Send + 'static,
{
Self::Inline(node.pack())
}
@@ -79,7 +79,7 @@ impl Node {
/// Create a block-level node.
pub fn block<T>(node: T) -> Self
where
- T: Layout + Debug + Hash + 'static,
+ T: Layout + Debug + Hash + Sync + Send + 'static,
{
Self::Block(node.pack())
}
diff --git a/src/eval/scope.rs b/src/eval/scope.rs
index 5178c819..34da68d4 100644
--- a/src/eval/scope.rs
+++ b/src/eval/scope.rs
@@ -2,14 +2,14 @@ use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt::{self, Debug, Formatter};
use std::iter;
-use std::rc::Rc;
+use std::sync::Arc;
use super::{Args, Class, Construct, EvalContext, Function, Set, Value};
use crate::diag::TypResult;
use crate::util::EcoString;
/// A slot where a variable is stored.
-pub type Slot = Rc<RefCell<Value>>;
+pub type Slot = Arc<RefCell<Value>>;
/// A stack of scopes.
#[derive(Debug, Default, Clone)]
@@ -85,12 +85,12 @@ impl Scope {
// FIXME: Use Ref::leak once stable.
std::mem::forget(cell.borrow());
- self.values.insert(var.into(), Rc::new(cell));
+ self.values.insert(var.into(), Arc::new(cell));
}
/// Define a mutable variable with a value.
pub fn def_mut(&mut self, var: impl Into<EcoString>, value: impl Into<Value>) {
- self.values.insert(var.into(), Rc::new(RefCell::new(value.into())));
+ self.values.insert(var.into(), Arc::new(RefCell::new(value.into())));
}
/// Define a variable with a slot.
diff --git a/src/eval/styles.rs b/src/eval/styles.rs
index 508996a1..5276353a 100644
--- a/src/eval/styles.rs
+++ b/src/eval/styles.rs
@@ -1,7 +1,7 @@
use std::any::{Any, TypeId};
use std::fmt::{self, Debug, Formatter};
use std::hash::{Hash, Hasher};
-use std::rc::Rc;
+use std::sync::Arc;
// TODO(style): Possible optimizations:
// - Ref-count map for cheaper cloning and smaller footprint
@@ -334,13 +334,13 @@ impl Debug for Link<'_> {
/// An entry for a single style property.
#[derive(Clone)]
struct Entry {
- p: Rc<dyn Bounds>,
+ p: Arc<dyn Bounds>,
scoped: bool,
}
impl Entry {
fn new<P: Property>(key: P, value: P::Value) -> Self {
- Self { p: Rc::new((key, value)), scoped: false }
+ Self { p: Arc::new((key, value)), scoped: false }
}
fn is<P: Property>(&self) -> bool {
@@ -390,11 +390,11 @@ impl Hash for Entry {
///
/// This trait is not intended to be implemented manually, but rather through
/// the `#[properties]` proc-macro.
-pub trait Property: Copy + 'static {
+pub trait Property: Copy + Sync + Send + 'static {
/// The type of value that is returned when getting this property from a
/// style map. For example, this could be [`Length`](crate::geom::Length)
/// for a `WIDTH` property.
- type Value: Debug + Clone + PartialEq + Hash + 'static;
+ type Value: Debug + Clone + PartialEq + Hash + Sync + Send + 'static;
/// The name of the property, used for debug printing.
const NAME: &'static str;
@@ -432,7 +432,7 @@ pub trait Nonfolding {}
/// value types below. Although it is zero-sized, the property `P` must be part
/// of the implementing type so that we can use it in the methods (it must be a
/// constrained type parameter).
-trait Bounds: 'static {
+trait Bounds: Sync + Send + 'static {
fn as_any(&self) -> &dyn Any;
fn dyn_fmt(&self, f: &mut Formatter) -> fmt::Result;
fn dyn_eq(&self, other: &Entry) -> bool;
diff --git a/src/eval/value.rs b/src/eval/value.rs
index e64f6cc6..7d65d5af 100644
--- a/src/eval/value.rs
+++ b/src/eval/value.rs
@@ -2,7 +2,7 @@ use std::any::Any;
use std::cmp::Ordering;
use std::fmt::{self, Debug, Formatter};
use std::hash::Hash;
-use std::rc::Rc;
+use std::sync::Arc;
use super::{ops, Args, Array, Class, Dict, Function, Node};
use crate::diag::StrResult;
@@ -58,7 +58,7 @@ impl Value {
/// Create an inline-level node value.
pub fn inline<T>(node: T) -> Self
where
- T: Layout + Debug + Hash + 'static,
+ T: Layout + Debug + Hash + Sync + Send + 'static,
{
Self::Node(Node::inline(node))
}
@@ -66,7 +66,7 @@ impl Value {
/// Create a block-level node value.
pub fn block<T>(node: T) -> Self
where
- T: Layout + Debug + Hash + 'static,
+ T: Layout + Debug + Hash + Sync + Send + 'static,
{
Self::Node(Node::block(node))
}
@@ -211,15 +211,15 @@ impl From<Dynamic> for Value {
/// A dynamic value.
#[derive(Clone)]
-pub struct Dynamic(Rc<dyn Bounds>);
+pub struct Dynamic(Arc<dyn Bounds>);
impl Dynamic {
/// Create a new instance from any value that satisifies the required bounds.
pub fn new<T>(any: T) -> Self
where
- T: Type + Debug + PartialEq + 'static,
+ T: Type + Debug + PartialEq + Sync + Send + 'static,
{
- Self(Rc::new(any))
+ Self(Arc::new(any))
}
/// Whether the wrapped type is `T`.
@@ -250,7 +250,7 @@ impl PartialEq for Dynamic {
}
}
-trait Bounds: Debug + 'static {
+trait Bounds: Debug + Sync + Send + 'static {
fn as_any(&self) -> &dyn Any;
fn dyn_eq(&self, other: &Dynamic) -> bool;
fn dyn_type_name(&self) -> &'static str;
@@ -258,7 +258,7 @@ trait Bounds: Debug + 'static {
impl<T> Bounds for T
where
- T: Type + Debug + PartialEq + 'static,
+ T: Type + Debug + PartialEq + Sync + Send + 'static,
{
fn as_any(&self) -> &dyn Any {
self
diff --git a/src/export/pdf.rs b/src/export/pdf.rs
index 1477e283..19134f99 100644
--- a/src/export/pdf.rs
+++ b/src/export/pdf.rs
@@ -3,7 +3,7 @@
use std::cmp::Eq;
use std::collections::{BTreeMap, HashMap, HashSet};
use std::hash::Hash;
-use std::rc::Rc;
+use std::sync::Arc;
use image::{DynamicImage, GenericImageView, ImageFormat, ImageResult, Rgba};
use pdf_writer::types::{
@@ -26,7 +26,7 @@ use crate::Context;
/// included in the PDF.
///
/// Returns the raw bytes making up the PDF file.
-pub fn pdf(ctx: &Context, frames: &[Rc<Frame>]) -> Vec<u8> {
+pub fn pdf(ctx: &Context, frames: &[Arc<Frame>]) -> Vec<u8> {
PdfExporter::new(ctx).export(frames)
}
@@ -60,14 +60,14 @@ impl<'a> PdfExporter<'a> {
}
}
- fn export(mut self, frames: &[Rc<Frame>]) -> Vec<u8> {
+ fn export(mut self, frames: &[Arc<Frame>]) -> Vec<u8> {
self.build_pages(frames);
self.write_fonts();
self.write_images();
self.write_structure()
}
- fn build_pages(&mut self, frames: &[Rc<Frame>]) {
+ fn build_pages(&mut self, frames: &[Arc<Frame>]) {
for frame in frames {
let page = PageExporter::new(self).export(frame);
self.pages.push(page);
diff --git a/src/font.rs b/src/font.rs
index 674ffa63..45cc6be2 100644
--- a/src/font.rs
+++ b/src/font.rs
@@ -3,7 +3,7 @@
use std::collections::{hash_map::Entry, BTreeMap, HashMap};
use std::fmt::{self, Debug, Formatter};
use std::path::{Path, PathBuf};
-use std::rc::Rc;
+use std::sync::Arc;
use serde::{Deserialize, Serialize};
use ttf_parser::{name_id, GlyphId, PlatformId};
@@ -33,15 +33,15 @@ impl FaceId {
/// Storage for loaded and parsed font faces.
pub struct FontStore {
- loader: Rc<dyn Loader>,
+ loader: Arc<dyn Loader>,
faces: Vec<Option<Face>>,
families: BTreeMap<String, Vec<FaceId>>,
- buffers: HashMap<FileHash, Rc<Vec<u8>>>,
+ buffers: HashMap<FileHash, Arc<Vec<u8>>>,
}
impl FontStore {
/// Create a new, empty font store.
- pub fn new(loader: Rc<dyn Loader>) -> Self {
+ pub fn new(loader: Arc<dyn Loader>) -> Self {
let mut faces = vec![];
let mut families = BTreeMap::<String, Vec<FaceId>>::new();
@@ -109,11 +109,11 @@ impl FontStore {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => {
let buffer = self.loader.load(path).ok()?;
- entry.insert(Rc::new(buffer))
+ entry.insert(Arc::new(buffer))
}
};
- let face = Face::new(Rc::clone(buffer), index)?;
+ let face = Face::new(Arc::clone(buffer), index)?;
*slot = Some(face);
}
@@ -147,7 +147,7 @@ pub struct Face {
/// The raw face data, possibly shared with other faces from the same
/// collection. Must stay alive put, because `ttf` points into it using
/// unsafe code.
- buffer: Rc<Vec<u8>>,
+ buffer: Arc<Vec<u8>>,
/// The face's index in the collection (zero if not a collection).
index: u32,
/// The underlying ttf-parser/rustybuzz face.
@@ -182,11 +182,11 @@ pub struct LineMetrics {
impl Face {
/// Parse a font face from a buffer and collection index.
- pub fn new(buffer: Rc<Vec<u8>>, index: u32) -> Option<Self> {
+ pub fn new(buffer: Arc<Vec<u8>>, index: u32) -> Option<Self> {
// Safety:
// - The slices's location is stable in memory:
// - We don't move the underlying vector
- // - Nobody else can move it since we have a strong ref to the `Rc`.
+ // - Nobody else can move it since we have a strong ref to the `Arc`.
// - The internal static lifetime is not leaked because its rewritten
// to the self-lifetime in `ttf()`.
let slice: &'static [u8] =
@@ -238,7 +238,7 @@ impl Face {
}
/// The underlying buffer.
- pub fn buffer(&self) -> &Rc<Vec<u8>> {
+ pub fn buffer(&self) -> &Arc<Vec<u8>> {
&self.buffer
}
diff --git a/src/frame.rs b/src/frame.rs
index 133ba256..f714fbbe 100644
--- a/src/frame.rs
+++ b/src/frame.rs
@@ -1,7 +1,7 @@
//! Finished layouts.
use std::fmt::{self, Debug, Formatter};
-use std::rc::Rc;
+use std::sync::Arc;
use crate::font::FaceId;
use crate::geom::{Align, Em, Length, Paint, Path, Point, Size, Spec, Transform};
@@ -43,7 +43,7 @@ impl Frame {
}
/// Add a group element.
- pub fn push_frame(&mut self, pos: Point, frame: Rc<Self>) {
+ pub fn push_frame(&mut self, pos: Point, frame: Arc<Self>) {
self.elements.push((pos, Element::Group(Group::new(frame))));
}
@@ -100,7 +100,7 @@ impl Frame {
F: FnOnce(&mut Group),
{
let mut wrapper = Frame { elements: vec![], ..*self };
- let mut group = Group::new(Rc::new(std::mem::take(self)));
+ let mut group = Group::new(Arc::new(std::mem::take(self)));
f(&mut group);
wrapper.push(Point::zero(), Element::Group(group));
*self = wrapper;
@@ -149,7 +149,7 @@ pub enum Element {
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Group {
/// The group's frame.
- pub frame: Rc<Frame>,
+ pub frame: Arc<Frame>,
/// A transformation to apply to the group.
pub transform: Transform,
/// Whether the frame should be a clipping boundary.
@@ -158,7 +158,7 @@ pub struct Group {
impl Group {
/// Create a new group with default settings.
- pub fn new(frame: Rc<Frame>) -> Self {
+ pub fn new(frame: Arc<Frame>) -> Self {
Self {
frame,
transform: Transform::identity(),
diff --git a/src/image.rs b/src/image.rs
index bd70bf28..24a0deec 100644
--- a/src/image.rs
+++ b/src/image.rs
@@ -5,7 +5,7 @@ use std::ffi::OsStr;
use std::fmt::{self, Debug, Formatter};
use std::io;
use std::path::Path;
-use std::rc::Rc;
+use std::sync::Arc;
use image::io::Reader as ImageReader;
use image::{DynamicImage, GenericImageView, ImageFormat};
@@ -33,14 +33,14 @@ impl ImageId {
/// Storage for loaded and decoded images.
pub struct ImageStore {
- loader: Rc<dyn Loader>,
+ loader: Arc<dyn Loader>,
files: HashMap<FileHash, ImageId>,
images: Vec<Image>,
}
impl ImageStore {
/// Create a new, empty image store.
- pub fn new(loader: Rc<dyn Loader>) -> Self {
+ pub fn new(loader: Arc<dyn Loader>) -> Self {
Self {
loader,
files: HashMap::new(),
diff --git a/src/layout/constraints.rs b/src/layout/constraints.rs
index 0d772cea..3bdbc4bc 100644
--- a/src/layout/constraints.rs
+++ b/src/layout/constraints.rs
@@ -1,4 +1,4 @@
-use std::rc::Rc;
+use std::sync::Arc;
use super::Regions;
use crate::frame::Frame;
@@ -7,12 +7,12 @@ use crate::geom::{Length, Size, Spec};
/// Constrain a frame with constraints.
pub trait Constrain {
/// Reference-count the frame and wrap it with constraints.
- fn constrain(self, cts: Constraints) -> Constrained<Rc<Frame>>;
+ fn constrain(self, cts: Constraints) -> Constrained<Arc<Frame>>;
}
impl Constrain for Frame {
- fn constrain(self, cts: Constraints) -> Constrained<Rc<Frame>> {
- Constrained::new(Rc::new(self), cts)
+ fn constrain(self, cts: Constraints) -> Constrained<Arc<Frame>> {
+ Constrained::new(Arc::new(self), cts)
}
}
diff --git a/src/layout/incremental.rs b/src/layout/incremental.rs
index 63915b53..2112fef1 100644
--- a/src/layout/incremental.rs
+++ b/src/layout/incremental.rs
@@ -1,6 +1,6 @@
use std::cmp::Reverse;
use std::collections::HashMap;
-use std::rc::Rc;
+use std::sync::Arc;
use itertools::Itertools;
@@ -65,7 +65,7 @@ impl LayoutCache {
&mut self,
hash: u64,
regions: &Regions,
- ) -> Option<Vec<Constrained<Rc<Frame>>>> {
+ ) -> Option<Vec<Constrained<Arc<Frame>>>> {
self.frames
.get_mut(&hash)?
.iter_mut()
@@ -193,7 +193,7 @@ impl LayoutCache {
#[derive(Debug, Clone)]
pub struct FramesEntry {
/// The cached frames for a node.
- frames: Vec<Constrained<Rc<Frame>>>,
+ frames: Vec<Constrained<Arc<Frame>>>,
/// How nested the frame was in the context is was originally appearing in.
level: usize,
/// For how long the element already exists.
@@ -209,7 +209,7 @@ pub struct FramesEntry {
impl FramesEntry {
/// Construct a new instance.
- pub fn new(frames: Vec<Constrained<Rc<Frame>>>, level: usize) -> Self {
+ pub fn new(frames: Vec<Constrained<Arc<Frame>>>, level: usize) -> Self {
Self {
frames,
level,
@@ -222,7 +222,7 @@ impl FramesEntry {
/// Checks if the cached frames are valid in the given regions and returns
/// them if so.
- pub fn lookup(&mut self, regions: &Regions) -> Option<Vec<Constrained<Rc<Frame>>>> {
+ pub fn lookup(&mut self, regions: &Regions) -> Option<Vec<Constrained<Arc<Frame>>>> {
self.check(regions).then(|| {
self.temperature[0] = self.temperature[0].saturating_add(1);
self.frames.clone()
@@ -396,9 +396,9 @@ mod tests {
use crate::geom::{Size, Spec};
use crate::layout::Constraints;
- fn empty_frames() -> Vec<Constrained<Rc<Frame>>> {
+ fn empty_frames() -> Vec<Constrained<Arc<Frame>>> {
vec![Constrained {
- item: Rc::new(Frame::default()),
+ item: Arc::new(Frame::default()),
cts: Constraints::new(Spec::splat(false)),
}]
}
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index e4c29f9b..147e8c9d 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -13,7 +13,7 @@ pub use regions::*;
use std::any::Any;
use std::fmt::{self, Debug, Formatter};
use std::hash::{Hash, Hasher};
-use std::rc::Rc;
+use std::sync::Arc;
use crate::eval::{StyleChain, Styled};
use crate::font::FontStore;
@@ -29,7 +29,7 @@ pub struct RootNode(pub Vec<Styled<PageNode>>);
impl RootNode {
/// Layout the document into a sequence of frames, one per page.
- pub fn layout(&self, ctx: &mut Context) -> Vec<Rc<Frame>> {
+ pub fn layout(&self, ctx: &mut Context) -> Vec<Arc<Frame>> {
let (mut ctx, styles) = LayoutContext::new(ctx);
self.0
.iter()
@@ -56,17 +56,17 @@ pub trait Layout {
ctx: &mut LayoutContext,
regions: &Regions,
styles: StyleChain,
- ) -> Vec<Constrained<Rc<Frame>>>;
+ ) -> Vec<Constrained<Arc<Frame>>>;
/// Convert to a packed node.
fn pack(self) -> PackedNode
where
- Self: Debug + Hash + Sized + 'static,
+ Self: Debug + Hash + Sized + Sync + Send + 'static,
{
PackedNode {
#[cfg(feature = "layout-cache")]
hash: self.hash64(),
- node: Rc::new(self),
+ node: Arc::new(self),
}
}
}
@@ -112,7 +112,7 @@ impl Layout for EmptyNode {
_: &mut LayoutContext,
regions: &Regions,
_: StyleChain,
- ) -> Vec<Constrained<Rc<Frame>>> {
+ ) -> Vec<Constrained<Arc<Frame>>> {
let size = regions.expand.select(regions.current, Size::zero());
let mut cts = Constraints::new(regions.expand);
cts.exact = regions.current.filter(regions.expand);
@@ -124,7 +124,7 @@ impl Layout for EmptyNode {
#[derive(Clone)]
pub struct PackedNode {
/// The type-erased node.
- node: Rc<dyn Bounds>,
+ node: Arc<dyn Bounds>,
/// A precomputed hash for the node.
#[cfg(feature = "layout-cache")]
hash: u64,
@@ -205,7 +205,7 @@ impl Layout for PackedNode {
ctx: &mut LayoutContext,
regions: &Regions,
styles: StyleChain,
- ) -> Vec<Constrained<Rc<Frame>>> {
+ ) -> Vec<Constrained<Arc<Frame>>> {
let styles = styles.barred(self.node.as_any().type_id());
#[cfg(not(feature = "layout-cache"))]
@@ -243,10 +243,7 @@ impl Layout for PackedNode {
})
}
- fn pack(self) -> PackedNode
- where
- Self: Sized + Hash + 'static,
- {
+ fn pack(self) -> PackedNode {
self
}
}
@@ -266,8 +263,8 @@ impl Debug for PackedNode {
impl PartialEq for PackedNode {
fn eq(&self, other: &Self) -> bool {
std::ptr::eq(
- Rc::as_ptr(&self.node) as *const (),
- Rc::as_ptr(&other.node) as *const (),
+ Arc::as_ptr(&self.node) as *const (),
+ Arc::as_ptr(&other.node) as *const (),
)
}
}
@@ -282,14 +279,14 @@ impl Hash for PackedNode {
}
}
-trait Bounds: Layout + Debug + 'static {
+trait Bounds: Layout + Debug + Sync + Send + 'static {
fn as_any(&self) -> &dyn Any;
fn hash64(&self) -> u64;
}
impl<T> Bounds for T
where
- T: Layout + Hash + Debug + 'static,
+ T: Layout + Hash + Debug + Sync + Send + 'static,
{
fn as_any(&self) -> &dyn Any {
self
@@ -320,7 +317,7 @@ impl Layout for SizedNode {
ctx: &mut LayoutContext,
regions: &Regions,
styles: StyleChain,
- ) -> Vec<Constrained<Rc<Frame>>> {
+ ) -> Vec<Constrained<Arc<Frame>>> {
let is_auto = self.sizing.map_is_none();
let is_rel = self.sizing.map(|s| s.map_or(false, Linear::is_relative));
@@ -346,7 +343,7 @@ impl Layout for SizedNode {
// Ensure frame size matches regions size if expansion is on.
let target = regions.expand.select(regions.current, frame.size);
- Rc::make_mut(frame).resize(target, Align::LEFT_TOP);
+ Arc::make_mut(frame).resize(target, Align::LEFT_TOP);
// Set base & exact constraints if the child is automatically sized
// since we don't know what the child might have done. Also set base if
@@ -374,11 +371,11 @@ impl Layout for FillNode {
ctx: &mut LayoutContext,
regions: &Regions,
styles: StyleChain,
- ) -> Vec<Constrained<Rc<Frame>>> {
+ ) -> Vec<Constrained<Arc<Frame>>> {
let mut frames = self.child.layout(ctx, regions, styles);
for Constrained { item: frame, .. } in &mut frames {
let shape = Shape::filled(Geometry::Rect(frame.size), self.fill);
- Rc::make_mut(frame).prepend(Point::zero(), Element::Shape(shape));
+ Arc::make_mut(frame).prepend(Point::zero(), Element::Shape(shape));
}
frames
}
@@ -399,11 +396,11 @@ impl Layout for StrokeNode {
ctx: &mut LayoutContext,
regions: &Regions,
styles: StyleChain,
- ) -> Vec<Constrained<Rc<Frame>>> {
+ ) -> Vec<Constrained<Arc<Frame>>> {
let mut frames = self.child.layout(ctx, regions, styles);
for Constrained { item: frame, .. } in &mut frames {
let shape = Shape::stroked(Geometry::Rect(frame.size), self.stroke);
- Rc::make_mut(frame).prepend(Point::zero(), Element::Shape(shape));
+ Arc::make_mut(frame).prepend(Point::zero(), Element::Shape(shape));
}
frames
}
diff --git a/src/lib.rs b/src/lib.rs
index a764468b..6d52ceaa 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -52,7 +52,7 @@ pub mod parse;
pub mod source;
pub mod syntax;
-use std::rc::Rc;
+use std::sync::Arc;
use crate::diag::TypResult;
use crate::eval::{Eval, EvalContext, Module, Scope, StyleMap};
@@ -68,7 +68,7 @@ use crate::source::{SourceId, SourceStore};
/// The core context which holds the loader, configuration and cached artifacts.
pub struct Context {
/// The loader the context was created with.
- pub loader: Rc<dyn Loader>,
+ pub loader: Arc<dyn Loader>,
/// Stores loaded source files.
pub sources: SourceStore,
/// Stores parsed font faces.
@@ -88,7 +88,7 @@ pub struct Context {
impl Context {
/// Create a new context with the default settings.
- pub fn new(loader: Rc<dyn Loader>) -> Self {
+ pub fn new(loader: Arc<dyn Loader>) -> Self {
Self::builder().build(loader)
}
@@ -124,7 +124,7 @@ impl Context {
/// Returns either a vector of frames representing individual pages or
/// diagnostics in the form of a vector of error message with file and span
/// information.
- pub fn typeset(&mut self, id: SourceId) -> TypResult<Vec<Rc<Frame>>> {
+ pub fn typeset(&mut self, id: SourceId) -> TypResult<Vec<Arc<Frame>>> {
let module = self.evaluate(id)?;
let tree = module.into_root();
let frames = tree.layout(self);
@@ -183,11 +183,11 @@ impl ContextBuilder {
/// Finish building the context by providing the `loader` used to load
/// fonts, images, source files and other resources.
- pub fn build(self, loader: Rc<dyn Loader>) -> Context {
+ pub fn build(self, loader: Arc<dyn Loader>) -> Context {
Context {
- sources: SourceStore::new(Rc::clone(&loader)),
- fonts: FontStore::new(Rc::clone(&loader)),
- images: ImageStore::new(Rc::clone(&loader)),
+ sources: SourceStore::new(Arc::clone(&loader)),
+ fonts: FontStore::new(Arc::clone(&loader)),
+ images: ImageStore::new(Arc::clone(&loader)),
loader,
#[cfg(feature = "layout-cache")]
layout_cache: LayoutCache::new(self.policy, self.max_size),
diff --git a/src/library/align.rs b/src/library/align.rs
index 8eee116e..ecf50cc4 100644
--- a/src/library/align.rs
+++ b/src/library/align.rs
@@ -27,7 +27,7 @@ impl Layout for AlignNode {
ctx: &mut LayoutContext,
regions: &Regions,
styles: StyleChain,
- ) -> Vec<Constrained<Rc<Frame>>> {
+ ) -> Vec<Constrained<Arc<Frame>>> {
// The child only needs to expand along an axis if there's no alignment.
let mut pod = regions.clone();
pod.expand &= self.aligns.map_is_none();
@@ -49,7 +49,7 @@ impl Layout for AlignNode {
let target = regions.expand.select(current, frame.size);
let default = Spec::new(Align::Left, Align::Top);
let aligns = self.aligns.unwrap_or(default);
- Rc::make_mut(frame).resize(target, aligns);
+ Arc::make_mut(frame).resize(target, aligns);
// Set constraints.
cts.expand = regions.expand;
diff --git a/src/library/columns.rs b/src/library/columns.rs
index d2dc350f..149da755 100644
--- a/src/library/columns.rs
+++ b/src/library/columns.rs
@@ -37,7 +37,7 @@ impl Layout for ColumnsNode {
ctx: &mut LayoutContext,
regions: &Regions,
styles: StyleChain,
- ) -> Vec<Constrained<Rc<Frame>>> {
+ ) -> Vec<Constrained<Arc<Frame>>> {
let columns = self.columns.get();
// Separating the infinite space into infinite columns does not make
diff --git a/src/library/flow.rs b/src/library/flow.rs
index 3405b04a..95426731 100644
--- a/src/library/flow.rs
+++ b/src/library/flow.rs
@@ -18,7 +18,7 @@ impl Layout for FlowNode {
ctx: &mut LayoutContext,
regions: &Regions,
styles: StyleChain,
- ) -> Vec<Constrained<Rc<Frame>>> {
+ ) -> Vec<Constrained<Arc<Frame>>> {
FlowLayouter::new(self, regions.clone()).layout(ctx, styles)
}
}
@@ -72,7 +72,7 @@ struct FlowLayouter<'a> {
/// Spacing and layouted nodes.
items: Vec<FlowItem>,
/// Finished frames for previous regions.
- finished: Vec<Constrained<Rc<Frame>>>,
+ finished: Vec<Constrained<Arc<Frame>>>,
}
/// A prepared item in a flow layout.
@@ -82,9 +82,9 @@ enum FlowItem {
/// Fractional spacing between other items.
Fractional(Fractional),
/// A frame for a layouted child node and how to align it.
- Frame(Rc<Frame>, Spec<Align>),
+ Frame(Arc<Frame>, Spec<Align>),
/// An absolutely placed frame.
- Placed(Rc<Frame>),
+ Placed(Arc<Frame>),
}
impl<'a> FlowLayouter<'a> {
@@ -113,7 +113,7 @@ impl<'a> FlowLayouter<'a> {
mut self,
ctx: &mut LayoutContext,
styles: StyleChain,
- ) -> Vec<Constrained<Rc<Frame>>> {
+ ) -> Vec<Constrained<Arc<Frame>>> {
for styled in self.children {
let styles = styled.map.chain(&styles);
match styled.item {
diff --git a/src/library/grid.rs b/src/library/grid.rs
index 59f52427..c49ac84f 100644
--- a/src/library/grid.rs
+++ b/src/library/grid.rs
@@ -38,7 +38,7 @@ impl Layout for GridNode {
ctx: &mut LayoutContext,
regions: &Regions,
styles: StyleChain,
- ) -> Vec<Constrained<Rc<Frame>>> {
+ ) -> Vec<Constrained<Arc<Frame>>> {
// Prepare grid layout by unifying content and gutter tracks.
let mut layouter = GridLayouter::new(self, regions.clone(), styles);
@@ -114,7 +114,7 @@ struct GridLayouter<'a> {
/// Constraints for the active region.
cts: Constraints,
/// Frames for finished regions.
- finished: Vec<Constrained<Rc<Frame>>>,
+ finished: Vec<Constrained<Arc<Frame>>>,
}
/// Produced by initial row layout, auto and linear rows are already finished,
@@ -355,7 +355,7 @@ impl<'a> GridLayouter<'a> {
}
/// Layout the grid row-by-row.
- fn layout(mut self, ctx: &mut LayoutContext) -> Vec<Constrained<Rc<Frame>>> {
+ fn layout(mut self, ctx: &mut LayoutContext) -> Vec<Constrained<Arc<Frame>>> {
for y in 0 .. self.rows.len() {
// Skip to next region if current one is full, but only for content
// rows, not for gutter rows.
diff --git a/src/library/heading.rs b/src/library/heading.rs
index 4c7bcc7d..17efb5e4 100644
--- a/src/library/heading.rs
+++ b/src/library/heading.rs
@@ -51,7 +51,7 @@ impl Layout for HeadingNode {
ctx: &mut LayoutContext,
regions: &Regions,
styles: StyleChain,
- ) -> Vec<Constrained<Rc<Frame>>> {
+ ) -> Vec<Constrained<Arc<Frame>>> {
let upscale = (1.6 - 0.1 * self.level as f64).max(0.75);
let mut passed = StyleMap::new();
@@ -82,7 +82,7 @@ impl Layout for HeadingNode {
// FIXME: Constraints and region size.
for Constrained { item: frame, .. } in &mut frames {
- let frame = Rc::make_mut(frame);
+ let frame = Arc::make_mut(frame);
frame.size.y += above + below;
frame.translate(Point::with_y(above));
}
diff --git a/src/library/hidden.rs b/src/library/hidden.rs
index 7287bf3d..5025fefb 100644
--- a/src/library/hidden.rs
+++ b/src/library/hidden.rs
@@ -19,12 +19,12 @@ impl Layout for HideNode {
ctx: &mut LayoutContext,
regions: &Regions,
styles: StyleChain,
- ) -> Vec<Constrained<Rc<Frame>>> {
+ ) -> Vec<Constrained<Arc<Frame>>> {
let mut frames = self.0.layout(ctx, regions, styles);
// Clear the frames.
for Constrained { item: frame, .. } in &mut frames {
- *frame = Rc::new(Frame { elements: vec![], ..**frame });
+ *frame = Arc::new(Frame { elements: vec![], ..**frame });
}
frames
diff --git a/src/library/image.rs b/src/library/image.rs
index a5423ccb..06b3fe31 100644
--- a/src/library/image.rs
+++ b/src/library/image.rs
@@ -44,7 +44,7 @@ impl Layout for ImageNode {
ctx: &mut LayoutContext,
regions: &Regions,
styles: StyleChain,
- ) -> Vec<Constrained<Rc<Frame>>> {
+ ) -> Vec<Constrained<Arc<Frame>>> {
let img = ctx.images.get(self.0);
let pxw = img.width() as f64;
let pxh = img.height() as f64;
diff --git a/src/library/link.rs b/src/library/link.rs
index dc523ffd..0ecd317b 100644
--- a/src/library/link.rs
+++ b/src/library/link.rs
@@ -10,13 +10,14 @@ pub struct LinkNode;
#[class]
impl LinkNode {
fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Node> {
- let url: String = args.expect::<EcoString>("url")?.into();
+ let url = args.expect::<EcoString>("url")?;
let body = args.find().unwrap_or_else(|| {
let mut text = url.as_str();
for prefix in ["mailto:", "tel:"] {
text = text.trim_start_matches(prefix);
}
- Node::Text(text.into())
+ let shorter = text.len() < url.len();
+ Node::Text(if shorter { text.into() } else { url.clone() })
});
Ok(body.styled(TextNode::LINK, Some(url)))
diff --git a/src/library/list.rs b/src/library/list.rs
index 9f742a32..94f7aa44 100644
--- a/src/library/list.rs
+++ b/src/library/list.rs
@@ -39,7 +39,7 @@ impl<L: ListKind> Layout for ListNode<L> {
ctx: &mut LayoutContext,
regions: &Regions,
styles: StyleChain,
- ) -> Vec<Constrained<Rc<Frame>>> {
+ ) -> Vec<Constrained<Arc<Frame>>> {
let em = styles.get(TextNode::SIZE).abs;
let label_indent = styles.get(Self::LABEL_INDENT).resolve(em);
let body_indent = styles.get(Self::BODY_INDENT).resolve(em);
@@ -65,7 +65,7 @@ impl<L: ListKind> Layout for ListNode<L> {
}
/// How to label a list.
-pub trait ListKind: Debug + Default + Hash + 'static {
+pub trait ListKind: Debug + Default + Hash + Sync + Send + 'static {
/// Return the item's label.
fn label(&self) -> EcoString;
}
diff --git a/src/library/mod.rs b/src/library/mod.rs
index 3115cc7a..ae7fc3a1 100644
--- a/src/library/mod.rs
+++ b/src/library/mod.rs
@@ -61,7 +61,7 @@ macro_rules! prelude {
prelude! {
pub use std::fmt::{self, Debug, Formatter};
pub use std::num::NonZeroUsize;
- pub use std::rc::Rc;
+ pub use std::sync::Arc;
pub use std::hash::Hash;
pub use typst_macros::class;
diff --git a/src/library/pad.rs b/src/library/pad.rs
index 394d3c17..8bfc6d17 100644
--- a/src/library/pad.rs
+++ b/src/library/pad.rs
@@ -37,7 +37,7 @@ impl Layout for PadNode {
ctx: &mut LayoutContext,
regions: &Regions,
styles: StyleChain,
- ) -> Vec<Constrained<Rc<Frame>>> {
+ ) -> Vec<Constrained<Arc<Frame>>> {
// Layout child into padded regions.
let pod = regions.map(|size| shrink(size, self.padding));
let mut frames = self.child.layout(ctx, &pod, styles);
@@ -52,7 +52,7 @@ impl Layout for PadNode {
let offset = Point::new(padding.left, padding.top);
// Grow the frame and translate everything in the frame inwards.
- let frame = Rc::make_mut(frame);
+ let frame = Arc::make_mut(frame);
frame.size = padded;
frame.translate(offset);
diff --git a/src/library/page.rs b/src/library/page.rs
index f3a287dc..9949e1e7 100644
--- a/src/library/page.rs
+++ b/src/library/page.rs
@@ -70,7 +70,7 @@ impl PageNode {
impl PageNode {
/// Layout the page run into a sequence of frames, one per page.
- pub fn layout(&self, ctx: &mut LayoutContext, styles: StyleChain) -> Vec<Rc<Frame>> {
+ pub fn layout(&self, ctx: &mut LayoutContext, styles: StyleChain) -> Vec<Arc<Frame>> {
// When one of the lengths is infinite the page fits its content along
// that axis.
let width = styles.get(Self::WIDTH).unwrap_or(Length::inf());
diff --git a/src/library/par.rs b/src/library/par.rs
index 4f711e76..913d2253 100644
--- a/src/library/par.rs
+++ b/src/library/par.rs
@@ -1,7 +1,7 @@
//! Paragraph layout.
use std::fmt::{self, Debug, Formatter};
-use std::rc::Rc;
+use std::sync::Arc;
use itertools::Either;
use unicode_bidi::{BidiInfo, Level};
@@ -9,7 +9,7 @@ use xi_unicode::LineBreakIterator;
use super::prelude::*;
use super::{shape, ShapedText, SpacingKind, TextNode};
-use crate::util::{EcoString, RangeExt, RcExt, SliceExt};
+use crate::util::{ArcExt, EcoString, RangeExt, SliceExt};
/// A node that arranges its children into a paragraph.
#[derive(Hash)]
@@ -75,7 +75,7 @@ impl Layout for ParNode {
ctx: &mut LayoutContext,
regions: &Regions,
styles: StyleChain,
- ) -> Vec<Constrained<Rc<Frame>>> {
+ ) -> Vec<Constrained<Arc<Frame>>> {
// Collect all text into one string used for BiDi analysis.
let text = self.collect_text();
@@ -253,7 +253,7 @@ impl<'a> ParLayouter<'a> {
let size = Size::new(regions.current.x, regions.base.y);
let pod = Regions::one(size, regions.base, Spec::splat(false));
let frame = node.layout(ctx, &pod, styles).remove(0);
- items.push(ParItem::Frame(Rc::take(frame.item)));
+ items.push(ParItem::Frame(Arc::take(frame.item)));
ranges.push(range);
}
}
@@ -271,7 +271,7 @@ impl<'a> ParLayouter<'a> {
self,
ctx: &mut LayoutContext,
regions: Regions,
- ) -> Vec<Constrained<Rc<Frame>>> {
+ ) -> Vec<Constrained<Arc<Frame>>> {
let mut stack = LineStack::new(self.leading, regions);
// The current line attempt.
@@ -582,7 +582,7 @@ struct LineStack<'a> {
regions: Regions,
size: Size,
lines: Vec<LineLayout<'a>>,
- finished: Vec<Constrained<Rc<Frame>>>,
+ finished: Vec<Constrained<Arc<Frame>>>,
cts: Constraints,
overflowing: bool,
fractional: bool,
@@ -650,7 +650,7 @@ impl<'a> LineStack<'a> {
}
/// Finish the last region and return the built frames.
- fn finish(mut self, ctx: &LayoutContext) -> Vec<Constrained<Rc<Frame>>> {
+ fn finish(mut self, ctx: &LayoutContext) -> Vec<Constrained<Arc<Frame>>> {
self.finish_region(ctx);
self.finished
}
diff --git a/src/library/place.rs b/src/library/place.rs
index cee687fa..d5880995 100644
--- a/src/library/place.rs
+++ b/src/library/place.rs
@@ -26,7 +26,7 @@ impl Layout for PlaceNode {
ctx: &mut LayoutContext,
regions: &Regions,
styles: StyleChain,
- ) -> Vec<Constrained<Rc<Frame>>> {
+ ) -> Vec<Constrained<Arc<Frame>>> {
let out_of_flow = self.out_of_flow();
// The pod is the base area of the region because for absolute
@@ -43,7 +43,7 @@ impl Layout for PlaceNode {
// If expansion is off, zero all sizes so that we don't take up any
// space in our parent. Otherwise, respect the expand settings.
let target = regions.expand.select(regions.current, Size::zero());
- Rc::make_mut(frame).resize(target, Align::LEFT_TOP);
+ Arc::make_mut(frame).resize(target, Align::LEFT_TOP);
// Set base constraint because our pod size is base and exact
// constraints if we needed to expand or offset.
diff --git a/src/library/shape.rs b/src/library/shape.rs
index 12126ab4..5d31d570 100644
--- a/src/library/shape.rs
+++ b/src/library/shape.rs
@@ -66,7 +66,7 @@ impl<S: ShapeKind> Layout for ShapeNode<S> {
ctx: &mut LayoutContext,
regions: &Regions,
styles: StyleChain,
- ) -> Vec<Constrained<Rc<Frame>>> {
+ ) -> Vec<Constrained<Arc<Frame>>> {
let mut frames;
if let Some(child) = &self.child {
let mut padding = styles.get(Self::PADDING);
@@ -118,7 +118,7 @@ impl<S: ShapeKind> Layout for ShapeNode<S> {
frames = vec![Frame::new(size).constrain(Constraints::tight(regions))];
}
- let frame = Rc::make_mut(&mut frames[0].item);
+ let frame = Arc::make_mut(&mut frames[0].item);
// Add fill and/or stroke.
let fill = styles.get(Self::FILL);
@@ -149,7 +149,7 @@ impl<S: ShapeKind> Layout for ShapeNode<S> {
}
/// Categorizes shapes.
-pub trait ShapeKind: Debug + Default + Hash + 'static {
+pub trait ShapeKind: Debug + Default + Hash + Sync + Send + 'static {
const ROUND: bool;
const QUADRATIC: bool;
}
diff --git a/src/library/stack.rs b/src/library/stack.rs
index 8c8a9f60..14b268c2 100644
--- a/src/library/stack.rs
+++ b/src/library/stack.rs
@@ -31,7 +31,7 @@ impl Layout for StackNode {
ctx: &mut LayoutContext,
regions: &Regions,
styles: StyleChain,
- ) -> Vec<Constrained<Rc<Frame>>> {
+ ) -> Vec<Constrained<Arc<Frame>>> {
StackLayouter::new(self, regions.clone(), styles).layout(ctx)
}
}
@@ -90,7 +90,7 @@ struct StackLayouter<'a> {
/// Spacing and layouted nodes.
items: Vec<StackItem>,
/// Finished frames for previous regions.
- finished: Vec<Constrained<Rc<Frame>>>,
+ finished: Vec<Constrained<Arc<Frame>>>,
}
/// A prepared item in a stack layout.
@@ -100,7 +100,7 @@ enum StackItem {
/// Fractional spacing between other items.
Fractional(Fractional),
/// A layouted child node.
- Frame(Rc<Frame>, Align),
+ Frame(Arc<Frame>, Align),
}
impl<'a> StackLayouter<'a> {
@@ -131,7 +131,7 @@ impl<'a> StackLayouter<'a> {
}
/// Layout all children.
- fn layout(mut self, ctx: &mut LayoutContext) -> Vec<Constrained<Rc<Frame>>> {
+ fn layout(mut self, ctx: &mut LayoutContext) -> Vec<Constrained<Arc<Frame>>> {
// Spacing to insert before the next node.
let mut deferred = None;
diff --git a/src/library/table.rs b/src/library/table.rs
index 0e41ad78..d7aa61db 100644
--- a/src/library/table.rs
+++ b/src/library/table.rs
@@ -60,7 +60,7 @@ impl Layout for TableNode {
ctx: &mut LayoutContext,
regions: &Regions,
styles: StyleChain,
- ) -> Vec<Constrained<Rc<Frame>>> {
+ ) -> Vec<Constrained<Arc<Frame>>> {
let primary = styles.get(Self::PRIMARY);
let secondary = styles.get(Self::SECONDARY);
let thickness = styles.get(Self::THICKNESS);
diff --git a/src/library/text.rs b/src/library/text.rs
index 6d7be323..c6c1ab80 100644
--- a/src/library/text.rs
+++ b/src/library/text.rs
@@ -55,7 +55,7 @@ impl TextNode {
#[fold(|a, b| a.into_iter().chain(b).collect())]
pub const LINES: Vec<Decoration> = vec![];
/// An URL the text should link to.
- pub const LINK: Option<String> = None;
+ pub const LINK: Option<EcoString> = None;
/// The size of the glyphs.
#[fold(Linear::compose)]
@@ -211,12 +211,12 @@ castable! {
/// A specific font family like "Arial".
#[derive(Clone, Eq, PartialEq, Hash)]
-pub struct NamedFamily(String);
+pub struct NamedFamily(EcoString);
impl NamedFamily {
/// Create a named font family variant.
pub fn new(string: &str) -> Self {
- Self(string.to_lowercase())
+ Self(string.to_lowercase().into())
}
/// The lowercased family name.
diff --git a/src/library/transform.rs b/src/library/transform.rs
index aceb4197..e9a41a98 100644
--- a/src/library/transform.rs
+++ b/src/library/transform.rs
@@ -36,7 +36,7 @@ impl<T: TransformKind> Layout for TransformNode<T> {
ctx: &mut LayoutContext,
regions: &Regions,
styles: StyleChain,
- ) -> Vec<Constrained<Rc<Frame>>> {
+ ) -> Vec<Constrained<Arc<Frame>>> {
let origin = styles.get(Self::ORIGIN).unwrap_or(Align::CENTER_HORIZON);
let matrix = self.kind.matrix();
@@ -48,7 +48,7 @@ impl<T: TransformKind> Layout for TransformNode<T> {
.pre_concat(matrix)
.pre_concat(Transform::translation(-x, -y));
- Rc::make_mut(frame).transform(transform);
+ Arc::make_mut(frame).transform(transform);
}
frames
@@ -56,7 +56,7 @@ impl<T: TransformKind> Layout for TransformNode<T> {
}
/// Kinds of transformations.
-pub trait TransformKind: Debug + Hash + Sized + 'static {
+pub trait TransformKind: Debug + Hash + Sized + Sync + Send + 'static {
fn construct(args: &mut Args) -> TypResult<Self>;
fn matrix(&self) -> Transform;
}
diff --git a/src/loading/fs.rs b/src/loading/fs.rs
index 4c46c80c..3f4a45e1 100644
--- a/src/loading/fs.rs
+++ b/src/loading/fs.rs
@@ -1,7 +1,7 @@
use std::fs::{self, File};
use std::io;
use std::path::Path;
-use std::rc::Rc;
+use std::sync::Arc;
use memmap2::Mmap;
use same_file::Handle;
@@ -35,10 +35,10 @@ impl FsLoader {
self
}
- /// Builder-style method to wrap the loader in an [`Rc`] to make it usable
+ /// Builder-style method to wrap the loader in an [`Arc`] to make it usable
/// with the [`Context`](crate::Context).
- pub fn wrap(self) -> Rc<Self> {
- Rc::new(self)
+ pub fn wrap(self) -> Arc<Self> {
+ Arc::new(self)
}
/// Search for fonts in the operating system's font directories.
diff --git a/src/loading/mem.rs b/src/loading/mem.rs
index 9ff02d2d..5e3e78d1 100644
--- a/src/loading/mem.rs
+++ b/src/loading/mem.rs
@@ -2,7 +2,7 @@ use std::borrow::Cow;
use std::collections::HashMap;
use std::io;
use std::path::{Path, PathBuf};
-use std::rc::Rc;
+use std::sync::Arc;
use super::{FileHash, Loader};
use crate::font::FaceInfo;
@@ -31,10 +31,10 @@ impl MemLoader {
self
}
- /// Builder-style method to wrap the loader in an [`Rc`] to make it usable
+ /// Builder-style method to wrap the loader in an [`Arc`] to make it usable
/// with the [`Context`](crate::Context).
- pub fn wrap(self) -> Rc<Self> {
- Rc::new(self)
+ pub fn wrap(self) -> Arc<Self> {
+ Arc::new(self)
}
/// Insert a path-file mapping. If the data forms a font, then that font
diff --git a/src/parse/incremental.rs b/src/parse/incremental.rs
index c1da9698..a347f6ca 100644
--- a/src/parse/incremental.rs
+++ b/src/parse/incremental.rs
@@ -1,5 +1,5 @@
use std::ops::Range;
-use std::rc::Rc;
+use std::sync::Arc;
use crate::syntax::{Green, GreenNode, NodeKind};
@@ -78,8 +78,8 @@ impl<'a> Reparser<'a> {
impl Reparser<'_> {
/// Find the innermost child that is incremental safe.
- pub fn reparse(&self, green: &mut Rc<GreenNode>) -> Range<usize> {
- self.reparse_step(Rc::make_mut(green), 0, TokenMode::Markup, true)
+ pub fn reparse(&self, green: &mut Arc<GreenNode>) -> Range<usize> {
+ self.reparse_step(Arc::make_mut(green), 0, TokenMode::Markup, true)
.unwrap_or_else(|| {
*green = parse(self.src);
0 .. self.src.len()
@@ -167,7 +167,7 @@ impl Reparser<'_> {
if last_kind.succession_rule() != SuccessionRule::Unsafe {
if let Some(range) = match child {
Green::Node(node) => self.reparse_step(
- Rc::make_mut(node),
+ Arc::make_mut(node),
first_start,
child_mode,
outermost,
diff --git a/src/parse/mod.rs b/src/parse/mod.rs
index 38a08ab8..fbace15b 100644
--- a/src/parse/mod.rs
+++ b/src/parse/mod.rs
@@ -12,14 +12,14 @@ pub use resolve::*;
pub use scanner::*;
pub use tokens::*;
-use std::rc::Rc;
+use std::sync::Arc;
use crate::syntax::ast::{Associativity, BinOp, UnOp};
use crate::syntax::{ErrorPos, Green, GreenNode, NodeKind};
use crate::util::EcoString;
/// Parse a source file.
-pub fn parse(src: &str) -> Rc<GreenNode> {
+pub fn parse(src: &str) -> Arc<GreenNode> {
let mut p = Parser::new(src, TokenMode::Markup);
markup(&mut p, true);
match p.finish().into_iter().next() {
diff --git a/src/parse/tokens.rs b/src/parse/tokens.rs
index 27da3b80..970c0dd6 100644
--- a/src/parse/tokens.rs
+++ b/src/parse/tokens.rs
@@ -1,4 +1,4 @@
-use std::rc::Rc;
+use std::sync::Arc;
use super::{
is_id_continue, is_id_start, is_newline, resolve_hex, resolve_raw, resolve_string,
@@ -321,7 +321,7 @@ impl<'s> Tokens<'s> {
// Special case for empty inline block.
if backticks == 2 {
- return NodeKind::Raw(Rc::new(RawNode {
+ return NodeKind::Raw(Arc::new(RawNode {
text: EcoString::new(),
lang: None,
block: false,
@@ -341,7 +341,7 @@ impl<'s> Tokens<'s> {
if found == backticks {
let end = self.s.index() - found as usize;
- NodeKind::Raw(Rc::new(resolve_raw(
+ NodeKind::Raw(Arc::new(resolve_raw(
column,
backticks,
self.s.get(start .. end),
@@ -393,7 +393,7 @@ impl<'s> Tokens<'s> {
};
if terminated {
- NodeKind::Math(Rc::new(MathNode {
+ NodeKind::Math(Arc::new(MathNode {
formula: self.s.get(start .. end).into(),
display,
}))
@@ -581,7 +581,7 @@ mod tests {
}
fn Raw(text: &str, lang: Option<&str>, block: bool) -> NodeKind {
- NodeKind::Raw(Rc::new(RawNode {
+ NodeKind::Raw(Arc::new(RawNode {
text: text.into(),
lang: lang.map(Into::into),
block,
@@ -589,7 +589,7 @@ mod tests {
}
fn Math(formula: &str, display: bool) -> NodeKind {
- NodeKind::Math(Rc::new(MathNode { formula: formula.into(), display }))
+ NodeKind::Math(Arc::new(MathNode { formula: formula.into(), display }))
}
fn Str(string: &str) -> NodeKind {
diff --git a/src/source.rs b/src/source.rs
index fd42c3f7..0e7b4c63 100644
--- a/src/source.rs
+++ b/src/source.rs
@@ -4,7 +4,7 @@ use std::collections::HashMap;
use std::io;
use std::ops::Range;
use std::path::{Path, PathBuf};
-use std::rc::Rc;
+use std::sync::Arc;
use crate::diag::TypResult;
use crate::loading::{FileHash, Loader};
@@ -37,14 +37,14 @@ impl SourceId {
/// Storage for loaded source files.
pub struct SourceStore {
- loader: Rc<dyn Loader>,
+ loader: Arc<dyn Loader>,
files: HashMap<FileHash, SourceId>,
sources: Vec<SourceFile>,
}
impl SourceStore {
/// Create a new, empty source store.
- pub fn new(loader: Rc<dyn Loader>) -> Self {
+ pub fn new(loader: Arc<dyn Loader>) -> Self {
Self {
loader,
files: HashMap::new(),
@@ -125,7 +125,7 @@ pub struct SourceFile {
path: PathBuf,
src: String,
lines: Vec<Line>,
- root: Rc<GreenNode>,
+ root: Arc<GreenNode>,
}
impl SourceFile {
@@ -148,7 +148,7 @@ impl SourceFile {
}
/// The root node of the file's untyped green tree.
- pub fn root(&self) -> &Rc<GreenNode> {
+ pub fn root(&self) -> &Arc<GreenNode> {
&self.root
}
diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs
index 03a496dd..a26384e1 100644
--- a/src/syntax/mod.rs
+++ b/src/syntax/mod.rs
@@ -7,7 +7,7 @@ mod span;
use std::fmt::{self, Debug, Display, Formatter};
use std::ops::Range;
-use std::rc::Rc;
+use std::sync::Arc;
pub use highlight::*;
pub use pretty::*;
@@ -24,7 +24,7 @@ use crate::util::EcoString;
#[derive(Clone, PartialEq)]
pub enum Green {
/// A reference-counted inner node.
- Node(Rc<GreenNode>),
+ Node(Arc<GreenNode>),
/// A terminal, owned token.
Token(GreenData),
}
@@ -76,7 +76,7 @@ impl Green {
pub fn convert(&mut self, kind: NodeKind) {
match self {
Self::Node(node) => {
- let node = Rc::make_mut(node);
+ let node = Arc::make_mut(node);
node.erroneous |= kind.is_error();
node.data.kind = kind;
}
@@ -187,12 +187,12 @@ impl GreenNode {
impl From<GreenNode> for Green {
fn from(node: GreenNode) -> Self {
- Rc::new(node).into()
+ Arc::new(node).into()
}
}
-impl From<Rc<GreenNode>> for Green {
- fn from(node: Rc<GreenNode>) -> Self {
+impl From<Arc<GreenNode>> for Green {
+ fn from(node: Arc<GreenNode>) -> Self {
Self::Node(node)
}
}
@@ -259,7 +259,7 @@ pub struct RedNode {
impl RedNode {
/// Create a new red node from a root [`GreenNode`].
- pub fn from_root(root: Rc<GreenNode>, id: SourceId) -> Self {
+ pub fn from_root(root: Arc<GreenNode>, id: SourceId) -> Self {
Self { id, offset: 0, green: root.into() }
}
@@ -611,9 +611,9 @@ pub enum NodeKind {
Emph,
/// An arbitrary number of backticks followed by inner contents, terminated
/// with the same number of backticks: `` `...` ``.
- Raw(Rc<RawNode>),
+ Raw(Arc<RawNode>),
/// Dollar signs surrounding inner contents.
- Math(Rc<MathNode>),
+ Math(Arc<MathNode>),
/// A section heading: `= Introduction`.
Heading,
/// An item in an unordered list: `- ...`.
diff --git a/src/util/eco_string.rs b/src/util/eco_string.rs
index 8cb83377..953508ce 100644
--- a/src/util/eco_string.rs
+++ b/src/util/eco_string.rs
@@ -3,9 +3,9 @@ use std::cmp::Ordering;
use std::fmt::{self, Debug, Display, Formatter, Write};
use std::hash::{Hash, Hasher};
use std::ops::{Add, AddAssign, Deref};
-use std::rc::Rc;
+use std::sync::Arc;
-use super::RcExt;
+use super::ArcExt;
/// Create a new [`EcoString`] from a format string.
macro_rules! format_eco {
@@ -27,13 +27,13 @@ pub struct EcoString(Repr);
#[derive(Clone)]
enum Repr {
Small { buf: [u8; LIMIT], len: u8 },
- Large(Rc<String>),
+ Large(Arc<String>),
}
/// The maximum number of bytes that can be stored inline.
///
/// The value is chosen such that an `EcoString` fits exactly into 16 bytes
-/// (which are needed anyway due to the `Rc`s alignment, at least on 64-bit
+/// (which are needed anyway due to the `Arc`s alignment, at least on 64-bit
/// platforms).
///
/// Must be at least 4 to hold any char.
@@ -50,7 +50,7 @@ impl EcoString {
if capacity <= LIMIT {
Self::new()
} else {
- Self(Repr::Large(Rc::new(String::with_capacity(capacity))))
+ Self(Repr::Large(Arc::new(String::with_capacity(capacity))))
}
}
@@ -66,7 +66,7 @@ impl EcoString {
buf[.. len].copy_from_slice(slice.as_bytes());
Repr::Small { buf, len: len as u8 }
} else {
- Repr::Large(Rc::new(s.into()))
+ Repr::Large(Arc::new(s.into()))
})
}
@@ -100,7 +100,7 @@ impl EcoString {
self.push_str(c.encode_utf8(&mut [0; 4]));
}
}
- Repr::Large(rc) => Rc::make_mut(rc).push(c),
+ Repr::Large(rc) => Arc::make_mut(rc).push(c),
}
}
@@ -117,10 +117,10 @@ impl EcoString {
let mut spilled = String::with_capacity(new);
spilled.push_str(self);
spilled.push_str(string);
- self.0 = Repr::Large(Rc::new(spilled));
+ self.0 = Repr::Large(Arc::new(spilled));
}
}
- Repr::Large(rc) => Rc::make_mut(rc).push_str(string),
+ Repr::Large(rc) => Arc::make_mut(rc).push_str(string),
}
}
@@ -132,7 +132,7 @@ impl EcoString {
*len -= c.len_utf8() as u8;
}
Repr::Large(rc) => {
- Rc::make_mut(rc).pop();
+ Arc::make_mut(rc).pop();
}
}
Some(c)
@@ -143,8 +143,8 @@ impl EcoString {
match &mut self.0 {
Repr::Small { len, .. } => *len = 0,
Repr::Large(rc) => {
- if Rc::strong_count(rc) == 1 {
- Rc::make_mut(rc).clear();
+ if Arc::strong_count(rc) == 1 {
+ Arc::make_mut(rc).clear();
} else {
*self = Self::new();
}
@@ -351,11 +351,17 @@ impl From<String> for EcoString {
}
}
+impl From<&EcoString> for String {
+ fn from(s: &EcoString) -> Self {
+ s.as_str().to_owned()
+ }
+}
+
impl From<EcoString> for String {
fn from(s: EcoString) -> Self {
match s.0 {
Repr::Small { .. } => s.as_str().to_owned(),
- Repr::Large(rc) => Rc::take(rc),
+ Repr::Large(rc) => Arc::take(rc),
}
}
}
diff --git a/src/util/mod.rs b/src/util/mod.rs
index 61e7131d..de37354e 100644
--- a/src/util/mod.rs
+++ b/src/util/mod.rs
@@ -11,7 +11,7 @@ use std::cell::RefMut;
use std::cmp::Ordering;
use std::ops::Range;
use std::path::{Component, Path, PathBuf};
-use std::rc::Rc;
+use std::sync::Arc;
/// Additional methods for strings.
pub trait StrExt {
@@ -62,18 +62,18 @@ impl<T> OptionExt<T> for Option<T> {
}
/// Additional methods for reference-counted pointers.
-pub trait RcExt<T> {
+pub trait ArcExt<T> {
/// Takes the inner value if there is exactly one strong reference and
/// clones it otherwise.
fn take(self) -> T;
}
-impl<T> RcExt<T> for Rc<T>
+impl<T> ArcExt<T> for Arc<T>
where
T: Clone,
{
fn take(self) -> T {
- match Rc::try_unwrap(self) {
+ match Arc::try_unwrap(self) {
Ok(v) => v,
Err(rc) => (*rc).clone(),
}