mirror of
https://github.com/typst/typst
synced 2025-05-13 20:46:23 +08:00
Switch from Rc
to Arc
This commit is contained in:
parent
fa57d86ed9
commit
20b1a38414
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 (),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -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())
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
20
src/font.rs
20
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
|
||||
}
|
||||
|
||||
|
10
src/frame.rs
10
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(),
|
||||
|
@ -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(),
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)),
|
||||
}]
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
16
src/lib.rs
16
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),
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)))
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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() {
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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: `- ...`.
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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(),
|
||||
}
|
||||
|
@ -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()
|
||||
|
Loading…
x
Reference in New Issue
Block a user