pub struct TypeScript;Expand description
The TypeScript backend.
Trait Implementations§
Source§impl Clone for TypeScript
impl Clone for TypeScript
Source§impl CodecTarget for TypeScript
impl CodecTarget for TypeScript
Source§fn scalar(kind: Scalar) -> Self::Type
fn scalar(kind: Scalar) -> Self::Type
number to i32, bigint beyond it.
Not a style: Number.MAX_SAFE_INTEGER is 2^53 − 1, so a
number holds every i32 and every u32 exactly and neither
i64 nor u64. An index and a size are number because a
collection’s length is one.
The same boundary adapter/typescript.rs draws for a member’s
declared type and runtime/typescript for its parameters.
Three places have to agree.
ts::Type::Keyword and not a named path spelled "number".
The two render the same text and are not the same tree, and the
materialiser builds the keyword: a backend that built the path
answered false to every type == ts::Type::number() a caller
asked, which is how a holder decision gets made twice and
differently.
Source§fn handle(kind: Handle) -> Self::Type
fn handle(kind: Handle) -> Self::Type
The runtime’s handles, by their exported names.
A generated file imports them, so the simple name is what it
writes; runtime/typescript exports each as an interface rather
than nesting it in the writer, because TypeScript has no nested
type in a class the way Java does.
Source§fn code_point(value: Self::Expr, _narrow: bool) -> Self::Expr
fn code_point(value: Self::Expr, _narrow: bool) -> Self::Expr
A string of one character is what a char is here.
codePointAt(0) is the runtime’s, not the generated file’s: the
narrowing a char needs belongs where the octet is written.
Source§fn constant(which: Constant) -> Self::Expr
fn constant(which: Constant) -> Self::Expr
The runtime’s enumerations, in TypeScript’s naming.
One member per constant and no catch-all: a policy this column has not implemented has to be a compile error here rather than a value that looks plausible.
Source§fn unsigned_holder(bits: u16) -> Self::Type
fn unsigned_holder(bits: u16) -> Self::Type
An unsigned holder is a number to 32 bits and a bigint at
64, for the reason Self::scalar gives.
Source§fn bitmask_value(ast: &Ast, id: Id<TypeNode>, value: Self::Expr) -> Self::Expr
fn bitmask_value(ast: &Ast, id: Id<TypeNode>, value: Self::Expr) -> Self::Expr
zdNumber(zd_bits) as Flags — the holder conversion first, the
alias after.
The trait’s one cast is zd_bits as Flags, and Flags here is
type Flags = number for a bound to 32 bits while the read
answers a bigint: as between the two is TS2352, because as
is erased and would have left the value a bigint besides. The
runtime conversion through Self::unsigned_holder’s keyword is
the same one every bitset field takes.
Source§fn value_type(ast: &Ast, id: Id<TypeNode>) -> Self::Type
fn value_type(ast: &Ast, id: Id<TypeNode>) -> Self::Type
The TypeScript type of a value of id.
Not Self::type_name, which is the codec’s tag —
p_long, seq_long — and names a function, not a type. A
parameter declared v: long is a reference to a type
TypeScript does not have, and tsc says so; it was what the
first generated codec of this column wrote.
Not adapter/typescript.rs’s ts_member_type either: that one
needs the rule application to spell a member’s declared type,
which a codec does not have and does not need. A structural
walk is enough here, and the two agree on every shape because
both read the same model.
Source§fn inherited_path(depth: usize) -> Option<String>
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 wide_int(value: i128) -> Self::Expr
fn wide_int(value: i128) -> Self::Expr
A bigint literal, which is a number with an n after it.
Every value the walk hands here is one a number cannot carry —
that is what makes it wide — so the suffix is unconditional.
Source§fn unsigned_int(value: i128) -> Self::Expr
fn unsigned_int(value: i128) -> Self::Expr
The number, with no suffix.
The trait’s default is C’s 123u. TypeScript has one numeric
type and no suffix for it, and 2u is not an expression at all:
tsc calls it TS1351, “an identifier or keyword cannot
immediately follow a numeric literal”. Every array bound and
every string bound the decode walk writes goes through here.
Source§fn header_field(value: Self::Expr, field: &str) -> Self::Expr
fn header_field(value: Self::Expr, field: &str) -> Self::Expr
A field of a header the runtime handed back, in the runtime’s spelling.
The walk names a header’s parts in the wire’s convention —
member_id, must_understand — and runtime/typescript spells
them as TypeScript properties. The names are listed rather than
run through Self::camel so that a part the runtime does not
publish is visible here: it becomes a tsc error naming the
property, which is where a header that grew a part shows up.
Source§fn call(callee: &str, args: Vec<Self::Expr>) -> Self::Expr
fn call(callee: &str, args: Vec<Self::Expr>) -> Self::Expr
strcmp is the walk’s name for a three-way code-unit
comparison; TypeScript’s </> on strings compare UTF-16 code
units, so the spelling is a ternary — the Java column’s caveat
about supplementary code points applies unchanged.
Source§fn carries_hdds_axes() -> bool
fn carries_hdds_axes() -> bool
runtime/typescript 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
fn runtime_static(method: &str, args: Vec<Self::Expr>) -> Self::Expr
A free function the generated file imports from the runtime.
TypeScript has module-level functions, so unlike Java there is no class to hang them on.
Source§fn index(value: Self::Expr, at: Self::Expr) -> Self::Expr
fn index(value: Self::Expr, at: Self::Expr) -> Self::Expr
v[i]!, with the non-null assertion.
runtime/typescript/tsconfig.json compiles under
noUncheckedIndexedAccess, where v[i] is T | undefined
however the loop is bounded — the checker does not relate i to
v.length. Every index the walk builds is inside a loop it
bounded itself with that very length, so the assertion states
something the generated code has already established.
Written here rather than turning the setting off, because a
generated file that only compiles under looser settings is one a
consumer who has that setting on cannot use. It is the one place
this column writes a !.
The read direction will need an lvalue form: v[i]! = x is not
an assignment target. emit/typescript.rs refuses to generate a
decoder at all today — default_into says so by name — and the
module that lifts that refusal has this to solve.
Source§fn count_of(base: &str, fixed: Option<u64>) -> Self::Expr
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
fn case_member(base: &str, field: &str) -> Self::Expr
(v as Extract<typeof v, { one: unknown }>).one
Not v.one. A union is a discriminated union here and not a
struct with every branch’s field in it, which is what the C and
Java columns have — so a case member lives on one arm only and
reaching it needs the value narrowed to that arm. Both
directions need it, for different reasons, and the two were
found independently by the read and the write halves of this
column before they were merged:
- Reading. TypeScript refuses
v.one = …on a union-typedv:oneis in one arm and_dis in all of them, so the discriminator assigns and the selected member does not. TS2339 on every union the walk reads. - Writing. Narrowing on the discriminator is what the walk’s
ifalready writes, and it is not enough for either of the two shapes the corpus has: adefault:arm carries the discriminator’s whole type, sov._d === 1leaves both arms live — TypeScript cannot spell “anumberthat is not 1” — and the no-case-selected arm{ _d: number }has the same effect on every union with nodefault:.
So this is not a spelling: it is the shape adapter/typescript.rs
deliberately chose so that a reader of the value narrows on _d.
Extract<typeof v, { <field>: unknown }> names the one arm that
has the field, so the access is checked against the member’s own
declared type rather than through an any that would check
nothing. typeof v is the declared type and not the narrowed
one, which is what makes it the same expression in both
directions.
Source§fn discriminant(base: &str) -> Self::Expr
fn discriminant(base: &str) -> Self::Expr
v.discriminator, which is the name DDS-TS 1.0 §7.5 gives the
property and the one adapter/typescript.rs declares. The
trait’s default is _d, which is what the other columns’
materialisers call it.
Source§fn enumerator_ordinal(
ast: &Ast,
id: Id<TypeNode>,
value: Self::Expr,
) -> Self::Expr
fn enumerator_ordinal( ast: &Ast, id: Id<TypeNode>, value: Self::Expr, ) -> Self::Expr
a.b.StatusOrdinal[v] — the wire value an enumerator carries.
§7.6 makes an enumeration a string-literal union, so this column
has no integer in the variable at all: the other columns’ answer
(the value itself) would put the first code unit of the
enumerator’s name on the wire. Measured against the ledger,
enum-sparse-values wrote 70 79 87 for FAIL OK WARN before
this override existed, where the recorded octets are
65535 1 100.
The table is the materialiser’s — adapter/typescript.rs’s
ordinal_path names it — so the codec looks the value up rather
than deriving it a second time from the model.
The identity answer is required and not a safety net. Two of
the three callers pass a type that is often not an enumeration
at all: encode::write_union_overlay’s suppressed arm hands
every BitPatternSource::Int through this seam — a long arm
among them — and encode::map_key_less hands a map key through
it whenever the ordering is by enumerator value. For those the
integer is already in the variable and the table would name
nothing.
The remaining door — an enumeration whose table cannot be
named — is a model adapter::typescript::ts_items has already
refused: ordinal_path fails there only through qualified,
and assemble’s insert walks the same module_chain for
every declaration before a file exists.
Source§fn case_label(ast: &Ast, discriminator: Id<TypeNode>, value: i128) -> Self::Expr
fn case_label(ast: &Ast, discriminator: Id<TypeNode>, value: i128) -> Self::Expr
a.b.Tag.TAG_A for an enumeration discriminator, and the trait’s
narrowed literal for every other kind.
§7.6 makes an enumeration a string-literal union, so the ordinal
is not a value of the type: v.discriminator === 1 against a
"TAG_A" | "TAG_B" is TS2367, “the types have no overlap”, on
every enumeration-discriminated union. The constant is also what
narrows the arm — comparison against a literal-typed const is
what TypeScript reads as a discriminant test.
A label that names no enumerator falls back to the trait’s
answer, which tsc then reports: there is no member for it, and
a number written in its place would compile against no arm at
all.
Source§fn materialised(value: Self::Expr) -> Option<Self::Expr>
fn materialised(value: Self::Expr) -> Option<Self::Expr>
!== undefined, which is what an absent @optional member is
here: adapter/typescript.rs declares one field?: T, so the
property is missing rather than null.
Source§fn optional_value(
_ast: &Ast,
_id: Id<TypeNode>,
base: &str,
field: &str,
) -> Self::Expr
fn optional_value( _ast: &Ast, _id: Id<TypeNode>, base: &str, field: &str, ) -> Self::Expr
The member itself: field?: T is the value or nothing, and
there is no wrapper to unwrap the way Java’s boxed field has.
Source§fn set_present(base: &str, field: &str, present: bool) -> Vec<Self::Stmt>
fn set_present(base: &str, field: &str, present: bool) -> Vec<Self::Stmt>
delete v.field for absence, and nothing for presence.
Not v.field = undefined. The declaration is field?: T and the
tree compiles under exactOptionalPropertyTypes, where assigning
undefined to an optional property is TS2412 — the property
being gone and the property holding undefined are two things
there. delete is also what crate::default_typescript writes
for the same clause, so a decoder and a defaulter cannot part
over what absent means.
Source§fn clear_union_cases(base: &str, fields: &[String]) -> Vec<Self::Stmt>
fn clear_union_cases(base: &str, fields: &[String]) -> Vec<Self::Stmt>
delete (v as { field?: unknown }).field for every case.
DDS-TS 1.0 §7.5 makes a union a discriminated union of object
types, one per case, so a branch the discriminator does not
select is a property the object does not have. The Table 9
default the decoder starts from carries the default branch’s
property, and without this a sample read with another
discriminator kept it (measured: idl-conformance/_interop
combo, reading came back with idleTicks: 0 beside
activeRate). The union type names no property shared by every
variant, so the operand is widened to an object whose one
property is optional — the form delete accepts (TS2790).
Source§fn binary(op: &'static str, lhs: Self::Expr, rhs: Self::Expr) -> Self::Expr
fn binary(op: &'static str, lhs: Self::Expr, rhs: Self::Expr) -> Self::Expr
== becomes === and != becomes !==.
Not house style. TypeScript narrows a discriminated union on the
strict comparison of its discriminant against a literal, and
a union case member is only reachable through that narrowing:
if (v._d == 1) { w.writeI32(v.whole) } is
TS2339: Property 'whole' does not exist, and the same line with
=== compiles. Measured on array-1d-union.
The loose form is also a different operator — 0 == "0" is true
— so a discriminator that arrived as a string would select an
arm no other column selects.
Source§fn unary(op: &'static str, value: Self::Expr) -> Self::Expr
fn unary(op: &'static str, value: Self::Expr) -> Self::Expr
!a as written, and every other operator as itself.
TypeScript has a real unary form for both ! and ~, so
neither needs the 0 <op> a stand-in that cost the C++ column
twenty-one cases.
Source§fn bool_less(left: Self::Expr, right: Self::Expr) -> Self::Expr
fn bool_less(left: Self::Expr, right: Self::Expr) -> Self::Expr
false before true, spelled as the conjunction — TypeScript’s
< does not take two booleans (TS2365).
Source§fn cast(type_: Self::Type, value: Self::Expr) -> Self::Expr
fn cast(type_: Self::Type, value: Self::Expr) -> Self::Expr
A conversion where the target is one of the three scalar holders,
a rewritten literal where the value is one, and as T elsewhere.
as is erased. Every other column’s narrowing is a real
operation — (int) in Java, static_cast in C++ — and writing
as for those would be two defects at once. tsc refuses the
erased form outright where the holders differ:
zd_bits as number on a bigint is TS2352, which the decode
walk emits for every bitmask and every bitset field and the
encode walk for every bitmask, bitset and union case. And where
it does not refuse — x as unknown as number — the value would
go into the field still a bigint, and every later comparison
against it would be false.
So the three holders take a runtime conversion:
zdNumber, zdBigInt and zdChar in runtime/typescript,
which carry the same value into number, bigint and the
one-character string an IDL char is here. Each is the
identity on a value already in its holder.
A literal is rewritten at generation time instead, and that
is not an optimisation. Two things need it, and both are the
encode walk’s union labels — cast(value_type(discriminator), wide_int(label)):
- a
booleanor enumeration discriminator reaches no coercion arm, because its holder isbooleanor the materialiser’stype Colour = number, and1n as booleanand1n as a.b.Colourare both TS2352; - a literal type is what a union arm is narrowed on, and
v._d === zdNumber(1n)narrows nothing whilev._d === 1narrows to the arm.
The four forms are the four adapter/typescript.rs’s
discriminant_literal writes, read off the target type rather
than off the model — a third reading of that mapping is how the
declaration and the comparison come to describe different arms.
Source§fn store(place: Self::Expr, type_: Self::Type, value: Self::Expr) -> Self::Stmt
fn store(place: Self::Expr, type_: Self::Type, value: Self::Expr) -> Self::Stmt
The same conversion, at the point a value reaches its member.
Self::cast answers the walk where the walk asked for a
narrowing; this answers where it did not. A wchar is the one
that needs it: the walk narrows the runtime’s answer to the
sixteen-bit storage every other column keeps a wchar in, and
this column keeps it in a string, so the value arrives as a
number and the destination is a string. Without the second
conversion that is a tsc error on every wchar member.
Source§fn read_call(
callee: &str,
place: Self::Expr,
_form: Handoff,
behaviour: Self::Expr,
) -> Self::Stmt
fn read_call( callee: &str, place: Self::Expr, _form: Handoff, behaviour: Self::Expr, ) -> Self::Stmt
place = zd_dec_T(r, zd_tc);
The trait’s default hands the destination to the callee, which
is C’s shape: its decoder takes a T * and fills it. A
TypeScript function has no out-parameter, so this column’s
decoders answer with the value — Self::routine declares them
(r, …extra) — and the destination is assigned at the call site.
Without this override the generated call was
zd_dec_p_long(r, v.a, TryConstruct.Discard): three arguments to
a two-parameter function, and — had it compiled — a member read
off the wire and thrown away, leaving Table 9’s value in v.a
with nothing to say so.
Source§fn read_forward(callee: &str) -> Self::Stmt
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
fn declare( type_: Self::Type, name: &str, value: Option<Self::Expr>, ) -> Self::Stmt
let name: T = value, with an integer literal spelled the way
T reads it.
let bits: bigint = 0 does not typecheck — 0 is a number —
and the walk declares exactly that for a bitset’s accumulator:
T::declare(T::scalar(Scalar::UInt64), "bits", int(0)). The n
is not a suffix the walk can add, because in C and Java the same
declaration is right as it stands. adapter/typescript.rs writes
k: bigint = 0n for a member of the same type and for the same
reason.
Source§fn mark_used(_name: &str) -> Vec<Self::Stmt>
fn mark_used(_name: &str) -> Vec<Self::Stmt>
Nothing. TypeScript has no unread-parameter diagnostic under the
settings this tree compiles with, and zd_tc; is not a
statement worth writing.
Source§fn drop_value(value: Self::Expr) -> Self::Stmt
fn drop_value(value: Self::Expr) -> Self::Stmt
void v; — the one form TypeScript 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>
fn make_room( base: &str, element: Self::Type, count: Self::Expr, assigned_whole: bool, fill: Vec<Self::Stmt>, ) -> Vec<Self::Stmt>
A new array of count elements, which a TypeScript collection
is: there is no reserve-then-fill, so the fill is the loop the
walk hands over.
new Array(n) is n holes. A sequence’s element decoder answers
with a value and the slot is assigned outright, so nothing more
is needed; a map’s two halves are written into the entry at
v[i], and an entry that was never made is a TypeError at the
first key — measured on map-key-long, “Cannot set properties
of undefined”. That is what assigned_whole separates, exactly
as the Java column’s make_room says, and the seed is the empty
object whose halves the loop assigns before anything reads them.
Source§fn storage(type_: Self::Type, name: &str) -> Self::Stmt
fn storage(type_: Self::Type, name: &str) -> Self::Stmt
let name: T = {} as T; — somewhere to put a value before its
halves arrive.
The trait’s default declares without a value, which TypeScript
under strict reads as “used before assigned” the moment a
map’s counting pass writes zd_scratch.key — and at run time
the property assignment lands on undefined. The empty object
is a seed whose properties the very next statements fill.
Source§fn keep_first(base: &str, count: Self::Expr) -> Vec<Self::Stmt>
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. A TypeScript array’s length is writable
and assigning a smaller one drops the tail, which is exactly the
operation and is why this column needs no splice.
Source§fn routine(spec: Routine<Self>) -> Option<Self::Decl>
fn routine(spec: Routine<Self>) -> Option<Self::Decl>
export function encodeT(w: Writer, v: T): void.
Exported. A generated file is one module, and a module-level
function that is not exported is reachable from nothing outside
that file: wireprobe-zerodds-typescript-gen never noticed
because it appends its own main to the same module, and an
application generated by idlc generate has no way to call a
single one of them. The same defect the Java column carried as
private static and was measured out of; the declarations
beside these — newT, isT, the interfaces — were exported all
along.
Source§fn default_into(
ast: &Ast,
id: Id<TypeNode>,
place: Self::Expr,
) -> Result<Self::Stmt, EncodeError>
fn default_into( ast: &Ast, id: Id<TypeNode>, place: Self::Expr, ) -> Result<Self::Stmt, EncodeError>
A call to a generated defaulter and not a literal in place.
A literal cannot carry an aggregate, and one written at every
position a member can go missing would put the same answer in the
file as many times as the type is reached — where two copies can
differ. crate::default_typescript carries the whole table and
the argument.
§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>
fn member_default( ast: &Ast, node: &MemberNode, type_: Id<TypeNode>, place: Self::Expr, ) -> Result<Vec<Self::Stmt>, EncodeError>
§Errors
As crate::default_typescript::member_default: a @default
this column cannot spell as a TypeScript 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
fn enumerator_constant( ast: &Ast, id: Id<TypeNode>, enumerator: &str, ) -> Self::Expr
a.b.Colour.RED — the as const object the materialiser
declared, written from the file root.
The trait’s default answers the bare enumerator name, which is
right for a target that flattens its modules into a prefix and
wrong here: the TypeScript materialiser nests each declaration in
a namespace per IDL module and a generated codec sits at the file
root, so RED there resolves to nothing — or, worse, to whatever
else happened to be in scope.
Source§fn wide_unsigned(value: u64) -> Self::Expr
fn wide_unsigned(value: u64) -> Self::Expr
123n, which is how TypeScript spells a 64-bit constant.
The trait’s default is C’s UINT64_C(123), which is a macro no
TypeScript file declares. Both of these reach the generated
source through the decode walk alone — the bitmask’s
undeclared-bit check and the enumerator chain — so a column that
did not override them produced a decoder that did not parse.
Source§fn wide_signed(value: i128) -> Self::Expr
fn wide_signed(value: i128) -> Self::Expr
As Self::wide_unsigned, and the value rather than the
two’s-complement pattern: a bigint is unbounded, so a negative
enumerator pattern is written as the negative number it is.
Source§fn type_name(ast: &Ast, id: Id<TypeNode>) -> String
fn type_name(ast: &Ast, id: Id<TypeNode>) -> String
id. Read moreSource§fn map_entry_name(ast: &Ast, id: Id<TypeNode>) -> String
fn map_entry_name(ast: &Ast, id: Id<TypeNode>) -> String
map’s entry type. Read moreSource§fn module_prefix(_ast: &Ast, _id: Id<TypeNode>) -> String
fn module_prefix(_ast: &Ast, _id: Id<TypeNode>) -> String
Source§fn escape(name: &str) -> String
fn escape(name: &str) -> String
Source§fn runtime(receiver: &str, method: &str, args: Vec<Self::Expr>) -> Self::Expr
fn runtime(receiver: &str, method: &str, args: Vec<Self::Expr>) -> Self::Expr
Source§fn member(base: &str, field: &str) -> Self::Expr
fn member(base: &str, field: &str) -> Self::Expr
Source§fn whole(base: &str) -> Self::Expr
fn whole(base: &str) -> Self::Expr
Source§fn elements(base: &str) -> Self::Expr
fn elements(base: &str) -> Self::Expr
Source§fn entry_half(entry: Self::Expr, key: bool) -> Self::Expr
fn entry_half(entry: Self::Expr, key: bool) -> Self::Expr
map’s entry. Read moreSource§fn present(base: &str, field: &str) -> Self::Expr
fn present(base: &str, field: &str) -> Self::Expr
@optional member is present. Read moreSource§fn optional_destination(
base: &str,
field: &str,
) -> (Vec<Self::Stmt>, Self::Expr)
fn optional_destination( base: &str, field: &str, ) -> (Vec<Self::Stmt>, Self::Expr)
@optional member’s value, and what it
takes to have somewhere to put it. Read moreSource§fn handoff(value: Self::Expr, _form: Handoff) -> Self::Expr
fn handoff(value: Self::Expr, _form: Handoff) -> Self::Expr
Source§fn when(
condition: Self::Expr,
then: Self::Block,
otherwise: Option<Self::Block>,
) -> Self::Stmt
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
fn count_up(counter: &str, bound: Self::Expr, body: Self::Block) -> Self::Stmt
bound, exclusive. Read moreSource§fn until(condition: Self::Expr, body: Self::Block) -> Self::Stmt
fn until(condition: Self::Expr, body: Self::Block) -> Self::Stmt
Source§fn sequence_element(
base: &str,
index: Self::Expr,
_element: Self::Type,
) -> (Vec<Self::Stmt>, Self::Expr, Vec<Self::Stmt>)
fn sequence_element( base: &str, index: Self::Expr, _element: Self::Type, ) -> (Vec<Self::Stmt>, Self::Expr, Vec<Self::Stmt>)
Source§fn bit_pattern(source: BitPatternSource, value: Self::Expr) -> Self::Expr
fn bit_pattern(source: BitPatternSource, value: Self::Expr) -> Self::Expr
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 moreSource§fn bulk_octets_write(base: &str, count: Self::Expr) -> Option<Self::Stmt>
fn bulk_octets_write(base: &str, count: Self::Expr) -> Option<Self::Stmt>
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>
fn bulk_octets_read(base: &str, count: Self::Expr) -> Option<Self::Stmt>
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>
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>
fn open_array(base: &str, lengths: &[i128]) -> Vec<Self::Stmt>
lengths are its dimensions,
outermost first. Read moreSource§fn close_array(base: &str, lengths: &[i128]) -> Vec<Self::Stmt>
fn close_array(base: &str, lengths: &[i128]) -> Vec<Self::Stmt>
CodecTarget::open_array.Source§fn behind_indirection(
ast: &Ast,
id: Id<TypeNode>,
place: Self::Expr,
) -> Self::Expr
fn behind_indirection( ast: &Ast, id: Id<TypeNode>, place: Self::Expr, ) -> Self::Expr
Source§fn make_indirection(
ast: &Ast,
id: Id<TypeNode>,
place: Self::Expr,
) -> (Vec<Self::Stmt>, Self::Expr)
fn make_indirection( ast: &Ast, id: Id<TypeNode>, place: Self::Expr, ) -> (Vec<Self::Stmt>, Self::Expr)
CodecTarget::behind_indirection:
the same place, and what has to happen before a reader can write
through it. Read moreSource§fn holds_by_reference(
ast: &Ast,
aggregate: Id<TypeNode>,
member_type: Id<TypeNode>,
optional: bool,
external: bool,
) -> bool
fn holds_by_reference( ast: &Ast, aggregate: Id<TypeNode>, member_type: Id<TypeNode>, optional: bool, external: bool, ) -> bool
@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 moreSource§fn reference_present(base: &str, field: &str) -> Self::Expr
fn reference_present(base: &str, field: &str) -> Self::Expr
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
fn reference_value( ast: &Ast, id: Id<TypeNode>, base: &str, field: &str, ) -> Self::Expr
Source§fn reference_destination(
ast: &Ast,
id: Id<TypeNode>,
base: &str,
field: &str,
) -> (Vec<Self::Stmt>, Self::Expr)
fn reference_destination( ast: &Ast, id: Id<TypeNode>, base: &str, field: &str, ) -> (Vec<Self::Stmt>, Self::Expr)
id is the member’s type.Source§fn reference_absent(base: &str, field: &str) -> Vec<Self::Stmt>
fn reference_absent(base: &str, field: &str) -> Vec<Self::Stmt>
Source§fn holds_a_cycle_externally() -> bool
fn holds_a_cycle_externally() -> bool
@external one — through the external_ seams
below, whether or not the member carries the annotation. Read moreSource§fn externals_are_pointers() -> bool
fn externals_are_pointers() -> bool
@external member behind a pointer
of its own, where the member’s value is not a pointer already. Read moreSource§fn optionals_are_pointers() -> bool
fn optionals_are_pointers() -> bool
@optional member behind a pointer
of its own, where the member’s value is not a pointer already. Read moreSource§fn value_is_pointer(ast: &Ast, id: Id<TypeNode>) -> bool
fn value_is_pointer(ast: &Ast, id: Id<TypeNode>) -> bool
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>
fn refuse_unset_external(present: Self::Expr) -> Vec<Self::Stmt>
@external
member that is not @optional has no value at the time of the
write. Read moreSource§fn external_value(
ast: &Ast,
id: Id<TypeNode>,
base: &str,
field: &str,
optional: bool,
) -> Self::Expr
fn external_value( ast: &Ast, id: Id<TypeNode>, base: &str, field: &str, optional: bool, ) -> Self::Expr
@external member, as the member’s codec takes
it. Read moreSource§fn external_destination(
base: &str,
field: &str,
optional: bool,
) -> (Vec<Self::Stmt>, Self::Expr)
fn external_destination( base: &str, field: &str, optional: bool, ) -> (Vec<Self::Stmt>, Self::Expr)
@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
fn external_present(base: &str, field: &str) -> Self::Expr
@optional @external member is present. Read moreSource§fn external_set_present(
base: &str,
field: &str,
present: bool,
) -> Vec<Self::Stmt>
fn external_set_present( base: &str, field: &str, present: bool, ) -> Vec<Self::Stmt>
@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
fn external_case_value( ast: &Ast, id: Id<TypeNode>, base: &str, field: &str, ) -> Self::Expr
@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)
fn external_case_destination( base: &str, field: &str, ) -> (Vec<Self::Stmt>, Self::Expr)
@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.