Skip to main content

Node

Struct Node 

Source
pub struct Node;
Expand description

The Node backend.

Trait Implementations§

Source§

impl Clone for Node

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 CodecTarget for Node

Source§

fn scalar(kind: Scalar) -> Self::Type

number to i32, bigint beyond it, a one-character string for a char — the boundary crate::emit::typescript::TypeScript::scalar draws, kept because it is the language’s own and not TypeScript’s.

Source§

fn named(name: &str) -> Self::Type

The tag, preserved exactly: this is how Node::cast recognises "signed char", and how a call site that names a type by its own spelling is answered honestly rather than folded into a generic tag that would hide the collision.

Source§

fn handle(_kind: Handle) -> Self::Type

Every runtime handle is a plain object; nothing casts one.

Source§

fn code_point(value: Self::Expr, _narrow: bool) -> Self::Expr

The member already is the code unit — a one-character string for both a char and a wchar — so there is nothing to convert.

Source§

fn constant(which: Constant) -> Self::Expr

The runtime’s policy tables, in runtime/node/zdwire.js’s own spelling — the same strings runtime/typescript’s enums answer with, since both runtimes were written against one clause and carry the measurements in crates/ast-layout/src/key.rs under one name apiece.

Source§

fn unsigned_holder(bits: u16) -> Self::Type

number to 32 bits, bigint at 64 — the same boundary Node::scalar draws for every other integer.

Source§

fn module_prefix(_ast: &Ast, _id: Id<TypeNode>) -> String

Nothing: the declared paths this backend writes go through Node::enumerator_constant, which flattens the whole scoped name into the one binding it names, so a prefix here would state the same thing twice.

Source§

fn escape(name: &str) -> String

The identity, always — zerodds_lang_cst::node::escape_member’s documentation carries why.

Source§

fn literal(value: Literal) -> Self::Expr

The raw tokens the walk escapes through Literal::Int, rewritten into the tree’s own boolean where they are one.

Source§

fn wide_int(value: i128) -> Self::Expr

A bigint literal: the number with a trailing n. Every value the walk hands here is one a number cannot carry exactly, so the suffix is unconditional.

Source§

fn unsigned_int(value: i128) -> Self::Expr

The number, with no suffix: JavaScript has one numeric literal grammar and no unsigned spelling — 2u is not a token.

Source§

fn wide_unsigned(value: u64) -> Self::Expr

123n, Node::wide_int’s spelling: the trait’s default is C’s UINT64_C(123), a macro no JavaScript file declares.

Source§

fn wide_signed(value: i128) -> Self::Expr

As Node::wide_unsigned: a bigint is unbounded, so a negative pattern is written as the negative number it is.

Source§

fn header_field(value: Self::Expr, field: &str) -> Self::Expr

A field of a header the runtime handed back, in the runtime’s own spelling — the same camelCase table crates/lang-rules/src/emit/typescript.rs’s override carries, because runtime/node/zdwire.js’s headers are plain objects with the same property names as runtime/typescript’s.

Source§

fn call(callee: &str, args: Vec<Self::Expr>) -> Self::Expr

strcmp is the walk’s name for a three-way code-unit comparison; JavaScript’s </> on strings already compare UTF-16 code units (ECMA-262 §7.2.13), so the spelling is a ternary — the same one crates/lang-rules/src/emit/typescript.rs writes, and the Java column’s caveat about supplementary code points applies unchanged.

A ternary and not the shorter (l < r) - (l > r): subtracting two relational results goes through Boolean’s numeric coercion, where true - false is 1 (ECMA-262 §7.1.4), so that form returns +1 for the case C11 §7.24.4 gives -1. The walk reads the result as strcmp(..) < 0, so the inverted sign puts a map’s entries on the wire in descending key order.

Source§

fn carries_hdds_axes() -> bool

runtime/node carries the three HDDS axes: beginPackedElement and finishPackedElement on the writer and the reader, the DHEADER pair for a sequence element’s own length, and writeWstringUtf8Octets / readWstringUtf8Octets.

Source§

fn runtime_static(method: &str, args: Vec<Self::Expr>) -> Self::Expr

A free function the generated file reaches through the runtime’s own object: zdwire.<method>(args).

Source§

fn member(base: &str, field: &str) -> Self::Expr

A field name with dots is a path through the members that hold a base (parent.x, XTypes 1.3 §7.5.1.4.1.3): one member step per segment.

Source§

fn inherited_path(depth: usize) -> Option<String>

The base is the first member parent (XTypes 1.3 §7.5.1.4.1.3).

Source§

fn index(value: Self::Expr, at: Self::Expr) -> Self::Expr

v[i] — a plain subscript; there is no noUncheckedIndexedAccess assertion to write outside TypeScript.

Source§

fn count_of(base: &str, fixed: Option<u64>) -> Self::Expr

.length, or the bound where the materialiser fixed one.

Source§

fn case_member(base: &str, field: &str) -> Self::Expr

v.one — a union’s branches sit beside _d on one plain object; nothing here needs the narrowing crate::emit::typescript::TypeScript::case_member’s Extract<> exists for, because nothing checks the type before the property is read.

Source§

fn materialised(_value: Self::Expr) -> Option<Self::Expr>

Nothing: every string and array this runtime materialises either exists or the read has already thrown — there is no allocator that can hand back an absent one for a codec to notice, exactly as crates/lang-rules/src/emit/lua.rs’s answer states for Lua’s tables.

Source§

fn optional_value( _ast: &Ast, _id: Id<TypeNode>, base: &str, field: &str, ) -> Self::Expr

The member itself: v.x is the value or the key is not there, and there is no wrapper to unwrap.

Source§

fn set_present(base: &str, field: &str, present: bool) -> Vec<Self::Stmt>

delete v.field for absence, and nothing for presence — writing the member is what makes it present, exactly as crates/lang-rules/src/emit/typescript.rs’s override reads; crate::default_node writes the same shape for the same clause.

Source§

fn clear_union_cases(base: &str, fields: &[String]) -> Vec<Self::Stmt>

delete v.field for every case: adapter/node.rs puts a union’s branches beside _d on one plain object, and a branch the discriminator does not select is a property that is not there. The same statement as an absent @optional member, Self::set_present with false.

Source§

fn binary(op: &'static str, lhs: Self::Expr, rhs: Self::Expr) -> Self::Expr

== becomes === and != becomes !==.

Not house style: JavaScript’s loose equality coerces across number and bigint inconsistently — 1 == 1n is true and 1 === 1n is false — and a discriminator compared with the loose form could match a label of the wrong holder. && and || are already this language’s own spelling and pass through unchanged, unlike crate::emit::lua::Lua::binary’s and/or.

Source§

fn unary(op: &'static str, value: Self::Expr) -> Self::Expr

Every operator as given: JavaScript has a real unary form for both ! and ~, so neither needs a stand-in.

Source§

fn cast(type_: Self::Type, value: Self::Expr) -> Self::Expr

A conversion where the target is one of the three scalar holders or the signed-char marker, a rewritten literal where the value is a boolean discriminator’s, and the value unchanged everywhere else — there is no as to fall back on and none is needed: a value this seam does not name a coercion for already carries the representation its destination wants.

"signed char" is the walk’s own reading of a map’s char key order: the member holds the code point as a string, so ((k.charCodeAt(0) + 128) % 256) - 128 is the two’s-complement wrap over its one octet — the same arithmetic crates/lang-rules/src/emit/python.rs’s signed_char writes and for the same reason.

Source§

fn store(place: Self::Expr, type_: Self::Type, value: Self::Expr) -> Self::Stmt

The same conversion, at the point a value reaches its member: the module documentation says why a wchar needs it here as well as at Node::cast’s own call sites.

Source§

fn read_call( callee: &str, place: Self::Expr, _form: Handoff, behaviour: Self::Expr, ) -> Self::Stmt

place = zd_dec_T(r, zd_tc); — this column’s decoders answer with the value, so the destination is the assignment’s left-hand side and never an out-parameter.

Source§

fn read_forward(callee: &str) -> Self::Stmt

v = zd_dec_T(r, zd_tc); — a typedef, handed straight on.

Source§

fn declare( type_: Self::Type, name: &str, value: Option<Self::Expr>, ) -> Self::Stmt

let name = value;, with an integer literal spelled the way the declared holder reads it — let bits = 0n; for a bigint accumulator, exactly as the walk’s own T::declare(T::scalar(Scalar::UInt64), "bits", int(0)) for a bitset needs.

Source§

fn mark_used(_name: &str) -> Vec<Self::Stmt>

Nothing: plain JavaScript has no unread-parameter diagnostic, and zd_tc; is not worth writing on its own.

Source§

fn drop_value(value: Self::Expr) -> Self::Stmt

void v; — the one form JavaScript has for “read and discard”, and the only place the walk needs it.

Source§

fn make_room( base: &str, _element: Self::Type, count: Self::Expr, assigned_whole: bool, fill: Vec<Self::Stmt>, ) -> Vec<Self::Stmt>

v = new Array(count);, and — for a map, whose entries are written half at a time — one {} per slot ahead of the fill, because v[i].key = … needs the slot object to exist first. A sequence’s element decoder assigns the slot outright and needs only the outer array.

Source§

fn storage(_type_: Self::Type, name: &str) -> Self::Stmt

let name = {}; — somewhere to put a value before its halves arrive, so zd_scratch.key = … does not assign onto undefined.

Source§

fn keep_first(base: &str, count: Self::Expr) -> Vec<Self::Stmt>

v.length = n;, which shortens an array in place. §7.3.1.2.1.12.3’s TRIM.

Source§

fn sequence_element( base: &str, index: Self::Expr, _element: Self::Type, ) -> (Vec<Self::Stmt>, Self::Expr, Vec<Self::Stmt>)

The subscript, with nothing around it: a JavaScript array element is a real place at every element type.

Source§

fn routine(spec: Routine<Self>) -> Option<Self::Decl>

function zd_enc_T(w, v) { … }, or the reading form that opens from Table 9 and returns the sample.

A top-level declaration, in module scope: nothing this column generates is exported, because the probe that runs it is a script and not a package.

Source§

fn default_into( ast: &Ast, id: Id<TypeNode>, place: Self::Expr, ) -> Result<Self::Stmt, EncodeError>

§Errors

Never; the signature matches the emitters around it.

Source§

fn member_default( ast: &Ast, node: &MemberNode, type_: Id<TypeNode>, place: Self::Expr, ) -> Result<Vec<Self::Stmt>, EncodeError>

§Errors

As crate::default_node::member_default: a @default this column cannot spell as a JavaScript expression is refused rather than silently replaced by Table 9’s zero.

Source§

fn enumerator_constant( ast: &Ast, id: Id<TypeNode>, enumerator: &str, ) -> Self::Expr

a_b_Colour.RED — the flattened frozen object crate::adapter::node declared, read from the file’s own top-level scope.

The trait’s default answers the bare enumerator name prefixed by Node::module_prefix, which is the empty string here — this column flattens a declared type’s whole scoped name into its one binding instead, and the enumerator lives inside that binding’s own object.

Source§

type Expr = Expr

An expression.
Source§

type Stmt = Stat

A statement.
Source§

type Block = Vec<Stat>

A sequence of statements.
Source§

type Type = NodeType

A type, as written in a declaration.
Source§

type Decl = Stat

A top-level declaration — in C a function, in Java a method.
Source§

fn nothing() -> Self::Type

What a codec function returns when it returns nothing.
Source§

fn value_type(ast: &Ast, id: Id<TypeNode>) -> Self::Type

How this target spells the type of id where a codec holds it. Read more
Source§

fn type_name(ast: &Ast, id: Id<TypeNode>) -> String

The name this target gives the type of id. Read more
Source§

fn map_entry_name(_ast: &Ast, _id: Id<TypeNode>) -> String

The name this target gives a map’s entry type. Read more
Source§

fn name(text: &str) -> Self::Expr

A bare name.
Source§

fn int(value: i128) -> Self::Expr

An integer literal.
Source§

fn runtime(receiver: &str, method: &str, args: Vec<Self::Expr>) -> Self::Expr

An operation on the runtime’s writer or reader. Read more
Source§

fn whole(base: &str) -> Self::Expr

The whole value the codec was handed, rather than one member. Read more
Source§

fn field_of(value: Self::Expr, field: &str) -> Self::Expr

A member of an expression.
Source§

fn elements(base: &str) -> Self::Expr

Where a sequence keeps the elements themselves. Read more
Source§

fn entry_half(entry: Self::Expr, key: bool) -> Self::Expr

One half of a map’s entry. Read more
Source§

fn absent() -> Self::Expr

The value that says a target holds nothing. Read more
Source§

fn present(base: &str, field: &str) -> Self::Expr

Whether an @optional member is present. Read more
Source§

fn optional_destination( base: &str, field: &str, ) -> (Vec<Self::Stmt>, Self::Expr)

Where a reader puts an @optional member’s value, and what it takes to have somewhere to put it. Read more
Source§

fn paren(value: Self::Expr) -> Self::Expr

Parentheses written on purpose. Read more
Source§

fn handoff(value: Self::Expr, _form: Handoff) -> Self::Expr

A value on its way into a nested codec. Read more
Source§

fn perform(value: Self::Expr) -> Self::Stmt

An expression evaluated for its effect.
Source§

fn give_back(value: Option<Self::Expr>) -> Self::Stmt

return, with or without a value.
Source§

fn when( condition: Self::Expr, then: Self::Block, otherwise: Option<Self::Block>, ) -> Self::Stmt

if (cond) { .. } else { .. }
Source§

fn count_up(counter: &str, bound: Self::Expr, body: Self::Block) -> Self::Stmt

A counted loop from zero to bound, exclusive. Read more
Source§

fn until(condition: Self::Expr, body: Self::Block) -> Self::Stmt

A loop with no counter. Read more
Source§

fn leave() -> Self::Stmt

Leave the enclosing loop.
Source§

fn note(doc: Doc) -> Self::Stmt

A comment on its own line.
Source§

fn block(statements: Vec<Self::Stmt>) -> Self::Block

Statements gathered into a body.
Source§

fn into_statements(block: Self::Block) -> Vec<Self::Stmt>

A body taken apart again. Read more
Source§

fn unsigned_less(octets: u8, left: Self::Expr, right: Self::Expr) -> Self::Expr

Whether left is less than right as unsigned integers of this width. Read more
Source§

fn bool_less(left: Self::Expr, right: Self::Expr) -> Self::Expr

Whether left is less than right as boolean map keys — false before true, the ascending-key order’s reading of the one-octet wire value. Read more
Source§

fn bit_pattern(source: BitPatternSource, value: Self::Expr) -> Self::Expr

The value’s storage bits, zero-extended into the runtime’s 64-bit pattern argument. See BitPatternSource; consumed by the runtime’s write_union_overlay, which writes the low octets of the pattern as one integer of that width in wire endianness — the Cyclone union overlay. Read more
Source§

fn bulk_octets_write(base: &str, count: Self::Expr) -> Option<Self::Stmt>

All of count octet elements of base at once, in place of the element loop of a sequence<octet> or a one-dimensional octet[N] (and the same over uint8); None, the default, keeps the loop. The octets are the loop’s: an octet has alignment 1 and no byte order (XTypes 1.3 §7.4.3.4.1), so a run of them is the same bytes however it is copied. What a target gains is the per-element call — measured in the C++ column: sequence<octet, 8192> element by element cost ~100 µs per roundtrip of four codec passes.
Source§

fn bulk_octets_read(base: &str, count: Self::Expr) -> Option<Self::Stmt>

The read side of Self::bulk_octets_write: count octets into base, which already holds room for them.
Source§

fn make_room_of( _ast: &Ast, _element_id: Id<TypeNode>, base: &str, element: Self::Type, count: Self::Expr, assigned_whole: bool, fill: Vec<Self::Stmt>, ) -> Vec<Self::Stmt>

CodecTarget::make_room for a sequence whose element is element_id. A target that cannot spell a slot’s start value from element alone overrides it: Kotlin’s Array(n) { T() } has no constructor to call where T is a typealias of Int.
Source§

fn open_array(base: &str, lengths: &[i128]) -> Vec<Self::Stmt>

Statements that make an array’s Table 9 default writable, before its elements are read into it; lengths are its dimensions, outermost first. Read more
Source§

fn close_array(base: &str, lengths: &[i128]) -> Vec<Self::Stmt>

Statements that give a read array the type its member declares, after its last element is read. Nothing by default; see CodecTarget::open_array.
Source§

fn discriminant(base: &str) -> Self::Expr

A union’s discriminant. Read more
Source§

fn enumerator_ordinal( ast: &Ast, id: Id<TypeNode>, value: Self::Expr, ) -> Self::Expr

The integer an enumeration’s value carries, given the value. Read more
Source§

fn case_label(ast: &Ast, discriminator: Id<TypeNode>, value: i128) -> Self::Expr

The value a union case label is compared against, in this target’s spelling of the discriminator’s type. Read more
Source§

fn behind_indirection( ast: &Ast, id: Id<TypeNode>, place: Self::Expr, ) -> Self::Expr

The place a member is reached at, given that the column could not put the member’s value inside its own aggregate. Read more
Source§

fn make_indirection( ast: &Ast, id: Id<TypeNode>, place: Self::Expr, ) -> (Vec<Self::Stmt>, Self::Expr)

The reading counterpart of CodecTarget::behind_indirection: the same place, and what has to happen before a reader can write through it. Read more
Source§

fn holds_by_reference( ast: &Ast, aggregate: Id<TypeNode>, member_type: Id<TypeNode>, optional: bool, external: bool, ) -> bool

Whether this column holds an @optional or @external member of aggregate, of type member_type, behind a reference of its own — where the shared walk would reach it through CodecTarget::present, CodecTarget::optional_value and their external_ counterparts. A member this answers for goes through CodecTarget::reference_present, CodecTarget::reference_value, CodecTarget::reference_destination and CodecTarget::reference_absent instead. Read more
Source§

fn reference_present(base: &str, field: &str) -> Self::Expr

Whether a member CodecTarget::holds_by_reference answers for is present. Reached only where that answered true.
Source§

fn reference_value( ast: &Ast, id: Id<TypeNode>, base: &str, field: &str, ) -> Self::Expr

The value behind such a member, given that it is present.
Source§

fn reference_destination( ast: &Ast, id: Id<TypeNode>, base: &str, field: &str, ) -> (Vec<Self::Stmt>, Self::Expr)

Where a reader puts such a member’s value, and what it takes to have somewhere to put it; id is the member’s type.
Source§

fn reference_absent(base: &str, field: &str) -> Vec<Self::Stmt>

The statements that leave such a member absent.
Source§

fn holds_a_cycle_externally() -> bool

Whether this column keeps a member that closes a type cycle the way it keeps an @external one — through the external_ seams below, whether or not the member carries the annotation. Read more
Source§

fn externals_are_pointers() -> bool

Whether this column holds an @external member behind a pointer of its own, where the member’s value is not a pointer already. Read more
Source§

fn optionals_are_pointers() -> bool

Whether this column holds an @optional member behind a pointer of its own, where the member’s value is not a pointer already. Read more
Source§

fn value_is_pointer(ast: &Ast, id: Id<TypeNode>) -> bool

Whether the column’s value of id is a pointer already, so that an @external or @optional member of that type needs no pointer of its own. C’s string, wstring and fixed are const char * (XTypes 1.3 §7.5.1.2.3.1); a C++ std::string is a value.
Source§

fn refuse_unset_external(present: Self::Expr) -> Vec<Self::Stmt>

Statements that stop a writer from going on when an @external member that is not @optional has no value at the time of the write. Read more
Source§

fn external_value( ast: &Ast, id: Id<TypeNode>, base: &str, field: &str, optional: bool, ) -> Self::Expr

The value of an @external member, as the member’s codec takes it. Read more
Source§

fn external_destination( base: &str, field: &str, optional: bool, ) -> (Vec<Self::Stmt>, Self::Expr)

Where a reader puts an @external member’s value, and what it takes to have somewhere to put it. The reading counterpart of CodecTarget::external_value, shaped like CodecTarget::optional_destination and for the same reason: a column whose member is an indirection has to make storage before there is a value to write into. The default is the walk’s old answer for both combinations.
Source§

fn external_present(base: &str, field: &str) -> Self::Expr

Whether an @optional @external member is present. Read more
Source§

fn external_set_present( base: &str, field: &str, present: bool, ) -> Vec<Self::Stmt>

Say that an @optional @external member is present, or is not. The counterpart of CodecTarget::set_present, split for the reason CodecTarget::external_present gives.
Source§

fn external_case_value( ast: &Ast, id: Id<TypeNode>, base: &str, field: &str, ) -> Self::Expr

The value of an @external union branch, as the branch’s codec takes it. The union counterpart of CodecTarget::external_value, reached through CodecTarget::case_member because that is the accessor a branch has; there is no optional parameter because no union member is @optional (DDS-XTypes 1.3 §7.2.2.4.4.4.7). The default is the accessor itself — the columns that keep the value inline — and a column that keeps an indirection answers with the dereference, exactly as it does for a structure member.
Source§

fn external_case_destination( base: &str, field: &str, ) -> (Vec<Self::Stmt>, Self::Expr)

Where a reader puts an @external union branch’s value, and what it takes to have somewhere to put it. The union counterpart of CodecTarget::external_destination, shaped the same way and defaulted the same way.
Source§

fn published_name(name: String) -> String

One generated name, in the spelling this target publishes it under. Read more
Source§

fn initialized_reader( _spec: Routine<Self>, _initializer: Self::Stmt, ) -> Option<Self::Decl>

A new reader entry with an explicit, target-derived initializer. Targets that cannot preserve this contract refuse the new entry only; existing data routines and their initialization remain unchanged.
Source§

fn bitmask_value(ast: &Ast, id: Id<TypeNode>, value: Self::Expr) -> Self::Expr

The 64-bit pattern a bitmask arrives as, in the bitmask’s own declared type. Read more
Source§

fn map_entry_type(ast: &Ast, id: Id<TypeNode>) -> Self::Type

The type a map’s entry is declared with — the reader’s scratch entry and make_room’s element. Read more
Source§

impl Copy for Node

Source§

impl Debug for Node

Source§

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

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

impl Eq for Node

Source§

impl PartialEq for Node

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
Source§

impl StructuralPartialEq for Node

Auto Trait Implementations§

§

impl Freeze for Node

§

impl RefUnwindSafe for Node

§

impl Send for Node

§

impl Sync for Node

§

impl Unpin for Node

§

impl UnsafeUnpin for Node

§

impl UnwindSafe for Node

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.