mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
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 serde_yaml as yaml;
|
||||||
use typst::diag::{bail, StrResult};
|
use typst::diag::{bail, StrResult};
|
||||||
use typst::doc::Frame;
|
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::font::{Font, FontBook};
|
||||||
use typst::geom::{Abs, Smart};
|
use typst::geom::Abs;
|
||||||
use typst_library::layout::{Margin, PageElem};
|
use typst_library::layout::{Margin, PageElem};
|
||||||
|
|
||||||
static DOCS_DIR: Dir<'_> = include_dir!("$CARGO_MANIFEST_DIR/../../docs");
|
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 if_chain::if_chain;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use typst::doc::Frame;
|
use typst::doc::Frame;
|
||||||
|
use typst::eval::repr::separated_list;
|
||||||
use typst::eval::{
|
use typst::eval::{
|
||||||
format_str, AutoValue, CastInfo, Func, Library, NoneValue, Repr, Scope, Type, Value,
|
format_str, AutoValue, CastInfo, Func, Library, NoneValue, Repr, Scope, Type, Value,
|
||||||
};
|
};
|
||||||
@ -13,7 +14,6 @@ use typst::model::Label;
|
|||||||
use typst::syntax::{
|
use typst::syntax::{
|
||||||
ast, is_id_continue, is_id_start, is_ident, LinkedNode, Source, SyntaxKind,
|
ast, is_id_continue, is_id_start, is_ident, LinkedNode, Source, SyntaxKind,
|
||||||
};
|
};
|
||||||
use typst::util::separated_list;
|
|
||||||
use typst::World;
|
use typst::World;
|
||||||
use unscanny::Scanner;
|
use unscanny::Scanner;
|
||||||
|
|
||||||
|
@ -3,11 +3,11 @@ use std::fmt::Write;
|
|||||||
use ecow::{eco_format, EcoString};
|
use ecow::{eco_format, EcoString};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use typst::doc::Frame;
|
use typst::doc::Frame;
|
||||||
|
use typst::eval::repr::{pretty_comma_list, separated_list};
|
||||||
use typst::eval::{CapturesVisitor, CastInfo, Repr, Tracer, Value};
|
use typst::eval::{CapturesVisitor, CastInfo, Repr, Tracer, Value};
|
||||||
use typst::geom::{round_2, Length, Numeric};
|
use typst::geom::{round_2, Length, Numeric};
|
||||||
use typst::syntax::ast;
|
use typst::syntax::ast;
|
||||||
use typst::syntax::{LinkedNode, Source, SyntaxKind};
|
use typst::syntax::{LinkedNode, Source, SyntaxKind};
|
||||||
use typst::util::{pretty_comma_list, separated_list};
|
|
||||||
use typst::World;
|
use typst::World;
|
||||||
|
|
||||||
use super::analyze::analyze_labels;
|
use super::analyze::analyze_labels;
|
||||||
|
@ -14,8 +14,8 @@ pub mod symbols;
|
|||||||
pub mod text;
|
pub mod text;
|
||||||
pub mod visualize;
|
pub mod visualize;
|
||||||
|
|
||||||
use typst::eval::{Array, LangItems, Library, Module, Scope};
|
use typst::eval::{Array, LangItems, Library, Module, Scope, Smart};
|
||||||
use typst::geom::{Align, Color, Dir, Smart};
|
use typst::geom::{Align, Color, Dir};
|
||||||
use typst::model::{NativeElement, Styles};
|
use typst::model::{NativeElement, Styles};
|
||||||
|
|
||||||
use self::layout::LayoutRoot;
|
use self::layout::LayoutRoot;
|
||||||
|
@ -18,7 +18,7 @@ pub use typst::doc::*;
|
|||||||
#[doc(no_inline)]
|
#[doc(no_inline)]
|
||||||
pub use typst::eval::{
|
pub use typst::eval::{
|
||||||
array, cast, dict, format_str, func, scope, ty, Args, Array, Bytes, Cast, Dict,
|
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)]
|
#[doc(no_inline)]
|
||||||
pub use typst::geom::*;
|
pub use typst::geom::*;
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::path::Path;
|
|
||||||
|
|
||||||
use typst::geom::{self, Smart};
|
|
||||||
use typst::image::{Image, ImageFormat, RasterFormat, VectorFormat};
|
use typst::image::{Image, ImageFormat, RasterFormat, VectorFormat};
|
||||||
use typst::util::option_eq;
|
use typst::util::option_eq;
|
||||||
|
|
||||||
@ -135,7 +133,7 @@ impl Layout for ImageElem {
|
|||||||
let format = match self.format(styles) {
|
let format = match self.format(styles) {
|
||||||
Smart::Custom(v) => v,
|
Smart::Custom(v) => v,
|
||||||
Smart::Auto => {
|
Smart::Auto => {
|
||||||
let ext = Path::new(self.path().as_str())
|
let ext = std::path::Path::new(self.path().as_str())
|
||||||
.extension()
|
.extension()
|
||||||
.and_then(OsStr::to_str)
|
.and_then(OsStr::to_str)
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
@ -213,7 +211,7 @@ impl Layout for ImageElem {
|
|||||||
|
|
||||||
// Create a clipping group if only part of the image should be visible.
|
// Create a clipping group if only part of the image should be visible.
|
||||||
if fit == ImageFit::Cover && !target.fits(fitted) {
|
if fit == ImageFit::Cover && !target.fits(fitted) {
|
||||||
frame.clip(geom::Path::rect(frame.size()));
|
frame.clip(Path::rect(frame.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply metadata.
|
// Apply metadata.
|
||||||
|
@ -1087,7 +1087,7 @@ fn create_repr_impl(element: &Elem) -> TokenStream {
|
|||||||
let fields = self.fields().into_iter()
|
let fields = self.fields().into_iter()
|
||||||
.map(|(name, value)| eco_format!("{}: {}", name, value.repr()))
|
.map(|(name, value)| eco_format!("{}: {}", name, value.repr()))
|
||||||
.collect::<Vec<_>>();
|
.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>() {
|
if id == ::std::any::TypeId::of::<dyn #capability>() {
|
||||||
let vtable = unsafe {
|
let vtable = unsafe {
|
||||||
let dangling = ::std::ptr::NonNull::<#ident>::dangling().as_ptr() as *const dyn #capability;
|
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);
|
return Some(vtable);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use std::num::NonZeroUsize;
|
use std::num::NonZeroUsize;
|
||||||
|
|
||||||
use pdf_writer::{Finish, Ref, TextStr};
|
use pdf_writer::{Finish, Ref, TextStr};
|
||||||
use typst::eval::item;
|
use typst::eval::{item, Smart};
|
||||||
use typst::geom::{Abs, Smart};
|
use typst::geom::Abs;
|
||||||
use typst::model::Content;
|
use typst::model::Content;
|
||||||
|
|
||||||
use crate::{AbsExt, PdfContext};
|
use crate::{AbsExt, PdfContext};
|
||||||
|
@ -8,12 +8,11 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use ecow::{eco_format, EcoString};
|
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::font::Font;
|
||||||
use crate::geom::{
|
use crate::geom::{
|
||||||
self, styled_rect, Abs, Axes, Color, Corners, Dir, Em, FixedAlign, FixedStroke,
|
self, styled_rect, Abs, Axes, Color, Corners, Dir, Em, FixedAlign, FixedStroke,
|
||||||
Geometry, Length, Numeric, Paint, Path, Point, Rel, Shape, Sides, Size, Smart,
|
Geometry, Length, Numeric, Paint, Path, Point, Rel, Shape, Sides, Size, Transform,
|
||||||
Transform,
|
|
||||||
};
|
};
|
||||||
use crate::image::Image;
|
use crate::image::Image;
|
||||||
use crate::model::{Content, Location, MetaElem, StyleChain};
|
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 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 super::{func, scope, ty, Array, Dict, FromValue, IntoValue, Repr, Str, Value};
|
||||||
use crate::diag::{bail, At, SourceDiagnostic, SourceResult};
|
use crate::diag::{bail, At, SourceDiagnostic, SourceResult};
|
||||||
use crate::syntax::{Span, Spanned};
|
use crate::syntax::{Span, Spanned};
|
||||||
use crate::util::pretty_array_like;
|
|
||||||
|
|
||||||
/// Captured arguments to a function.
|
/// Captured arguments to a function.
|
||||||
///
|
///
|
||||||
|
@ -7,6 +7,7 @@ use ecow::{eco_format, EcoString, EcoVec};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
|
use super::repr::pretty_array_like;
|
||||||
use super::{
|
use super::{
|
||||||
cast, func, ops, scope, ty, Args, Bytes, CastInfo, FromValue, Func, IntoValue,
|
cast, func, ops, scope, ty, Args, Bytes, CastInfo, FromValue, Func, IntoValue,
|
||||||
Reflect, Repr, Value, Version, Vm,
|
Reflect, Repr, Value, Version, Vm,
|
||||||
@ -14,7 +15,6 @@ use super::{
|
|||||||
use crate::diag::{At, SourceResult, StrResult};
|
use crate::diag::{At, SourceResult, StrResult};
|
||||||
use crate::eval::ops::{add, mul};
|
use crate::eval::ops::{add, mul};
|
||||||
use crate::syntax::Span;
|
use crate::syntax::Span;
|
||||||
use crate::util::pretty_array_like;
|
|
||||||
|
|
||||||
/// Create a new [`Array`] from values.
|
/// Create a new [`Array`] from values.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
@ -3,6 +3,7 @@ use std::fmt::Debug;
|
|||||||
|
|
||||||
use super::{ty, CastInfo, FromValue, IntoValue, Reflect, Repr, Type, Value};
|
use super::{ty, CastInfo, FromValue, IntoValue, Reflect, Repr, Type, Value};
|
||||||
use crate::diag::StrResult;
|
use crate::diag::StrResult;
|
||||||
|
use crate::model::{Fold, Resolve, StyleChain};
|
||||||
|
|
||||||
/// A value that indicates a smart default.
|
/// A value that indicates a smart default.
|
||||||
///
|
///
|
||||||
@ -50,3 +51,182 @@ impl Repr for AutoValue {
|
|||||||
"auto".into()
|
"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 smallvec::SmallVec;
|
||||||
use unicode_math_class::MathClass;
|
use unicode_math_class::MathClass;
|
||||||
|
|
||||||
|
use super::repr::separated_list;
|
||||||
use super::{Repr, Type, Value};
|
use super::{Repr, Type, Value};
|
||||||
use crate::diag::{At, SourceResult, StrResult};
|
use crate::diag::{At, SourceResult, StrResult};
|
||||||
use crate::syntax::{Span, Spanned};
|
use crate::syntax::{Span, Spanned};
|
||||||
use crate::util::separated_list;
|
|
||||||
|
|
||||||
/// Determine details of a type.
|
/// Determine details of a type.
|
||||||
///
|
///
|
||||||
|
@ -9,10 +9,9 @@ use time::error::{Format, InvalidFormatDescription};
|
|||||||
use time::macros::format_description;
|
use time::macros::format_description;
|
||||||
use time::{format_description, Month, PrimitiveDateTime};
|
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::diag::{bail, StrResult};
|
||||||
use crate::geom::Smart;
|
|
||||||
use crate::util::pretty_array_like;
|
|
||||||
use crate::World;
|
use crate::World;
|
||||||
|
|
||||||
/// Represents a date, a time, or a combination of both.
|
/// Represents a date, a time, or a combination of both.
|
||||||
|
@ -7,10 +7,11 @@ use ecow::{eco_format, EcoString};
|
|||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
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 super::{array, func, scope, ty, Array, Repr, Str, Value};
|
||||||
use crate::diag::StrResult;
|
use crate::diag::StrResult;
|
||||||
use crate::syntax::is_ident;
|
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.
|
/// Create a new [`Dict`] from key-value pairs.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
@ -4,8 +4,8 @@ use std::fmt::Debug;
|
|||||||
use std::ops::{Add, Div, Mul, Neg, Sub};
|
use std::ops::{Add, Div, Mul, Neg, Sub};
|
||||||
use time::ext::NumericalDuration;
|
use time::ext::NumericalDuration;
|
||||||
|
|
||||||
|
use super::repr::pretty_array_like;
|
||||||
use super::{func, scope, ty, Repr};
|
use super::{func, scope, ty, Repr};
|
||||||
use crate::util::pretty_array_like;
|
|
||||||
|
|
||||||
/// Represents a positive or negative span of time.
|
/// Represents a positive or negative span of time.
|
||||||
#[ty(scope)]
|
#[ty(scope)]
|
||||||
|
@ -2,9 +2,9 @@ use std::num::ParseFloatError;
|
|||||||
|
|
||||||
use ecow::{eco_format, EcoString};
|
use ecow::{eco_format, EcoString};
|
||||||
|
|
||||||
|
use super::repr::{format_float, MINUS_SIGN};
|
||||||
use super::{cast, func, scope, ty, Repr, Str};
|
use super::{cast, func, scope, ty, Repr, Str};
|
||||||
use crate::geom::Ratio;
|
use crate::geom::Ratio;
|
||||||
use crate::util::fmt::{format_float, MINUS_SIGN};
|
|
||||||
|
|
||||||
/// A floating-point number.
|
/// A floating-point number.
|
||||||
///
|
///
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use std::num::{NonZeroI64, NonZeroIsize, NonZeroU64, NonZeroUsize, ParseIntError};
|
use std::num::{NonZeroI64, NonZeroIsize, NonZeroU64, NonZeroUsize, ParseIntError};
|
||||||
|
|
||||||
use crate::util::fmt::{format_int_with_base, MINUS_SIGN};
|
|
||||||
use ecow::{eco_format, EcoString};
|
use ecow::{eco_format, EcoString};
|
||||||
|
|
||||||
|
use super::repr::{format_int_with_base, MINUS_SIGN};
|
||||||
use super::{cast, func, scope, ty, Repr, Str, Value};
|
use super::{cast, func, scope, ty, Repr, Str, Value};
|
||||||
|
|
||||||
/// A whole number.
|
/// A whole number.
|
||||||
|
@ -27,6 +27,7 @@ mod module;
|
|||||||
mod none;
|
mod none;
|
||||||
pub mod ops;
|
pub mod ops;
|
||||||
mod plugin;
|
mod plugin;
|
||||||
|
pub mod repr;
|
||||||
mod scope;
|
mod scope;
|
||||||
mod symbol;
|
mod symbol;
|
||||||
mod tracer;
|
mod tracer;
|
||||||
@ -43,7 +44,7 @@ pub use {
|
|||||||
|
|
||||||
pub use self::args::{Arg, Args};
|
pub use self::args::{Arg, Args};
|
||||||
pub use self::array::{array, Array};
|
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::bytes::Bytes;
|
||||||
pub use self::cast::{
|
pub use self::cast::{
|
||||||
cast, Cast, CastInfo, Container, FromValue, IntoResult, IntoValue, Never, Reflect,
|
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::module::Module;
|
||||||
pub use self::none::NoneValue;
|
pub use self::none::NoneValue;
|
||||||
pub use self::plugin::Plugin;
|
pub use self::plugin::Plugin;
|
||||||
|
pub use self::repr::Repr;
|
||||||
pub use self::scope::{NativeScope, Scope, Scopes};
|
pub use self::scope::{NativeScope, Scope, Scopes};
|
||||||
pub use self::str::{format_str, Regex, Str};
|
pub use self::str::{format_str, Regex, Str};
|
||||||
pub use self::symbol::{symbols, Symbol};
|
pub use self::symbol::{symbols, Symbol};
|
||||||
pub use self::tracer::Tracer;
|
pub use self::tracer::Tracer;
|
||||||
pub use self::ty::{scope, ty, NativeType, NativeTypeData, Type};
|
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;
|
pub use self::version::Version;
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
@ -4,10 +4,9 @@ use std::cmp::Ordering;
|
|||||||
|
|
||||||
use ecow::eco_format;
|
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::diag::{bail, StrResult};
|
||||||
use crate::eval::item;
|
use crate::geom::{Align, Length, Numeric, Rel, Stroke};
|
||||||
use crate::geom::{Align, Length, Numeric, Rel, Smart, Stroke};
|
|
||||||
use Value::*;
|
use Value::*;
|
||||||
|
|
||||||
/// Bail with a type mismatch error.
|
/// Bail with a type mismatch error.
|
||||||
|
@ -2,6 +2,12 @@ use ecow::{eco_format, EcoString};
|
|||||||
|
|
||||||
pub const MINUS_SIGN: &str = "\u{2212}";
|
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.
|
/// Format an integer in a base.
|
||||||
pub fn format_int_with_base(mut n: i64, base: i64) -> EcoString {
|
pub fn format_int_with_base(mut n: i64, base: i64) -> EcoString {
|
||||||
if n == 0 {
|
if n == 0 {
|
@ -7,6 +7,7 @@ use ecow::EcoString;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use unicode_segmentation::UnicodeSegmentation;
|
use unicode_segmentation::UnicodeSegmentation;
|
||||||
|
|
||||||
|
use super::repr::{format_float, format_int_with_base};
|
||||||
use super::{
|
use super::{
|
||||||
cast, dict, func, scope, ty, Args, Array, Bytes, Dict, Func, IntoValue, Repr, Type,
|
cast, dict, func, scope, ty, Args, Array, Bytes, Dict, Func, IntoValue, Repr, Type,
|
||||||
Value, Version, Vm,
|
Value, Version, Vm,
|
||||||
@ -15,7 +16,6 @@ use crate::diag::{bail, At, SourceResult, StrResult};
|
|||||||
use crate::geom::Align;
|
use crate::geom::Align;
|
||||||
use crate::model::Label;
|
use crate::model::Label;
|
||||||
use crate::syntax::{Span, Spanned};
|
use crate::syntax::{Span, Spanned};
|
||||||
use crate::util::fmt::{format_float, format_int_with_base};
|
|
||||||
|
|
||||||
/// Create a new [`Str`] from a format string.
|
/// Create a new [`Str`] from a format string.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
@ -11,17 +11,17 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
|||||||
use siphasher::sip128::{Hasher128, SipHasher13};
|
use siphasher::sip128::{Hasher128, SipHasher13};
|
||||||
use typst::eval::Duration;
|
use typst::eval::Duration;
|
||||||
|
|
||||||
|
use super::repr::{format_float, format_int_with_base};
|
||||||
use super::{
|
use super::{
|
||||||
fields, ops, Args, Array, AutoValue, Bytes, CastInfo, Content, Dict, FromValue, Func,
|
fields, ops, Args, Array, AutoValue, Bytes, CastInfo, Content, Dict, FromValue, Func,
|
||||||
IntoValue, Module, NativeType, NoneValue, Plugin, Reflect, Scope, Str, Symbol, Type,
|
IntoValue, Module, NativeType, NoneValue, Plugin, Reflect, Repr, Scope, Str, Symbol,
|
||||||
Version,
|
Type, Version,
|
||||||
};
|
};
|
||||||
use crate::diag::StrResult;
|
use crate::diag::StrResult;
|
||||||
use crate::eval::{item, Datetime};
|
use crate::eval::{item, Datetime};
|
||||||
use crate::geom::{Abs, Angle, Color, Em, Fr, Gradient, Length, Ratio, Rel};
|
use crate::geom::{Abs, Angle, Color, Em, Fr, Gradient, Length, Ratio, Rel};
|
||||||
use crate::model::{Label, Styles};
|
use crate::model::{Label, Styles};
|
||||||
use crate::syntax::{ast, Span};
|
use crate::syntax::{ast, Span};
|
||||||
use crate::util::fmt::{format_float, format_int_with_base};
|
|
||||||
|
|
||||||
/// A computational value.
|
/// A computational value.
|
||||||
#[derive(Debug, Default, Clone)]
|
#[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 {
|
trait Bounds: Debug + Repr + Sync + Send + 'static {
|
||||||
fn as_any(&self) -> &dyn Any;
|
fn as_any(&self) -> &dyn Any;
|
||||||
fn dyn_eq(&self, other: &Dynamic) -> bool;
|
fn dyn_eq(&self, other: &Dynamic) -> bool;
|
||||||
|
@ -5,9 +5,9 @@ use std::iter::repeat;
|
|||||||
|
|
||||||
use ecow::{eco_format, EcoString, EcoVec};
|
use ecow::{eco_format, EcoString, EcoVec};
|
||||||
|
|
||||||
|
use super::repr::pretty_array_like;
|
||||||
use super::{cast, func, scope, ty, Repr};
|
use super::{cast, func, scope, ty, Repr};
|
||||||
use crate::diag::{bail, error, StrResult};
|
use crate::diag::{bail, error, StrResult};
|
||||||
use crate::util::pretty_array_like;
|
|
||||||
|
|
||||||
/// A version with an arbitrary number of components.
|
/// A version with an arbitrary number of components.
|
||||||
///
|
///
|
||||||
|
@ -24,7 +24,6 @@ mod scalar;
|
|||||||
mod shape;
|
mod shape;
|
||||||
mod sides;
|
mod sides;
|
||||||
mod size;
|
mod size;
|
||||||
mod smart;
|
|
||||||
mod stroke;
|
mod stroke;
|
||||||
mod transform;
|
mod transform;
|
||||||
|
|
||||||
@ -52,7 +51,6 @@ pub use self::scalar::Scalar;
|
|||||||
pub use self::shape::{Geometry, Shape};
|
pub use self::shape::{Geometry, Shape};
|
||||||
pub use self::sides::{Side, Sides};
|
pub use self::sides::{Side, Sides};
|
||||||
pub use self::size::Size;
|
pub use self::size::Size;
|
||||||
pub use self::smart::Smart;
|
|
||||||
pub use self::stroke::{DashLength, DashPattern, FixedStroke, LineCap, LineJoin, Stroke};
|
pub use self::stroke::{DashLength, DashPattern, FixedStroke, LineCap, LineJoin, Stroke};
|
||||||
pub use self::transform::Transform;
|
pub use self::transform::Transform;
|
||||||
|
|
||||||
@ -66,9 +64,9 @@ use std::ops::*;
|
|||||||
use ecow::{eco_format, EcoString};
|
use ecow::{eco_format, EcoString};
|
||||||
|
|
||||||
use crate::diag::{bail, StrResult};
|
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::model::{Fold, Resolve, StyleChain};
|
||||||
use crate::util::fmt::format_float;
|
|
||||||
|
|
||||||
/// Generic access to a structure's components.
|
/// Generic access to a structure's components.
|
||||||
pub trait Get<Index> {
|
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::diag::{SourceResult, StrResult};
|
||||||
use crate::doc::Meta;
|
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::eval::{func, scope, ty, Dict, FromValue, IntoValue, Repr, Str, Value, Vm};
|
||||||
use crate::syntax::Span;
|
use crate::syntax::Span;
|
||||||
use crate::util::pretty_array_like;
|
|
||||||
|
|
||||||
/// A piece of document content.
|
/// A piece of document content.
|
||||||
///
|
///
|
||||||
@ -256,7 +256,7 @@ impl Content {
|
|||||||
{
|
{
|
||||||
let vtable = self.elem().vtable()(TypeId::of::<C>())?;
|
let vtable = self.elem().vtable()(TypeId::of::<C>())?;
|
||||||
let data = Arc::as_ptr(&self.0) as *const ();
|
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
|
/// 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.
|
// Safety: We ensure the element is not shared.
|
||||||
let vtable = self.elem().vtable()(TypeId::of::<C>())?;
|
let vtable = self.elem().vtable()(TypeId::of::<C>())?;
|
||||||
let data = self.make_mut() as *mut dyn NativeElement as *mut ();
|
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.
|
/// Whether the content is a sequence.
|
||||||
@ -749,3 +749,66 @@ fn missing_field_no_default(field: &str) -> EcoString {
|
|||||||
field.repr()
|
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 typst_macros::elem;
|
||||||
|
|
||||||
pub use self::block::{Block, Blockable};
|
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::{
|
pub use self::element::{
|
||||||
Construct, Element, ElementFields, LocalName, NativeElement, NativeElementData, Set,
|
Construct, Element, ElementFields, LocalName, NativeElement, NativeElementData, Set,
|
||||||
};
|
};
|
||||||
|
@ -7,11 +7,11 @@ use smallvec::SmallVec;
|
|||||||
|
|
||||||
use super::{Content, Element, Label, Locatable, Location};
|
use super::{Content, Element, Label, Locatable, Location};
|
||||||
use crate::diag::{bail, StrResult};
|
use crate::diag::{bail, StrResult};
|
||||||
|
use crate::eval::repr::pretty_array_like;
|
||||||
use crate::eval::{
|
use crate::eval::{
|
||||||
cast, func, item, scope, ty, CastInfo, Dict, FromValue, Func, Reflect, Regex, Repr,
|
cast, func, item, scope, ty, CastInfo, Dict, FromValue, Func, Reflect, Regex, Repr,
|
||||||
Str, Symbol, Type, Value,
|
Str, Symbol, Type, Value,
|
||||||
};
|
};
|
||||||
use crate::util::pretty_array_like;
|
|
||||||
|
|
||||||
/// A helper macro to create a field selector used in [`Selector::Elem`]
|
/// 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.
|
//! Utilities.
|
||||||
|
|
||||||
pub mod fat;
|
mod pico;
|
||||||
pub mod fmt;
|
|
||||||
mod str;
|
|
||||||
|
|
||||||
pub use self::fmt::{pretty_array_like, pretty_comma_list, separated_list};
|
pub use self::pico::PicoStr;
|
||||||
pub use self::str::PicoStr;
|
|
||||||
|
|
||||||
use std::fmt::{Debug, Formatter};
|
use std::fmt::{Debug, Formatter};
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
@ -23,10 +23,10 @@ use walkdir::WalkDir;
|
|||||||
use typst::diag::{bail, FileError, FileResult, Severity, StrResult};
|
use typst::diag::{bail, FileError, FileResult, Severity, StrResult};
|
||||||
use typst::doc::{Document, Frame, FrameItem, Meta};
|
use typst::doc::{Document, Frame, FrameItem, Meta};
|
||||||
use typst::eval::{
|
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::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::syntax::{FileId, PackageVersion, Source, SyntaxNode, VirtualPath};
|
||||||
use typst::{World, WorldExt};
|
use typst::{World, WorldExt};
|
||||||
use typst_library::layout::{Margin, PageElem};
|
use typst_library::layout::{Margin, PageElem};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user