Move some things out of util
This commit is contained in:
parent
d7fea7077e
commit
7f0fcda376
@ -21,9 +21,11 @@ use serde::Deserialize;
|
||||
use serde_yaml as yaml;
|
||||
use typst::diag::{bail, StrResult};
|
||||
use typst::doc::Frame;
|
||||
use typst::eval::{CastInfo, Func, Library, Module, ParamInfo, Repr, Scope, Type, Value};
|
||||
use typst::eval::{
|
||||
CastInfo, Func, Library, Module, ParamInfo, Repr, Scope, Smart, Type, Value,
|
||||
};
|
||||
use typst::font::{Font, FontBook};
|
||||
use typst::geom::{Abs, Smart};
|
||||
use typst::geom::Abs;
|
||||
use typst_library::layout::{Margin, PageElem};
|
||||
|
||||
static DOCS_DIR: Dir<'_> = include_dir!("$CARGO_MANIFEST_DIR/../../docs");
|
||||
|
@ -5,6 +5,7 @@ use ecow::{eco_format, EcoString};
|
||||
use if_chain::if_chain;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use typst::doc::Frame;
|
||||
use typst::eval::repr::separated_list;
|
||||
use typst::eval::{
|
||||
format_str, AutoValue, CastInfo, Func, Library, NoneValue, Repr, Scope, Type, Value,
|
||||
};
|
||||
@ -13,7 +14,6 @@ use typst::model::Label;
|
||||
use typst::syntax::{
|
||||
ast, is_id_continue, is_id_start, is_ident, LinkedNode, Source, SyntaxKind,
|
||||
};
|
||||
use typst::util::separated_list;
|
||||
use typst::World;
|
||||
use unscanny::Scanner;
|
||||
|
||||
|
@ -3,11 +3,11 @@ use std::fmt::Write;
|
||||
use ecow::{eco_format, EcoString};
|
||||
use if_chain::if_chain;
|
||||
use typst::doc::Frame;
|
||||
use typst::eval::repr::{pretty_comma_list, separated_list};
|
||||
use typst::eval::{CapturesVisitor, CastInfo, Repr, Tracer, Value};
|
||||
use typst::geom::{round_2, Length, Numeric};
|
||||
use typst::syntax::ast;
|
||||
use typst::syntax::{LinkedNode, Source, SyntaxKind};
|
||||
use typst::util::{pretty_comma_list, separated_list};
|
||||
use typst::World;
|
||||
|
||||
use super::analyze::analyze_labels;
|
||||
|
@ -14,8 +14,8 @@ pub mod symbols;
|
||||
pub mod text;
|
||||
pub mod visualize;
|
||||
|
||||
use typst::eval::{Array, LangItems, Library, Module, Scope};
|
||||
use typst::geom::{Align, Color, Dir, Smart};
|
||||
use typst::eval::{Array, LangItems, Library, Module, Scope, Smart};
|
||||
use typst::geom::{Align, Color, Dir};
|
||||
use typst::model::{NativeElement, Styles};
|
||||
|
||||
use self::layout::LayoutRoot;
|
||||
|
@ -18,7 +18,7 @@ pub use typst::doc::*;
|
||||
#[doc(no_inline)]
|
||||
pub use typst::eval::{
|
||||
array, cast, dict, format_str, func, scope, ty, Args, Array, Bytes, Cast, Dict,
|
||||
FromValue, Func, IntoValue, Repr, Scope, Str, Symbol, Type, Value, Vm,
|
||||
FromValue, Func, IntoValue, Repr, Scope, Smart, Str, Symbol, Type, Value, Vm,
|
||||
};
|
||||
#[doc(no_inline)]
|
||||
pub use typst::geom::*;
|
||||
|
@ -1,7 +1,5 @@
|
||||
use std::ffi::OsStr;
|
||||
use std::path::Path;
|
||||
|
||||
use typst::geom::{self, Smart};
|
||||
use typst::image::{Image, ImageFormat, RasterFormat, VectorFormat};
|
||||
use typst::util::option_eq;
|
||||
|
||||
@ -135,7 +133,7 @@ impl Layout for ImageElem {
|
||||
let format = match self.format(styles) {
|
||||
Smart::Custom(v) => v,
|
||||
Smart::Auto => {
|
||||
let ext = Path::new(self.path().as_str())
|
||||
let ext = std::path::Path::new(self.path().as_str())
|
||||
.extension()
|
||||
.and_then(OsStr::to_str)
|
||||
.unwrap_or_default()
|
||||
@ -213,7 +211,7 @@ impl Layout for ImageElem {
|
||||
|
||||
// Create a clipping group if only part of the image should be visible.
|
||||
if fit == ImageFit::Cover && !target.fits(fitted) {
|
||||
frame.clip(geom::Path::rect(frame.size()));
|
||||
frame.clip(Path::rect(frame.size()));
|
||||
}
|
||||
|
||||
// Apply metadata.
|
||||
|
@ -1087,7 +1087,7 @@ fn create_repr_impl(element: &Elem) -> TokenStream {
|
||||
let fields = self.fields().into_iter()
|
||||
.map(|(name, value)| eco_format!("{}: {}", name, value.repr()))
|
||||
.collect::<Vec<_>>();
|
||||
::ecow::eco_format!(#repr_format, ::typst::util::pretty_array_like(&fields, false))
|
||||
::ecow::eco_format!(#repr_format, ::typst::eval::repr::pretty_array_like(&fields, false))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1108,7 +1108,7 @@ fn create_vtable_func(element: &Elem) -> TokenStream {
|
||||
if id == ::std::any::TypeId::of::<dyn #capability>() {
|
||||
let vtable = unsafe {
|
||||
let dangling = ::std::ptr::NonNull::<#ident>::dangling().as_ptr() as *const dyn #capability;
|
||||
::typst::util::fat::vtable(dangling)
|
||||
::typst::model::fat::vtable(dangling)
|
||||
};
|
||||
return Some(vtable);
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
use std::num::NonZeroUsize;
|
||||
|
||||
use pdf_writer::{Finish, Ref, TextStr};
|
||||
use typst::eval::item;
|
||||
use typst::geom::{Abs, Smart};
|
||||
use typst::eval::{item, Smart};
|
||||
use typst::geom::Abs;
|
||||
use typst::model::Content;
|
||||
|
||||
use crate::{AbsExt, PdfContext};
|
||||
|
@ -8,12 +8,11 @@ use std::sync::Arc;
|
||||
|
||||
use ecow::{eco_format, EcoString};
|
||||
|
||||
use crate::eval::{cast, dict, ty, Datetime, Dict, Repr, Value};
|
||||
use crate::eval::{cast, dict, ty, Datetime, Dict, Repr, Smart, Value};
|
||||
use crate::font::Font;
|
||||
use crate::geom::{
|
||||
self, styled_rect, Abs, Axes, Color, Corners, Dir, Em, FixedAlign, FixedStroke,
|
||||
Geometry, Length, Numeric, Paint, Path, Point, Rel, Shape, Sides, Size, Smart,
|
||||
Transform,
|
||||
Geometry, Length, Numeric, Paint, Path, Point, Rel, Shape, Sides, Size, Transform,
|
||||
};
|
||||
use crate::image::Image;
|
||||
use crate::model::{Content, Location, MetaElem, StyleChain};
|
||||
|
@ -2,10 +2,10 @@ use std::fmt::{self, Debug, Formatter};
|
||||
|
||||
use ecow::{eco_format, eco_vec, EcoString, EcoVec};
|
||||
|
||||
use super::repr::pretty_array_like;
|
||||
use super::{func, scope, ty, Array, Dict, FromValue, IntoValue, Repr, Str, Value};
|
||||
use crate::diag::{bail, At, SourceDiagnostic, SourceResult};
|
||||
use crate::syntax::{Span, Spanned};
|
||||
use crate::util::pretty_array_like;
|
||||
|
||||
/// Captured arguments to a function.
|
||||
///
|
||||
|
@ -7,6 +7,7 @@ use ecow::{eco_format, EcoString, EcoVec};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use super::repr::pretty_array_like;
|
||||
use super::{
|
||||
cast, func, ops, scope, ty, Args, Bytes, CastInfo, FromValue, Func, IntoValue,
|
||||
Reflect, Repr, Value, Version, Vm,
|
||||
@ -14,7 +15,6 @@ use super::{
|
||||
use crate::diag::{At, SourceResult, StrResult};
|
||||
use crate::eval::ops::{add, mul};
|
||||
use crate::syntax::Span;
|
||||
use crate::util::pretty_array_like;
|
||||
|
||||
/// Create a new [`Array`] from values.
|
||||
#[macro_export]
|
||||
|
@ -3,6 +3,7 @@ use std::fmt::Debug;
|
||||
|
||||
use super::{ty, CastInfo, FromValue, IntoValue, Reflect, Repr, Type, Value};
|
||||
use crate::diag::StrResult;
|
||||
use crate::model::{Fold, Resolve, StyleChain};
|
||||
|
||||
/// A value that indicates a smart default.
|
||||
///
|
||||
@ -50,3 +51,182 @@ impl Repr for AutoValue {
|
||||
"auto".into()
|
||||
}
|
||||
}
|
||||
|
||||
/// A value that can be automatically determined.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub enum Smart<T> {
|
||||
/// The value should be determined smartly based on the circumstances.
|
||||
Auto,
|
||||
/// A specific value.
|
||||
Custom(T),
|
||||
}
|
||||
|
||||
impl<T> Smart<T> {
|
||||
/// Whether the value is `Auto`.
|
||||
pub fn is_auto(&self) -> bool {
|
||||
matches!(self, Self::Auto)
|
||||
}
|
||||
|
||||
/// Whether this holds a custom value.
|
||||
pub fn is_custom(&self) -> bool {
|
||||
matches!(self, Self::Custom(_))
|
||||
}
|
||||
|
||||
/// Returns a `Smart<&T>` borrowing the inner `T`.
|
||||
pub fn as_ref(&self) -> Smart<&T> {
|
||||
match self {
|
||||
Smart::Auto => Smart::Auto,
|
||||
Smart::Custom(v) => Smart::Custom(v),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference the contained custom value.
|
||||
/// If the value is [`Smart::Auto`], `None` is returned.
|
||||
pub fn as_custom(self) -> Option<T> {
|
||||
match self {
|
||||
Self::Auto => None,
|
||||
Self::Custom(x) => Some(x),
|
||||
}
|
||||
}
|
||||
|
||||
/// Map the contained custom value with `f`.
|
||||
pub fn map<F, U>(self, f: F) -> Smart<U>
|
||||
where
|
||||
F: FnOnce(T) -> U,
|
||||
{
|
||||
match self {
|
||||
Self::Auto => Smart::Auto,
|
||||
Self::Custom(x) => Smart::Custom(f(x)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Map the contained custom value with `f` if it contains a custom value,
|
||||
/// otherwise returns `default`.
|
||||
pub fn map_or<F, U>(self, default: U, f: F) -> U
|
||||
where
|
||||
F: FnOnce(T) -> U,
|
||||
{
|
||||
match self {
|
||||
Self::Auto => default,
|
||||
Self::Custom(x) => f(x),
|
||||
}
|
||||
}
|
||||
|
||||
/// Keeps `self` if it contains a custom value, otherwise returns `other`.
|
||||
pub fn or(self, other: Smart<T>) -> Self {
|
||||
match self {
|
||||
Self::Custom(x) => Self::Custom(x),
|
||||
Self::Auto => other,
|
||||
}
|
||||
}
|
||||
|
||||
/// Retusn `Auto` if `self` is `Auto`, otherwise calls the provided function onthe contained
|
||||
/// value and returns the result.
|
||||
pub fn and_then<F, U>(self, f: F) -> Smart<U>
|
||||
where
|
||||
F: FnOnce(T) -> Smart<U>,
|
||||
{
|
||||
match self {
|
||||
Smart::Auto => Smart::Auto,
|
||||
Smart::Custom(x) => f(x),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the contained custom value or a provided default value.
|
||||
pub fn unwrap_or(self, default: T) -> T {
|
||||
match self {
|
||||
Self::Auto => default,
|
||||
Self::Custom(x) => x,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the contained custom value or computes a default value.
|
||||
pub fn unwrap_or_else<F>(self, f: F) -> T
|
||||
where
|
||||
F: FnOnce() -> T,
|
||||
{
|
||||
match self {
|
||||
Self::Auto => f(),
|
||||
Self::Custom(x) => x,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the contained custom value or the default value.
|
||||
pub fn unwrap_or_default(self) -> T
|
||||
where
|
||||
T: Default,
|
||||
{
|
||||
// we want to do this; the Clippy lint is not type-aware
|
||||
#[allow(clippy::unwrap_or_default)]
|
||||
self.unwrap_or_else(T::default)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Smart<Smart<T>> {
|
||||
/// Removes a single level of nesting, returns `Auto` if the inner or outer value is `Auto`.
|
||||
pub fn flatten(self) -> Smart<T> {
|
||||
match self {
|
||||
Smart::Custom(Smart::Auto) | Smart::Auto => Smart::Auto,
|
||||
Smart::Custom(Smart::Custom(v)) => Smart::Custom(v),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Default for Smart<T> {
|
||||
fn default() -> Self {
|
||||
Self::Auto
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Reflect> Reflect for Smart<T> {
|
||||
fn input() -> CastInfo {
|
||||
T::input() + AutoValue::input()
|
||||
}
|
||||
|
||||
fn output() -> CastInfo {
|
||||
T::output() + AutoValue::output()
|
||||
}
|
||||
|
||||
fn castable(value: &Value) -> bool {
|
||||
AutoValue::castable(value) || T::castable(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: IntoValue> IntoValue for Smart<T> {
|
||||
fn into_value(self) -> Value {
|
||||
match self {
|
||||
Smart::Custom(v) => v.into_value(),
|
||||
Smart::Auto => Value::Auto,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: FromValue> FromValue for Smart<T> {
|
||||
fn from_value(value: Value) -> StrResult<Self> {
|
||||
match value {
|
||||
Value::Auto => Ok(Self::Auto),
|
||||
v if T::castable(&v) => Ok(Self::Custom(T::from_value(v)?)),
|
||||
_ => Err(Self::error(&value)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Resolve> Resolve for Smart<T> {
|
||||
type Output = Smart<T::Output>;
|
||||
|
||||
fn resolve(self, styles: StyleChain) -> Self::Output {
|
||||
self.map(|v| v.resolve(styles))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Fold for Smart<T>
|
||||
where
|
||||
T: Fold,
|
||||
T::Output: Default,
|
||||
{
|
||||
type Output = Smart<T::Output>;
|
||||
|
||||
fn fold(self, outer: Self::Output) -> Self::Output {
|
||||
self.map(|inner| inner.fold(outer.unwrap_or_default()))
|
||||
}
|
||||
}
|
||||
|
@ -10,10 +10,10 @@ use ecow::{eco_format, EcoString};
|
||||
use smallvec::SmallVec;
|
||||
use unicode_math_class::MathClass;
|
||||
|
||||
use super::repr::separated_list;
|
||||
use super::{Repr, Type, Value};
|
||||
use crate::diag::{At, SourceResult, StrResult};
|
||||
use crate::syntax::{Span, Spanned};
|
||||
use crate::util::separated_list;
|
||||
|
||||
/// Determine details of a type.
|
||||
///
|
||||
|
@ -9,10 +9,9 @@ use time::error::{Format, InvalidFormatDescription};
|
||||
use time::macros::format_description;
|
||||
use time::{format_description, Month, PrimitiveDateTime};
|
||||
|
||||
use super::{cast, func, scope, ty, Dict, Duration, Repr, Str, Value, Vm};
|
||||
use super::repr::pretty_array_like;
|
||||
use super::{cast, func, scope, ty, Dict, Duration, Repr, Smart, Str, Value, Vm};
|
||||
use crate::diag::{bail, StrResult};
|
||||
use crate::geom::Smart;
|
||||
use crate::util::pretty_array_like;
|
||||
use crate::World;
|
||||
|
||||
/// Represents a date, a time, or a combination of both.
|
||||
|
@ -7,10 +7,11 @@ use ecow::{eco_format, EcoString};
|
||||
use indexmap::IndexMap;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
use super::repr::{pretty_array_like, separated_list};
|
||||
use super::{array, func, scope, ty, Array, Repr, Str, Value};
|
||||
use crate::diag::StrResult;
|
||||
use crate::syntax::is_ident;
|
||||
use crate::util::{pretty_array_like, separated_list, ArcExt};
|
||||
use crate::util::ArcExt;
|
||||
|
||||
/// Create a new [`Dict`] from key-value pairs.
|
||||
#[macro_export]
|
||||
|
@ -4,8 +4,8 @@ use std::fmt::Debug;
|
||||
use std::ops::{Add, Div, Mul, Neg, Sub};
|
||||
use time::ext::NumericalDuration;
|
||||
|
||||
use super::repr::pretty_array_like;
|
||||
use super::{func, scope, ty, Repr};
|
||||
use crate::util::pretty_array_like;
|
||||
|
||||
/// Represents a positive or negative span of time.
|
||||
#[ty(scope)]
|
||||
|
@ -2,9 +2,9 @@ use std::num::ParseFloatError;
|
||||
|
||||
use ecow::{eco_format, EcoString};
|
||||
|
||||
use super::repr::{format_float, MINUS_SIGN};
|
||||
use super::{cast, func, scope, ty, Repr, Str};
|
||||
use crate::geom::Ratio;
|
||||
use crate::util::fmt::{format_float, MINUS_SIGN};
|
||||
|
||||
/// A floating-point number.
|
||||
///
|
||||
|
@ -1,8 +1,8 @@
|
||||
use std::num::{NonZeroI64, NonZeroIsize, NonZeroU64, NonZeroUsize, ParseIntError};
|
||||
|
||||
use crate::util::fmt::{format_int_with_base, MINUS_SIGN};
|
||||
use ecow::{eco_format, EcoString};
|
||||
|
||||
use super::repr::{format_int_with_base, MINUS_SIGN};
|
||||
use super::{cast, func, scope, ty, Repr, Str, Value};
|
||||
|
||||
/// A whole number.
|
||||
|
@ -27,6 +27,7 @@ mod module;
|
||||
mod none;
|
||||
pub mod ops;
|
||||
mod plugin;
|
||||
pub mod repr;
|
||||
mod scope;
|
||||
mod symbol;
|
||||
mod tracer;
|
||||
@ -43,7 +44,7 @@ pub use {
|
||||
|
||||
pub use self::args::{Arg, Args};
|
||||
pub use self::array::{array, Array};
|
||||
pub use self::auto::AutoValue;
|
||||
pub use self::auto::{AutoValue, Smart};
|
||||
pub use self::bytes::Bytes;
|
||||
pub use self::cast::{
|
||||
cast, Cast, CastInfo, Container, FromValue, IntoResult, IntoValue, Never, Reflect,
|
||||
@ -60,12 +61,13 @@ pub use self::methods::mutable_methods_on;
|
||||
pub use self::module::Module;
|
||||
pub use self::none::NoneValue;
|
||||
pub use self::plugin::Plugin;
|
||||
pub use self::repr::Repr;
|
||||
pub use self::scope::{NativeScope, Scope, Scopes};
|
||||
pub use self::str::{format_str, Regex, Str};
|
||||
pub use self::symbol::{symbols, Symbol};
|
||||
pub use self::tracer::Tracer;
|
||||
pub use self::ty::{scope, ty, NativeType, NativeTypeData, Type};
|
||||
pub use self::value::{Dynamic, Repr, Value};
|
||||
pub use self::value::{Dynamic, Value};
|
||||
pub use self::version::Version;
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
@ -4,10 +4,9 @@ use std::cmp::Ordering;
|
||||
|
||||
use ecow::eco_format;
|
||||
|
||||
use super::{format_str, IntoValue, Regex, Repr, Value};
|
||||
use super::{format_str, item, IntoValue, Regex, Repr, Smart, Value};
|
||||
use crate::diag::{bail, StrResult};
|
||||
use crate::eval::item;
|
||||
use crate::geom::{Align, Length, Numeric, Rel, Smart, Stroke};
|
||||
use crate::geom::{Align, Length, Numeric, Rel, Stroke};
|
||||
use Value::*;
|
||||
|
||||
/// Bail with a type mismatch error.
|
||||
|
@ -2,6 +2,12 @@ use ecow::{eco_format, EcoString};
|
||||
|
||||
pub const MINUS_SIGN: &str = "\u{2212}";
|
||||
|
||||
/// A trait that defines the `repr` of a Typst value.
|
||||
pub trait Repr {
|
||||
/// Return the debug representation of the value.
|
||||
fn repr(&self) -> EcoString;
|
||||
}
|
||||
|
||||
/// Format an integer in a base.
|
||||
pub fn format_int_with_base(mut n: i64, base: i64) -> EcoString {
|
||||
if n == 0 {
|
@ -7,6 +7,7 @@ use ecow::EcoString;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
use super::repr::{format_float, format_int_with_base};
|
||||
use super::{
|
||||
cast, dict, func, scope, ty, Args, Array, Bytes, Dict, Func, IntoValue, Repr, Type,
|
||||
Value, Version, Vm,
|
||||
@ -15,7 +16,6 @@ use crate::diag::{bail, At, SourceResult, StrResult};
|
||||
use crate::geom::Align;
|
||||
use crate::model::Label;
|
||||
use crate::syntax::{Span, Spanned};
|
||||
use crate::util::fmt::{format_float, format_int_with_base};
|
||||
|
||||
/// Create a new [`Str`] from a format string.
|
||||
#[macro_export]
|
||||
|
@ -11,17 +11,17 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use siphasher::sip128::{Hasher128, SipHasher13};
|
||||
use typst::eval::Duration;
|
||||
|
||||
use super::repr::{format_float, format_int_with_base};
|
||||
use super::{
|
||||
fields, ops, Args, Array, AutoValue, Bytes, CastInfo, Content, Dict, FromValue, Func,
|
||||
IntoValue, Module, NativeType, NoneValue, Plugin, Reflect, Scope, Str, Symbol, Type,
|
||||
Version,
|
||||
IntoValue, Module, NativeType, NoneValue, Plugin, Reflect, Repr, Scope, Str, Symbol,
|
||||
Type, Version,
|
||||
};
|
||||
use crate::diag::StrResult;
|
||||
use crate::eval::{item, Datetime};
|
||||
use crate::geom::{Abs, Angle, Color, Em, Fr, Gradient, Length, Ratio, Rel};
|
||||
use crate::model::{Label, Styles};
|
||||
use crate::syntax::{ast, Span};
|
||||
use crate::util::fmt::{format_float, format_int_with_base};
|
||||
|
||||
/// A computational value.
|
||||
#[derive(Debug, Default, Clone)]
|
||||
@ -489,12 +489,6 @@ impl PartialEq for Dynamic {
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait that defines the `repr` of a Typst value.
|
||||
pub trait Repr {
|
||||
/// Return the debug representation of the value.
|
||||
fn repr(&self) -> EcoString;
|
||||
}
|
||||
|
||||
trait Bounds: Debug + Repr + Sync + Send + 'static {
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
fn dyn_eq(&self, other: &Dynamic) -> bool;
|
||||
|
@ -5,9 +5,9 @@ use std::iter::repeat;
|
||||
|
||||
use ecow::{eco_format, EcoString, EcoVec};
|
||||
|
||||
use super::repr::pretty_array_like;
|
||||
use super::{cast, func, scope, ty, Repr};
|
||||
use crate::diag::{bail, error, StrResult};
|
||||
use crate::util::pretty_array_like;
|
||||
|
||||
/// A version with an arbitrary number of components.
|
||||
///
|
||||
|
@ -24,7 +24,6 @@ mod scalar;
|
||||
mod shape;
|
||||
mod sides;
|
||||
mod size;
|
||||
mod smart;
|
||||
mod stroke;
|
||||
mod transform;
|
||||
|
||||
@ -52,7 +51,6 @@ pub use self::scalar::Scalar;
|
||||
pub use self::shape::{Geometry, Shape};
|
||||
pub use self::sides::{Side, Sides};
|
||||
pub use self::size::Size;
|
||||
pub use self::smart::Smart;
|
||||
pub use self::stroke::{DashLength, DashPattern, FixedStroke, LineCap, LineJoin, Stroke};
|
||||
pub use self::transform::Transform;
|
||||
|
||||
@ -66,9 +64,9 @@ use std::ops::*;
|
||||
use ecow::{eco_format, EcoString};
|
||||
|
||||
use crate::diag::{bail, StrResult};
|
||||
use crate::eval::{array, cast, func, scope, ty, Array, Dict, Repr, Value};
|
||||
use crate::eval::repr::format_float;
|
||||
use crate::eval::{array, cast, func, scope, ty, Array, Dict, Repr, Smart, Value};
|
||||
use crate::model::{Fold, Resolve, StyleChain};
|
||||
use crate::util::fmt::format_float;
|
||||
|
||||
/// Generic access to a structure's components.
|
||||
pub trait Get<Index> {
|
||||
|
@ -1,181 +0,0 @@
|
||||
use super::*;
|
||||
use crate::eval::{AutoValue, CastInfo, FromValue, IntoValue, Reflect};
|
||||
|
||||
/// A value that can be automatically determined.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub enum Smart<T> {
|
||||
/// The value should be determined smartly based on the circumstances.
|
||||
Auto,
|
||||
/// A specific value.
|
||||
Custom(T),
|
||||
}
|
||||
|
||||
impl<T> Smart<T> {
|
||||
/// Whether the value is `Auto`.
|
||||
pub fn is_auto(&self) -> bool {
|
||||
matches!(self, Self::Auto)
|
||||
}
|
||||
|
||||
/// Whether this holds a custom value.
|
||||
pub fn is_custom(&self) -> bool {
|
||||
matches!(self, Self::Custom(_))
|
||||
}
|
||||
|
||||
/// Returns a `Smart<&T>` borrowing the inner `T`.
|
||||
pub fn as_ref(&self) -> Smart<&T> {
|
||||
match self {
|
||||
Smart::Auto => Smart::Auto,
|
||||
Smart::Custom(v) => Smart::Custom(v),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference the contained custom value.
|
||||
/// If the value is [`Smart::Auto`], `None` is returned.
|
||||
pub fn as_custom(self) -> Option<T> {
|
||||
match self {
|
||||
Self::Auto => None,
|
||||
Self::Custom(x) => Some(x),
|
||||
}
|
||||
}
|
||||
|
||||
/// Map the contained custom value with `f`.
|
||||
pub fn map<F, U>(self, f: F) -> Smart<U>
|
||||
where
|
||||
F: FnOnce(T) -> U,
|
||||
{
|
||||
match self {
|
||||
Self::Auto => Smart::Auto,
|
||||
Self::Custom(x) => Smart::Custom(f(x)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Map the contained custom value with `f` if it contains a custom value,
|
||||
/// otherwise returns `default`.
|
||||
pub fn map_or<F, U>(self, default: U, f: F) -> U
|
||||
where
|
||||
F: FnOnce(T) -> U,
|
||||
{
|
||||
match self {
|
||||
Self::Auto => default,
|
||||
Self::Custom(x) => f(x),
|
||||
}
|
||||
}
|
||||
|
||||
/// Keeps `self` if it contains a custom value, otherwise returns `other`.
|
||||
pub fn or(self, other: Smart<T>) -> Self {
|
||||
match self {
|
||||
Self::Custom(x) => Self::Custom(x),
|
||||
Self::Auto => other,
|
||||
}
|
||||
}
|
||||
|
||||
/// Retusn `Auto` if `self` is `Auto`, otherwise calls the provided function onthe contained
|
||||
/// value and returns the result.
|
||||
pub fn and_then<F, U>(self, f: F) -> Smart<U>
|
||||
where
|
||||
F: FnOnce(T) -> Smart<U>,
|
||||
{
|
||||
match self {
|
||||
Smart::Auto => Smart::Auto,
|
||||
Smart::Custom(x) => f(x),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the contained custom value or a provided default value.
|
||||
pub fn unwrap_or(self, default: T) -> T {
|
||||
match self {
|
||||
Self::Auto => default,
|
||||
Self::Custom(x) => x,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the contained custom value or computes a default value.
|
||||
pub fn unwrap_or_else<F>(self, f: F) -> T
|
||||
where
|
||||
F: FnOnce() -> T,
|
||||
{
|
||||
match self {
|
||||
Self::Auto => f(),
|
||||
Self::Custom(x) => x,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the contained custom value or the default value.
|
||||
pub fn unwrap_or_default(self) -> T
|
||||
where
|
||||
T: Default,
|
||||
{
|
||||
// we want to do this; the Clippy lint is not type-aware
|
||||
#[allow(clippy::unwrap_or_default)]
|
||||
self.unwrap_or_else(T::default)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Smart<Smart<T>> {
|
||||
/// Removes a single level of nesting, returns `Auto` if the inner or outer value is `Auto`.
|
||||
pub fn flatten(self) -> Smart<T> {
|
||||
match self {
|
||||
Smart::Custom(Smart::Auto) | Smart::Auto => Smart::Auto,
|
||||
Smart::Custom(Smart::Custom(v)) => Smart::Custom(v),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Default for Smart<T> {
|
||||
fn default() -> Self {
|
||||
Self::Auto
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Reflect> Reflect for Smart<T> {
|
||||
fn input() -> CastInfo {
|
||||
T::input() + AutoValue::input()
|
||||
}
|
||||
|
||||
fn output() -> CastInfo {
|
||||
T::output() + AutoValue::output()
|
||||
}
|
||||
|
||||
fn castable(value: &Value) -> bool {
|
||||
AutoValue::castable(value) || T::castable(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: IntoValue> IntoValue for Smart<T> {
|
||||
fn into_value(self) -> Value {
|
||||
match self {
|
||||
Smart::Custom(v) => v.into_value(),
|
||||
Smart::Auto => Value::Auto,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: FromValue> FromValue for Smart<T> {
|
||||
fn from_value(value: Value) -> StrResult<Self> {
|
||||
match value {
|
||||
Value::Auto => Ok(Self::Auto),
|
||||
v if T::castable(&v) => Ok(Self::Custom(T::from_value(v)?)),
|
||||
_ => Err(Self::error(&value)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Resolve> Resolve for Smart<T> {
|
||||
type Output = Smart<T::Output>;
|
||||
|
||||
fn resolve(self, styles: StyleChain) -> Self::Output {
|
||||
self.map(|v| v.resolve(styles))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Fold for Smart<T>
|
||||
where
|
||||
T: Fold,
|
||||
T::Output: Default,
|
||||
{
|
||||
type Output = Smart<T::Output>;
|
||||
|
||||
fn fold(self, outer: Self::Output) -> Self::Output {
|
||||
self.map(|inner| inner.fold(outer.unwrap_or_default()))
|
||||
}
|
||||
}
|
@ -16,9 +16,9 @@ use super::{
|
||||
};
|
||||
use crate::diag::{SourceResult, StrResult};
|
||||
use crate::doc::Meta;
|
||||
use crate::eval::repr::pretty_array_like;
|
||||
use crate::eval::{func, scope, ty, Dict, FromValue, IntoValue, Repr, Str, Value, Vm};
|
||||
use crate::syntax::Span;
|
||||
use crate::util::pretty_array_like;
|
||||
|
||||
/// A piece of document content.
|
||||
///
|
||||
@ -256,7 +256,7 @@ impl Content {
|
||||
{
|
||||
let vtable = self.elem().vtable()(TypeId::of::<C>())?;
|
||||
let data = Arc::as_ptr(&self.0) as *const ();
|
||||
Some(unsafe { &*crate::util::fat::from_raw_parts(data, vtable) })
|
||||
Some(unsafe { &*fat::from_raw_parts(data, vtable) })
|
||||
}
|
||||
|
||||
/// Cast to a mutable trait object if the contained element has the given
|
||||
@ -268,7 +268,7 @@ impl Content {
|
||||
// Safety: We ensure the element is not shared.
|
||||
let vtable = self.elem().vtable()(TypeId::of::<C>())?;
|
||||
let data = self.make_mut() as *mut dyn NativeElement as *mut ();
|
||||
Some(unsafe { &mut *crate::util::fat::from_raw_parts_mut(data, vtable) })
|
||||
Some(unsafe { &mut *fat::from_raw_parts_mut(data, vtable) })
|
||||
}
|
||||
|
||||
/// Whether the content is a sequence.
|
||||
@ -749,3 +749,66 @@ fn missing_field_no_default(field: &str) -> EcoString {
|
||||
field.repr()
|
||||
)
|
||||
}
|
||||
|
||||
/// Fat pointer handling.
|
||||
///
|
||||
/// This assumes the memory representation of fat pointers. Although it is not
|
||||
/// guaranteed by Rust, it's improbable that it will change. Still, when the
|
||||
/// pointer metadata APIs are stable, we should definitely move to them:
|
||||
/// <https://github.com/rust-lang/rust/issues/81513>
|
||||
pub mod fat {
|
||||
use std::alloc::Layout;
|
||||
use std::mem;
|
||||
|
||||
/// Create a fat pointer from a data address and a vtable address.
|
||||
///
|
||||
/// # Safety
|
||||
/// Must only be called when `T` is a `dyn Trait`. The data address must point
|
||||
/// to a value whose type implements the trait of `T` and the `vtable` must have
|
||||
/// been extracted with [`vtable`].
|
||||
#[track_caller]
|
||||
pub unsafe fn from_raw_parts<T: ?Sized>(
|
||||
data: *const (),
|
||||
vtable: *const (),
|
||||
) -> *const T {
|
||||
let fat = FatPointer { data, vtable };
|
||||
debug_assert_eq!(Layout::new::<*const T>(), Layout::new::<FatPointer>());
|
||||
mem::transmute_copy::<FatPointer, *const T>(&fat)
|
||||
}
|
||||
|
||||
/// Create a mutable fat pointer from a data address and a vtable address.
|
||||
///
|
||||
/// # Safety
|
||||
/// Must only be called when `T` is a `dyn Trait`. The data address must point
|
||||
/// to a value whose type implements the trait of `T` and the `vtable` must have
|
||||
/// been extracted with [`vtable`].
|
||||
#[track_caller]
|
||||
pub unsafe fn from_raw_parts_mut<T: ?Sized>(
|
||||
data: *mut (),
|
||||
vtable: *const (),
|
||||
) -> *mut T {
|
||||
let fat = FatPointer { data, vtable };
|
||||
debug_assert_eq!(Layout::new::<*mut T>(), Layout::new::<FatPointer>());
|
||||
mem::transmute_copy::<FatPointer, *mut T>(&fat)
|
||||
}
|
||||
|
||||
/// Extract the address to a trait object's vtable.
|
||||
///
|
||||
/// # Safety
|
||||
/// Must only be called when `T` is a `dyn Trait`.
|
||||
#[track_caller]
|
||||
pub unsafe fn vtable<T: ?Sized>(ptr: *const T) -> *const () {
|
||||
debug_assert_eq!(Layout::new::<*const T>(), Layout::new::<FatPointer>());
|
||||
mem::transmute_copy::<*const T, FatPointer>(&ptr).vtable
|
||||
}
|
||||
|
||||
/// The memory representation of a trait object pointer.
|
||||
///
|
||||
/// Although this is not guaranteed by Rust, it's improbable that it will
|
||||
/// change.
|
||||
#[repr(C)]
|
||||
struct FatPointer {
|
||||
data: *const (),
|
||||
vtable: *const (),
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ use ecow::EcoVec;
|
||||
pub use typst_macros::elem;
|
||||
|
||||
pub use self::block::{Block, Blockable};
|
||||
pub use self::content::{Content, MetaElem, PlainText};
|
||||
pub use self::content::{fat, Content, MetaElem, PlainText};
|
||||
pub use self::element::{
|
||||
Construct, Element, ElementFields, LocalName, NativeElement, NativeElementData, Set,
|
||||
};
|
||||
|
@ -7,11 +7,11 @@ use smallvec::SmallVec;
|
||||
|
||||
use super::{Content, Element, Label, Locatable, Location};
|
||||
use crate::diag::{bail, StrResult};
|
||||
use crate::eval::repr::pretty_array_like;
|
||||
use crate::eval::{
|
||||
cast, func, item, scope, ty, CastInfo, Dict, FromValue, Func, Reflect, Regex, Repr,
|
||||
Str, Symbol, Type, Value,
|
||||
};
|
||||
use crate::util::pretty_array_like;
|
||||
|
||||
/// A helper macro to create a field selector used in [`Selector::Elem`]
|
||||
///
|
||||
|
@ -1,55 +0,0 @@
|
||||
//! Fat pointer handling.
|
||||
//!
|
||||
//! This assumes the memory representation of fat pointers. Although it is not
|
||||
//! guaranteed by Rust, it's improbable that it will change. Still, when the
|
||||
//! pointer metadata APIs are stable, we should definitely move to them:
|
||||
//! <https://github.com/rust-lang/rust/issues/81513>
|
||||
|
||||
use std::alloc::Layout;
|
||||
use std::mem;
|
||||
|
||||
/// Create a fat pointer from a data address and a vtable address.
|
||||
///
|
||||
/// # Safety
|
||||
/// Must only be called when `T` is a `dyn Trait`. The data address must point
|
||||
/// to a value whose type implements the trait of `T` and the `vtable` must have
|
||||
/// been extracted with [`vtable`].
|
||||
#[track_caller]
|
||||
pub unsafe fn from_raw_parts<T: ?Sized>(data: *const (), vtable: *const ()) -> *const T {
|
||||
let fat = FatPointer { data, vtable };
|
||||
debug_assert_eq!(Layout::new::<*const T>(), Layout::new::<FatPointer>());
|
||||
mem::transmute_copy::<FatPointer, *const T>(&fat)
|
||||
}
|
||||
|
||||
/// Create a mutable fat pointer from a data address and a vtable address.
|
||||
///
|
||||
/// # Safety
|
||||
/// Must only be called when `T` is a `dyn Trait`. The data address must point
|
||||
/// to a value whose type implements the trait of `T` and the `vtable` must have
|
||||
/// been extracted with [`vtable`].
|
||||
#[track_caller]
|
||||
pub unsafe fn from_raw_parts_mut<T: ?Sized>(data: *mut (), vtable: *const ()) -> *mut T {
|
||||
let fat = FatPointer { data, vtable };
|
||||
debug_assert_eq!(Layout::new::<*mut T>(), Layout::new::<FatPointer>());
|
||||
mem::transmute_copy::<FatPointer, *mut T>(&fat)
|
||||
}
|
||||
|
||||
/// Extract the address to a trait object's vtable.
|
||||
///
|
||||
/// # Safety
|
||||
/// Must only be called when `T` is a `dyn Trait`.
|
||||
#[track_caller]
|
||||
pub unsafe fn vtable<T: ?Sized>(ptr: *const T) -> *const () {
|
||||
debug_assert_eq!(Layout::new::<*const T>(), Layout::new::<FatPointer>());
|
||||
mem::transmute_copy::<*const T, FatPointer>(&ptr).vtable
|
||||
}
|
||||
|
||||
/// The memory representation of a trait object pointer.
|
||||
///
|
||||
/// Although this is not guaranteed by Rust, it's improbable that it will
|
||||
/// change.
|
||||
#[repr(C)]
|
||||
struct FatPointer {
|
||||
data: *const (),
|
||||
vtable: *const (),
|
||||
}
|
@ -1,11 +1,8 @@
|
||||
//! Utilities.
|
||||
|
||||
pub mod fat;
|
||||
pub mod fmt;
|
||||
mod str;
|
||||
mod pico;
|
||||
|
||||
pub use self::fmt::{pretty_array_like, pretty_comma_list, separated_list};
|
||||
pub use self::str::PicoStr;
|
||||
pub use self::pico::PicoStr;
|
||||
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::hash::Hash;
|
||||
|
@ -23,10 +23,10 @@ use walkdir::WalkDir;
|
||||
use typst::diag::{bail, FileError, FileResult, Severity, StrResult};
|
||||
use typst::doc::{Document, Frame, FrameItem, Meta};
|
||||
use typst::eval::{
|
||||
eco_format, func, Bytes, Datetime, Library, NoneValue, Repr, Tracer, Value,
|
||||
eco_format, func, Bytes, Datetime, Library, NoneValue, Repr, Smart, Tracer, Value,
|
||||
};
|
||||
use typst::font::{Font, FontBook};
|
||||
use typst::geom::{Abs, Color, Smart, Transform};
|
||||
use typst::geom::{Abs, Color, Transform};
|
||||
use typst::syntax::{FileId, PackageVersion, Source, SyntaxNode, VirtualPath};
|
||||
use typst::{World, WorldExt};
|
||||
use typst_library::layout::{Margin, PageElem};
|
||||
|
Loading…
x
Reference in New Issue
Block a user