mirror of
https://github.com/typst/typst
synced 2025-05-13 20:46:23 +08:00
StyleSlot
, KeyId
and NodeId
This commit is contained in:
parent
8fbb11fc05
commit
89927d7de0
@ -249,12 +249,12 @@ fn process_const(
|
|||||||
|
|
||||||
const NAME: &'static str = #name;
|
const NAME: &'static str = #name;
|
||||||
|
|
||||||
fn node() -> TypeId {
|
fn node() -> model::NodeId {
|
||||||
TypeId::of::<#self_ty>()
|
model::NodeId::of::<#self_ty>()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get(
|
fn get(
|
||||||
chain: StyleChain<'a>,
|
chain: model::StyleChain<'a>,
|
||||||
mut values: impl Iterator<Item = &'a Self::Value>,
|
mut values: impl Iterator<Item = &'a Self::Value>,
|
||||||
) -> Self::Output {
|
) -> Self::Output {
|
||||||
#get
|
#get
|
||||||
|
@ -5,7 +5,7 @@ use std::fmt::{self, Debug, Formatter};
|
|||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use super::{Barrier, Resolve, StyleChain};
|
use super::{Barrier, NodeId, Resolve, StyleChain, StyleSlot};
|
||||||
use crate::diag::TypResult;
|
use crate::diag::TypResult;
|
||||||
use crate::eval::{RawAlign, RawLength};
|
use crate::eval::{RawAlign, RawLength};
|
||||||
use crate::frame::{Element, Frame, Geometry};
|
use crate::frame::{Element, Frame, Geometry};
|
||||||
@ -148,9 +148,9 @@ impl LayoutNode {
|
|||||||
(**self.0).as_any().is::<T>()
|
(**self.0).as_any().is::<T>()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A barrier for the node.
|
/// The id of this node.
|
||||||
pub fn barrier(&self) -> Barrier {
|
pub fn id(&self) -> NodeId {
|
||||||
(**self.0).barrier()
|
(**self.0).node_id()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Try to downcast to a specific layout node.
|
/// Try to downcast to a specific layout node.
|
||||||
@ -220,7 +220,8 @@ impl Layout for LayoutNode {
|
|||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
) -> TypResult<Vec<Arc<Frame>>> {
|
) -> TypResult<Vec<Arc<Frame>>> {
|
||||||
ctx.query((self, regions, styles), |ctx, (node, regions, styles)| {
|
ctx.query((self, regions, styles), |ctx, (node, regions, styles)| {
|
||||||
node.0.layout(ctx, regions, node.barrier().chain(&styles))
|
let slot = StyleSlot::from(Barrier::new(node.id()));
|
||||||
|
node.0.layout(ctx, regions, slot.chain(&styles))
|
||||||
})
|
})
|
||||||
.clone()
|
.clone()
|
||||||
}
|
}
|
||||||
@ -250,7 +251,7 @@ impl PartialEq for LayoutNode {
|
|||||||
|
|
||||||
trait Bounds: Layout + Debug + Sync + Send + 'static {
|
trait Bounds: Layout + Debug + Sync + Send + 'static {
|
||||||
fn as_any(&self) -> &dyn Any;
|
fn as_any(&self) -> &dyn Any;
|
||||||
fn barrier(&self) -> Barrier;
|
fn node_id(&self) -> NodeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Bounds for T
|
impl<T> Bounds for T
|
||||||
@ -261,8 +262,8 @@ where
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn barrier(&self) -> Barrier {
|
fn node_id(&self) -> NodeId {
|
||||||
Barrier::new::<T>()
|
NodeId::of::<Self>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
use std::any::{Any, TypeId};
|
|
||||||
use std::fmt::{self, Debug, Formatter};
|
use std::fmt::{self, Debug, Formatter};
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use super::{Content, StyleChain};
|
use super::{Content, NodeId, StyleChain};
|
||||||
use crate::diag::TypResult;
|
use crate::diag::TypResult;
|
||||||
use crate::eval::Dict;
|
use crate::eval::Dict;
|
||||||
use crate::util::Prehashed;
|
use crate::util::Prehashed;
|
||||||
@ -57,9 +56,9 @@ impl ShowNode {
|
|||||||
Self(Arc::new(Prehashed::new(node)))
|
Self(Arc::new(Prehashed::new(node)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The type id of this node.
|
/// The id of this node.
|
||||||
pub fn id(&self) -> TypeId {
|
pub fn id(&self) -> NodeId {
|
||||||
self.0.as_any().type_id()
|
(**self.0).node_id()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,14 +98,14 @@ impl PartialEq for ShowNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
trait Bounds: Show + Debug + Sync + Send + 'static {
|
trait Bounds: Show + Debug + Sync + Send + 'static {
|
||||||
fn as_any(&self) -> &dyn Any;
|
fn node_id(&self) -> NodeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Bounds for T
|
impl<T> Bounds for T
|
||||||
where
|
where
|
||||||
T: Show + Debug + Hash + Sync + Send + 'static,
|
T: Show + Debug + Hash + Sync + Send + 'static,
|
||||||
{
|
{
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn node_id(&self) -> NodeId {
|
||||||
self
|
NodeId::of::<Self>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
use std::any::{Any, TypeId};
|
use std::any::Any;
|
||||||
use std::fmt::{self, Debug, Formatter};
|
use std::fmt::{self, Debug, Formatter};
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use super::{Content, Layout, Show, ShowNode};
|
use super::{Content, Show, ShowNode};
|
||||||
use crate::diag::{At, TypResult};
|
use crate::diag::{At, TypResult};
|
||||||
use crate::eval::{Args, Func, Node, Smart, Value};
|
use crate::eval::{Args, Func, Node, Smart, Value};
|
||||||
use crate::geom::{Numeric, Relative, Sides, Spec};
|
use crate::geom::{Numeric, Relative, Sides, Spec};
|
||||||
use crate::library::layout::PageNode;
|
use crate::library::layout::PageNode;
|
||||||
use crate::library::text::{FontFamily, ParNode, TextNode};
|
use crate::library::text::{FontFamily, ParNode, TextNode};
|
||||||
use crate::syntax::Span;
|
use crate::syntax::Span;
|
||||||
use crate::util::Prehashed;
|
use crate::util::{Prehashed, ReadableTypeId};
|
||||||
use crate::Context;
|
use crate::Context;
|
||||||
|
|
||||||
/// A map of style properties.
|
/// A map of style properties.
|
||||||
@ -73,7 +73,7 @@ impl StyleMap {
|
|||||||
self.0
|
self.0
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|entry| entry.property())
|
.filter_map(|entry| entry.property())
|
||||||
.any(|property| property.key == TypeId::of::<K>())
|
.any(|property| property.key == KeyId::of::<K>())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Make `self` the first link of the `tail` chain.
|
/// Make `self` the first link of the `tail` chain.
|
||||||
@ -141,13 +141,42 @@ impl Debug for StyleMap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A stack-allocated slot for a single style property or barrier.
|
||||||
|
pub struct StyleSlot(Entry);
|
||||||
|
|
||||||
|
impl StyleSlot {
|
||||||
|
/// Make this slot the first link of the `tail` chain.
|
||||||
|
pub fn chain<'a>(&'a self, tail: &'a StyleChain) -> StyleChain<'a> {
|
||||||
|
if let Entry::Barrier(barrier) = &self.0 {
|
||||||
|
if !tail
|
||||||
|
.entries()
|
||||||
|
.filter_map(Entry::property)
|
||||||
|
.any(|p| p.scoped && p.node == barrier.0)
|
||||||
|
{
|
||||||
|
return *tail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyleChain {
|
||||||
|
head: std::slice::from_ref(&self.0),
|
||||||
|
tail: Some(tail),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Barrier> for StyleSlot {
|
||||||
|
fn from(barrier: Barrier) -> Self {
|
||||||
|
Self(Entry::Barrier(barrier))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// An entry for a single style property, recipe or barrier.
|
/// An entry for a single style property, recipe or barrier.
|
||||||
#[derive(Clone, PartialEq, Hash)]
|
#[derive(Clone, PartialEq, Hash)]
|
||||||
enum Entry {
|
enum Entry {
|
||||||
/// A style property originating from a set rule or constructor.
|
/// A style property originating from a set rule or constructor.
|
||||||
Property(Property),
|
Property(Property),
|
||||||
/// A barrier for scoped styles.
|
/// A barrier for scoped styles.
|
||||||
Barrier(TypeId, &'static str),
|
Barrier(Barrier),
|
||||||
/// A show rule recipe.
|
/// A show rule recipe.
|
||||||
Recipe(Recipe),
|
Recipe(Recipe),
|
||||||
}
|
}
|
||||||
@ -176,20 +205,55 @@ impl Debug for Entry {
|
|||||||
match self {
|
match self {
|
||||||
Self::Property(property) => property.fmt(f)?,
|
Self::Property(property) => property.fmt(f)?,
|
||||||
Self::Recipe(recipe) => recipe.fmt(f)?,
|
Self::Recipe(recipe) => recipe.fmt(f)?,
|
||||||
Self::Barrier(_, name) => write!(f, "Barrier for {name}")?,
|
Self::Barrier(barrier) => barrier.fmt(f)?,
|
||||||
}
|
}
|
||||||
f.write_str("]")
|
f.write_str("]")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A unique identifier for a node.
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
|
pub struct NodeId(ReadableTypeId);
|
||||||
|
|
||||||
|
impl NodeId {
|
||||||
|
/// The id of the given node.
|
||||||
|
pub fn of<T: 'static>() -> Self {
|
||||||
|
Self(ReadableTypeId::of::<T>())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for NodeId {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
self.0.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A unique identifier for a property key.
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
|
pub struct KeyId(ReadableTypeId);
|
||||||
|
|
||||||
|
impl KeyId {
|
||||||
|
/// The id of the given key.
|
||||||
|
pub fn of<'a, T: Key<'a>>() -> Self {
|
||||||
|
Self(ReadableTypeId::of::<T>())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for KeyId {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
self.0.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A style property originating from a set rule or constructor.
|
/// A style property originating from a set rule or constructor.
|
||||||
#[derive(Clone, Hash)]
|
#[derive(Clone, Hash)]
|
||||||
struct Property {
|
struct Property {
|
||||||
/// The type id of the property's [key](Key).
|
/// The id of the property's [key](Key).
|
||||||
key: TypeId,
|
key: KeyId,
|
||||||
/// The type id of the node the property belongs to.
|
/// The id of the node the property belongs to.
|
||||||
node: TypeId,
|
node: NodeId,
|
||||||
/// The name of the property.
|
/// The name of the property.
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
/// The property's value.
|
/// The property's value.
|
||||||
value: Arc<Prehashed<dyn Bounds>>,
|
value: Arc<Prehashed<dyn Bounds>>,
|
||||||
@ -202,8 +266,9 @@ impl Property {
|
|||||||
/// Create a new property from a key-value pair.
|
/// Create a new property from a key-value pair.
|
||||||
fn new<'a, K: Key<'a>>(_: K, value: K::Value) -> Self {
|
fn new<'a, K: Key<'a>>(_: K, value: K::Value) -> Self {
|
||||||
Self {
|
Self {
|
||||||
key: TypeId::of::<K>(),
|
key: KeyId::of::<K>(),
|
||||||
node: K::node(),
|
node: K::node(),
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
name: K::NAME,
|
name: K::NAME,
|
||||||
value: Arc::new(Prehashed::new(value)),
|
value: Arc::new(Prehashed::new(value)),
|
||||||
scoped: false,
|
scoped: false,
|
||||||
@ -223,7 +288,7 @@ impl Property {
|
|||||||
|
|
||||||
/// Access the property's value if it is of the given key.
|
/// Access the property's value if it is of the given key.
|
||||||
fn downcast<'a, K: Key<'a>>(&'a self) -> Option<&'a K::Value> {
|
fn downcast<'a, K: Key<'a>>(&'a self) -> Option<&'a K::Value> {
|
||||||
if self.key == TypeId::of::<K>() {
|
if self.key == KeyId::of::<K>() {
|
||||||
(**self.value).as_any().downcast_ref()
|
(**self.value).as_any().downcast_ref()
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -232,13 +297,15 @@ impl Property {
|
|||||||
|
|
||||||
/// Whether this property belongs to the node `T`.
|
/// Whether this property belongs to the node `T`.
|
||||||
fn is_of<T: Node>(&self) -> bool {
|
fn is_of<T: Node>(&self) -> bool {
|
||||||
self.node == TypeId::of::<T>()
|
self.node == NodeId::of::<T>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for Property {
|
impl Debug for Property {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
write!(f, "{} = {:?}", self.name, self.value)?;
|
#[cfg(debug_assertions)]
|
||||||
|
write!(f, "{} = ", self.name)?;
|
||||||
|
write!(f, "{:?}", self.value)?;
|
||||||
if self.scoped {
|
if self.scoped {
|
||||||
write!(f, " [scoped]")?;
|
write!(f, " [scoped]")?;
|
||||||
}
|
}
|
||||||
@ -286,8 +353,8 @@ pub trait Key<'a>: Copy + 'static {
|
|||||||
/// The name of the property, used for debug printing.
|
/// The name of the property, used for debug printing.
|
||||||
const NAME: &'static str;
|
const NAME: &'static str;
|
||||||
|
|
||||||
/// The type id of the node this property belongs to.
|
/// The ids of the key and of the node the key belongs to.
|
||||||
fn node() -> TypeId;
|
fn node() -> NodeId;
|
||||||
|
|
||||||
/// Compute an output value from a sequence of values belong to this key,
|
/// Compute an output value from a sequence of values belong to this key,
|
||||||
/// folding if necessary.
|
/// folding if necessary.
|
||||||
@ -388,13 +455,32 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A scoped property barrier.
|
||||||
|
///
|
||||||
|
/// Barriers interact with [scoped](StyleMap::scoped) styles: A scoped style
|
||||||
|
/// can still be read through a single barrier (the one of the node it
|
||||||
|
/// _should_ apply to), but a second barrier will make it invisible.
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
|
pub struct Barrier(NodeId);
|
||||||
|
|
||||||
|
impl Barrier {
|
||||||
|
/// Create a new barrier for the given node.
|
||||||
|
pub fn new(node: NodeId) -> Self {
|
||||||
|
Self(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for Barrier {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
write!(f, "Barrier for {:?}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A show rule recipe.
|
/// A show rule recipe.
|
||||||
#[derive(Clone, PartialEq, Hash)]
|
#[derive(Clone, PartialEq, Hash)]
|
||||||
struct Recipe {
|
struct Recipe {
|
||||||
/// The affected node.
|
/// The affected node.
|
||||||
node: TypeId,
|
node: NodeId,
|
||||||
/// The name of the affected node.
|
|
||||||
name: &'static str,
|
|
||||||
/// The function that defines the recipe.
|
/// The function that defines the recipe.
|
||||||
func: Func,
|
func: Func,
|
||||||
/// The span to report all erros with.
|
/// The span to report all erros with.
|
||||||
@ -404,67 +490,13 @@ struct Recipe {
|
|||||||
impl Recipe {
|
impl Recipe {
|
||||||
/// Create a new recipe for the node `T`.
|
/// Create a new recipe for the node `T`.
|
||||||
fn new<T: Node>(func: Func, span: Span) -> Self {
|
fn new<T: Node>(func: Func, span: Span) -> Self {
|
||||||
Self {
|
Self { node: NodeId::of::<T>(), func, span }
|
||||||
node: TypeId::of::<T>(),
|
|
||||||
name: std::any::type_name::<T>(),
|
|
||||||
func,
|
|
||||||
span,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for Recipe {
|
impl Debug for Recipe {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
write!(f, "Recipe for {} from {:?}", self.name, self.span)
|
write!(f, "Recipe for {:?} from {:?}", self.node, self.span)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A style chain barrier.
|
|
||||||
///
|
|
||||||
/// Barriers interact with [scoped](StyleMap::scoped) styles: A scoped style
|
|
||||||
/// can still be read through a single barrier (the one of the node it
|
|
||||||
/// _should_ apply to), but a second barrier will make it invisible.
|
|
||||||
#[derive(Clone, PartialEq, Hash)]
|
|
||||||
pub struct Barrier(Entry);
|
|
||||||
|
|
||||||
impl Barrier {
|
|
||||||
/// Create a new barrier for the layout node `T`.
|
|
||||||
pub fn new<T: Layout>() -> Self {
|
|
||||||
Self(Entry::Barrier(
|
|
||||||
TypeId::of::<T>(),
|
|
||||||
std::any::type_name::<T>(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Make this barrier the first link of the `tail` chain.
|
|
||||||
pub fn chain<'a>(&'a self, tail: &'a StyleChain) -> StyleChain<'a> {
|
|
||||||
// We have to store a full `Entry` enum inside the barrier because
|
|
||||||
// otherwise the `slice::from_ref` trick below won't work.
|
|
||||||
// Unfortunately, that also means we have to somehow extract the id
|
|
||||||
// here.
|
|
||||||
let id = match self.0 {
|
|
||||||
Entry::Barrier(id, _) => id,
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if tail
|
|
||||||
.entries()
|
|
||||||
.filter_map(Entry::property)
|
|
||||||
.any(|p| p.scoped && p.node == id)
|
|
||||||
{
|
|
||||||
StyleChain {
|
|
||||||
head: std::slice::from_ref(&self.0),
|
|
||||||
tail: Some(tail),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
*tail
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Debug for Barrier {
|
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
||||||
self.0.fmt(f)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -536,7 +568,7 @@ impl<'a> StyleChain<'a> {
|
|||||||
impl<'a> StyleChain<'a> {
|
impl<'a> StyleChain<'a> {
|
||||||
/// Return the chain, but without the trailing scoped property for the given
|
/// Return the chain, but without the trailing scoped property for the given
|
||||||
/// `node`. This is a 90% hack fix for show node constructor scoping.
|
/// `node`. This is a 90% hack fix for show node constructor scoping.
|
||||||
pub(super) fn unscoped(mut self, node: TypeId) -> Self {
|
pub(super) fn unscoped(mut self, node: NodeId) -> Self {
|
||||||
while self
|
while self
|
||||||
.head
|
.head
|
||||||
.last()
|
.last()
|
||||||
@ -626,8 +658,8 @@ impl<'a, K: Key<'a>> Iterator for Values<'a, K> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Entry::Barrier(id, _) => {
|
Entry::Barrier(barrier) => {
|
||||||
self.depth += (*id == K::node()) as usize;
|
self.depth += (barrier.0 == K::node()) as usize;
|
||||||
}
|
}
|
||||||
Entry::Recipe(_) => {}
|
Entry::Recipe(_) => {}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ pub use eco_string::EcoString;
|
|||||||
pub use mac_roman::decode_mac_roman;
|
pub use mac_roman::decode_mac_roman;
|
||||||
pub use prehashed::Prehashed;
|
pub use prehashed::Prehashed;
|
||||||
|
|
||||||
|
use std::any::TypeId;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::fmt::{self, Debug, Formatter};
|
use std::fmt::{self, Debug, Formatter};
|
||||||
use std::ops::{Deref, Range};
|
use std::ops::{Deref, Range};
|
||||||
@ -34,7 +35,61 @@ where
|
|||||||
Wrapper(f)
|
Wrapper(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Additional methods for strings.
|
/// An alternative type id that prints as something readable in debug mode.
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
|
pub struct ReadableTypeId {
|
||||||
|
id: TypeId,
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
name: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ReadableTypeId {
|
||||||
|
/// The type id of the given type.
|
||||||
|
pub fn of<T: 'static>() -> Self {
|
||||||
|
Self {
|
||||||
|
id: TypeId::of::<T>(),
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
name: std::any::type_name::<T>(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for ReadableTypeId {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
f.pad(self.name)?;
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
|
f.pad("ReadableTypeId")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Either owned or shared.
|
||||||
|
pub enum MaybeShared<T> {
|
||||||
|
/// Owned data.
|
||||||
|
Owned(T),
|
||||||
|
/// Shared data.
|
||||||
|
Shared(Arc<T>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> AsRef<T> for MaybeShared<T> {
|
||||||
|
fn as_ref(&self) -> &T {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Deref for MaybeShared<T> {
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
match self {
|
||||||
|
Self::Owned(owned) => owned,
|
||||||
|
Self::Shared(shared) => shared,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extra methods for [`str`].
|
||||||
pub trait StrExt {
|
pub trait StrExt {
|
||||||
/// The number of code units this string would use if it was encoded in
|
/// The number of code units this string would use if it was encoded in
|
||||||
/// UTF16. This runs in linear time.
|
/// UTF16. This runs in linear time.
|
||||||
@ -47,7 +102,7 @@ impl StrExt for str {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Additional methods for options.
|
/// Extra methods for [`Option<T>`].
|
||||||
pub trait OptionExt<T> {
|
pub trait OptionExt<T> {
|
||||||
/// Sets `other` as the value if `self` is `None` or if it contains a value
|
/// Sets `other` as the value if `self` is `None` or if it contains a value
|
||||||
/// larger than `other`.
|
/// larger than `other`.
|
||||||
@ -82,7 +137,7 @@ impl<T> OptionExt<T> for Option<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Additional methods for reference-counted pointers.
|
/// Extra methods for [`Arc`].
|
||||||
pub trait ArcExt<T> {
|
pub trait ArcExt<T> {
|
||||||
/// Takes the inner value if there is exactly one strong reference and
|
/// Takes the inner value if there is exactly one strong reference and
|
||||||
/// clones it otherwise.
|
/// clones it otherwise.
|
||||||
@ -101,32 +156,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Either owned or shared.
|
/// Extra methods for `[T]`.
|
||||||
pub enum MaybeShared<T> {
|
|
||||||
/// Owned data.
|
|
||||||
Owned(T),
|
|
||||||
/// Shared data.
|
|
||||||
Shared(Arc<T>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> AsRef<T> for MaybeShared<T> {
|
|
||||||
fn as_ref(&self) -> &T {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Deref for MaybeShared<T> {
|
|
||||||
type Target = T;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
match self {
|
|
||||||
Self::Owned(owned) => owned,
|
|
||||||
Self::Shared(shared) => shared,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Additional methods for slices.
|
|
||||||
pub trait SliceExt<T> {
|
pub trait SliceExt<T> {
|
||||||
/// Split a slice into consecutive runs with the same key and yield for
|
/// Split a slice into consecutive runs with the same key and yield for
|
||||||
/// each such run the key and the slice of elements with that key.
|
/// each such run the key and the slice of elements with that key.
|
||||||
@ -165,7 +195,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Additional methods for [`Range<usize>`].
|
/// Extra methods for [`Range<usize>`].
|
||||||
pub trait RangeExt {
|
pub trait RangeExt {
|
||||||
/// Locate a position relative to a range.
|
/// Locate a position relative to a range.
|
||||||
///
|
///
|
||||||
@ -193,7 +223,7 @@ impl RangeExt for Range<usize> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Additional methods for [`Path`].
|
/// Extra methods for [`Path`].
|
||||||
pub trait PathExt {
|
pub trait PathExt {
|
||||||
/// Lexically normalize a path.
|
/// Lexically normalize a path.
|
||||||
fn normalize(&self) -> PathBuf;
|
fn normalize(&self) -> PathBuf;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user