Skip to main content

Tag

Struct Tag 

Source
pub struct Tag {
    pub name: String,
    pub attributes: IndexMap<String, RenderableTreeNodes>,
    pub children: Vec<RenderableTreeNode>,
}
Expand description

An element in a renderable tree.

Mirrors upstream src/tag.ts. The name is what a renderer emits – p, article, or whatever a schema’s render said – and it is a plain string rather than an HTML element type, because this crate decides no HTML policy. A host rendering to something that is not HTML puts its own names here.

§Why an attribute holds a whole subtree

Upstream types attributes as Record<string, any> and means it: an ordinary attribute is a scalar, but a rendered slot is put in the attribute map as the transformed nodes of that slot (transformer.ts, attributes). The corpus fixes this – “Basic slot” expects attributes: {bar: [{tag: p, ...}]} – so narrowing attributes to Scalar would fail cases that are otherwise correct. RenderableTreeNodes is the honest type, and a scalar attribute is One(Scalar(..)).

Fields§

§name: String

The element name. Upstream defaults it to div.

§attributes: IndexMap<String, RenderableTreeNodes>

The attributes, in authored order.

§children: Vec<RenderableTreeNode>

The children, in document order.

Implementations§

Source§

impl Tag

Source

pub fn new(name: impl Into<String>) -> Tag

A tag with no attributes and no children.

Source

pub fn with( name: impl Into<String>, attributes: IndexMap<String, RenderableTreeNodes>, children: Vec<RenderableTreeNode>, ) -> Tag

A tag with attributes and children.

The argument order is upstream’s new Tag(name, attributes, children), so a ported test reads next to the TypeScript it came from.

Source

pub fn set( &mut self, name: impl Into<String>, value: impl Into<RenderableTreeNodes>, )

Set an attribute to a single value, in authored order.

Source

pub fn push(&mut self, child: RenderableTreeNode)

Append a child.

Trait Implementations§

Source§

impl Clone for Tag

§Why the three traversals are written out rather than derived

The reasoning is on Scalar, and applies here for the same reason it applies to Drop: a tag’s children are tags, so a derived Clone, PartialEq or Debug recurses per level of a tree whose depth is attacker-controlled.

RenderableTreeNode and RenderableTreeNodes keep their derives, and that is safe because these exist: their recursion reaches a Tag or a Scalar in one step, and both stop there. Nothing here may call those derives on a nested tag, which is why the walks decompose them by hand.

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Tag

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Tag

Source§

fn default() -> Tag

Upstream’s default element is div, and schemas rely on it: a tag constructed with no name renders as a div rather than as nothing.

Source§

impl Drop for Tag

Dropping a renderable tree is iterative, for the reason dropping an AST is.

Node carries a manual Drop because nesting depth is attacker-controlled and the derived recursive drop aborts the process on a deep document. A renderable tree is built from that AST, one tag per nested tag, so it inherits the same exposure and needs the same guard. An abort cannot be caught, so the crate’s panic-freedom promise is not true without it.

One Drop covers the whole tree. A RenderableTreeNode and a RenderableTreeNodes are shallow wrappers whose derived drops recurse exactly one level before reaching a Tag, and this implementation unlinks every descendant onto the heap before any of them is dropped – so each tag it drops is already empty and recurses no further. Putting a manual Drop on the enums instead would forbid moving a tag out of one, which is what a renderer does on every node.

Scalar carries its own guard, below, for a different reason: its nesting is bounded for values this crate builds and unbounded for values a caller builds.

The cost, stated because it is invisible until someone hits it: a type with a manual Drop cannot have a field moved out of it, so taking ownership of Tag::children needs std::mem::take rather than a partial move. That is the same tax Node charges, paid for the same reason.

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more
Source§

impl From<Tag> for RenderableTreeNodes

Source§

fn from(tag: Tag) -> RenderableTreeNodes

Converts to this type from the input type.
Source§

impl PartialEq for Tag

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more

Auto Trait Implementations§

§

impl Freeze for Tag

§

impl RefUnwindSafe for Tag

§

impl Send for Tag

§

impl Sync for Tag

§

impl Unpin for Tag

§

impl UnsafeUnpin for Tag

§

impl UnwindSafe for Tag

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.