Switch from Rc to Arc

This commit is contained in:
Laurenz 2022-01-31 16:06:44 +01:00
parent fa57d86ed9
commit 20b1a38414
45 changed files with 222 additions and 218 deletions

View File

@ -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()
}
}

View File

@ -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));
}
}
}

View File

@ -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()
}
}

View File

@ -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 (),
)
}
}

View File

@ -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())
}

View File

@ -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.

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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
}

View File

@ -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(),

View File

@ -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(),

View File

@ -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)
}
}

View File

@ -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)),
}]
}

View File

@ -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
}

View File

@ -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),

View File

@ -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;

View File

@ -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

View File

@ -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 {

View File

@ -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.

View File

@ -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));
}

View File

@ -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

View File

@ -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;

View File

@ -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)))

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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());

View File

@ -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
}

View File

@ -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.

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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.

View File

@ -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;
}

View File

@ -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.

View File

@ -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

View File

@ -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,

View File

@ -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() {

View File

@ -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 {

View File

@ -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
}

View File

@ -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: `- ...`.

View File

@ -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),
}
}
}

View File

@ -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(),
}

View File

@ -3,7 +3,7 @@ use std::ffi::OsStr;
use std::fs;
use std::ops::Range;
use std::path::Path;
use std::rc::Rc;
use std::sync::Arc;
use tiny_skia as sk;
use walkdir::WalkDir;
@ -258,7 +258,7 @@ fn test_part(
line: usize,
debug: bool,
rng: &mut LinearShift,
) -> (bool, bool, Vec<Rc<Frame>>) {
) -> (bool, bool, Vec<Arc<Frame>>) {
let mut ok = true;
let id = ctx.sources.provide(src_path, src);
@ -483,7 +483,7 @@ fn test_incremental(
ctx: &mut Context,
i: usize,
tree: &RootNode,
frames: &[Rc<Frame>],
frames: &[Arc<Frame>],
) -> bool {
let mut ok = true;
@ -527,7 +527,7 @@ fn test_incremental(
}
/// Draw all frames into one image with padding in between.
fn render(ctx: &mut Context, frames: &[Rc<Frame>]) -> sk::Pixmap {
fn render(ctx: &mut Context, frames: &[Arc<Frame>]) -> sk::Pixmap {
let pixel_per_pt = 2.0;
let pixmaps: Vec<_> = frames
.iter()