pub struct Fsharp;Expand description
The F# backend.
Trait Implementations§
Source§impl CodecTarget for Fsharp
impl CodecTarget for Fsharp
Source§fn scalar(kind: Scalar) -> Self::Type
fn scalar(kind: Scalar) -> Self::Type
The fixed-width F# type each scalar local takes. Index is
uint32 — a sequence length is a uint32 on the wire — and
Size is int32, which is what a .NET array’s own Length and
a byte position are held in.
Source§fn code_point(value: Self::Expr, narrow: bool) -> Self::Expr
fn code_point(value: Self::Expr, narrow: bool) -> Self::Expr
A char’s member already is the runtime’s own type — byte,
which is what ZdWire.Writer.WriteChar takes — and there is
nothing to convert.
A wchar’s member is a uint16 and WriteWchar takes a code
point as int, because the four-octet form of §7.4.1.1.1 Table
30 is not a uint16 on the wire. F# converts no numeric type
implicitly, so the conversion is written here — the same
asymmetry the walk spells out in the other direction, where
crates/lang-rules/src/emit/decode.rs casts read_wchar’s
answer back to a uint16 itself.
Source§fn constant(which: Constant) -> Self::Expr
fn constant(which: Constant) -> Self::Expr
The runtime’s policy values: numbers and strings where
ZdWire.fs takes them so, and the runtime’s own union cases for
the enumerated kinds.
Source§fn unsigned_holder(bits: u16) -> Self::Type
fn unsigned_holder(bits: u16) -> Self::Type
The unsigned type wide enough for bits of a bit set — the same
answer the materialiser’s fsharp_holder gives its fields.
Source§fn carries_hdds_axes() -> bool
fn carries_hdds_axes() -> bool
runtime/fsharp carries the three HDDS axes: BeginPackedElement
and FinishPackedElement on the writer and ReaderBeginPackedElement
/ ReaderFinishPackedElement on the reader, the DHEADER pair for a
sequence element’s own length, and WriteWstringUtf8Octets /
ReadWstringUtf8Octets.
Source§fn map_entry_name(ast: &Ast, id: Id<TypeNode>) -> String
fn map_entry_name(ast: &Ast, id: Id<TypeNode>) -> String
The entry name the materialiser declared, and a distinct one per type when its tag walk refuses: the slot keeps two refused entries from collapsing onto one declaration, which would merge two map types under one name.
Source§fn module_prefix(_ast: &Ast, _id: Id<TypeNode>) -> String
fn module_prefix(_ast: &Ast, _id: Id<TypeNode>) -> String
Nothing: a declared type’s F# name is already flat — the adapter
folds the modules in — and an enumerator lives in its enum’s own
scope, which CodecTarget::enumerator_constant’s override
reaches.
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 literal(value: Literal) -> Self::Expr
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
fn wide_int(value: i128) -> Self::Expr
int64(v) or uint64(v), whichever the value’s own range needs
— a union label the size of 16045690984833335998 does not fit
an int64, and the trait’s own documentation names that exact
value. F# gives neither width bare literal syntax: measured
(fsi, .NET SDK 9.0.106), let x : int64 = 5 is error FS0001
with no suffix, so this seam wraps in the conversion function
crate::adapter::fsharp::typed_int names, not a literal suffix
— crates/lang-cst/src/fsharp/mod.rs’s tree carries no signed
arbitrary-precision literal form the way Zig’s comptime_int is
one.
Source§fn unsigned_int(value: i128) -> Self::Expr
fn unsigned_int(value: i128) -> Self::Expr
uint32(v) — a count, an element index and a member id are all
uint32 on the wire, and this column’s own Scalar::Index
answers the same width for the same reason.
Source§fn wide_unsigned(value: u64) -> Self::Expr
fn wide_unsigned(value: u64) -> Self::Expr
uint64(v).
Source§fn wide_signed(value: i128) -> Self::Expr
fn wide_signed(value: i128) -> Self::Expr
int64(v).
Source§fn member(base: &str, field: &str) -> Self::Expr
fn member(base: &str, field: &str) -> Self::Expr
v.x — and v._d as it stands: this column keeps the IDL-facing
spelling, underscore and all.
Source§fn header_field(value: Self::Expr, field: &str) -> Self::Expr
fn header_field(value: Self::Expr, field: &str) -> Self::Expr
The runtime’s own spelling for a header field the walk asks for by its wire name.
runtime/fsharp/ZdWire.fs holds PidRead and EmHeaderRead as
records, and a record field is a name in the language: end is a
reserved word of the F# specification §3.4 and zd_p.end is
error FS0599, “missing qualification after ‘.’”. The other
names differ from the wire’s for the same reason the C# column’s
do — a .NET member is PascalCase — so the mapping is written
once here rather than bent into the runtime.
Source§fn index(value: Self::Expr, at: Self::Expr) -> Self::Expr
fn index(value: Self::Expr, at: Self::Expr) -> Self::Expr
value.[int at] — an F# array index is always int, and this
walk’s own counters are uint32 (Self::count_up’s own
documentation says why); measured (fsi, .NET SDK 9.0.106),
v.[i] with i: uint32 is error FS0001. The cast is written
here and not at every call site, because every index this walk
ever builds ends up as an array subscript.
Source§fn count_of(base: &str, fixed: Option<u64>) -> Self::Expr
fn count_of(base: &str, fixed: Option<u64>) -> Self::Expr
uint32 v.len.Length, or the bound where the materialiser fixed
one: .Length is an int32 and a sequence’s count is a
uint32 on the wire.
Source§fn case_member(base: &str, field: &str) -> Self::Expr
fn case_member(base: &str, field: &str) -> Self::Expr
v.x — a union is a class carrying its branches directly.
Source§fn entry_half(entry: Self::Expr, key: bool) -> Self::Expr
fn entry_half(entry: Self::Expr, key: bool) -> Self::Expr
entry.Key and entry.Value, the two properties the
materialiser gives a map’s entry class.
Source§fn materialised(_value: Self::Expr) -> Option<Self::Expr>
fn materialised(_value: Self::Expr) -> Option<Self::Expr>
Nothing: an F# array and string always exist once the runtime
answered — an allocation failure is a .NET OutOfMemoryException
no code here is built to survive anyway — so there is no absent
state for the guard to test.
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
v.x.Value — the value a 'T option holds, given that it holds
one. Only ever reached inside a branch the presence test
guarded, where the unwrap cannot trip.
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>
Nothing on the way in — assigning Some value is what makes the
member present, through Self::optional_destination’s marker
— and v.x <- None on the way out.
Source§fn optional_destination(
base: &str,
field: &str,
) -> (Vec<Self::Stmt>, Self::Expr)
fn optional_destination( base: &str, field: &str, ) -> (Vec<Self::Stmt>, Self::Expr)
The marked place; Self::read_call wraps the decoded T in
Some before the assignment, because unlike Zig’s ?T an F#
'T option does not coerce from a bare T.
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
The operators, unchanged: F# spells every one of them the same
as the walk does, &&/|| included. = never reaches a
rendered expression — Self::perform turns it into an
assignment statement.
The operator, with the spellings F# does not share with the
walk’s own C-family default: the shifts and the three bitwise
operators take a third symbol — << is <<<, >> is >>>,
& is &&&, | is |||, ^ is ^^^ — because F# still
parses a bare &/| as its own long-deprecated boolean
and/or (measured, fsc 9.0.106: zdBits & mask on two
uint64 is error FS0001, “expected bool”). == is =,
F#’s equality operator — == is reference equality on a class
and refuses two int32 [] outright — and != is <>.
Source§fn unary(op: &'static str, value: Self::Expr) -> Self::Expr
fn unary(op: &'static str, value: Self::Expr) -> Self::Expr
not value for !, -value for -, ~~~value for ~ — F#’s
own bitwise complement, spelled with three tildes and not one.
Source§fn cast(type_: Self::Type, value: Self::Expr) -> Self::Expr
fn cast(type_: Self::Type, value: Self::Expr) -> Self::Expr
The conversion, spelled by what it converts into. A bool
target with an integer literal becomes the boolean literal, as
in the sibling columns.
Source§fn handoff(value: Self::Expr, _form: Handoff) -> Self::Expr
fn handoff(value: Self::Expr, _form: Handoff) -> Self::Expr
The value, unchanged: an F# array and a class both hand by header/reference already.
Source§fn call(callee: &str, args: Vec<Self::Expr>) -> Self::Expr
fn call(callee: &str, args: Vec<Self::Expr>) -> Self::Expr
A call to a generated codec — a curried let function, not a
.NET method: fsharp::Expr::CurriedCall’s documentation
carries the measurement that f(a, b) does not compile against
one. strcmp is the runtime’s, which spells C11 §7.24.4’s
unsigned-octet order over two UTF-8 strings, and is a free
function of runtime/fsharp/ZdWire.fs too.
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
w.WriteU32(x) — a method on the writer or the reader.
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 of the runtime, qualified — except
pid_is_user_member, which is a property on the header the
reader handed back.
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 — the type written, so a reader of the
generated file sees the width. Every local the body reassigns is
written let mutable by Self::routine’s assembly pass;
Self::declare itself answers false because most locals the
walk declares are never reassigned, and the pass corrects the
minority that are.
Two coercions the other columns need none of, both because F# converts no numeric type implicitly and admits no null in a record:
- A bare integer initialiser takes the slot’s own width. The
walk writes its zeros and ones through one
intseam — C’suint32_t zd_before = 0and C#’suint zd_before = 0both compile — and F#’slet zd_before : uint32 = 0iserror FS0001.crate::adapter::fsharp::typed_intgives the literal its suffix instead. - A slot with no initialiser gets the runtime’s empty handle.
crates/lang-rules/src/emit/decode.rsdeclareszd_pandzd_hwith no value, meaning “a header the loop is about to read into”; C leaves the struct uninitialised and F# has no such state, so the runtime’snoPidRead ()/noEmheaderRead ()stand in — the same answerHandle::DHeaderalready gets fromZdWire.noDheader ()through the walk’s own seam.
Source§fn give_back(value: Option<Self::Expr>) -> Self::Stmt
fn give_back(value: Option<Self::Expr>) -> Self::Stmt
The body’s trailing expression: an F# decoder’s last line is the
sample it built, with no return keyword to write.
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
for i = 0 to (int bound) - 1 do … — F#’s own counted loop,
scoped by the language; the module documentation of
crates/lang-cst/src/fsharp/mod.rs says why this needs none of
Zig’s block-wrapping trick. The counter is int32 and not
uint32 — unlike a let-bound local, F#’s for … = … to … do
syntax takes only int: measured (fsi, .NET SDK 9.0.106),
for i = 0u to n - 1u do is error FS0001, “This expression was
expected to have type ‘int’ … ‘uint32’”. bound is cast to
int because Self::count_of’s own answer is uint32, the
wire’s own width for a count.
The walk nevertheless reads a counter as a count, at the
width Scalar::Index gives: crates/lang-rules/src/emit/ encode.rs’s ascending_by_key declares zd_before at
Scalar::UInt32 and compares it against the enclosing
counter, which C# gets away with because C# promotes both to
long and F# does not — measured, if zd_before = zd_rank then
with an int counter is error FS0001. So the loop counts in
int, as the syntax requires, and the body opens with
let i = uint32 i: F# admits the shadow inside the loop’s own
scope (measured, fsi, .NET SDK 9.0.106) and every use behind it
then sees the width the walk assumed. An index into a .NET array
crosses Self::element_at’s own int conversion either way.
Source§fn drop_value(value: Self::Expr) -> Self::Stmt
fn drop_value(value: Self::Expr) -> Self::Stmt
value |> ignore — F#’s spelling of a value read for its effect
and not kept.
Source§fn mark_used(_name: &str) -> Vec<Self::Stmt>
fn mark_used(_name: &str) -> Vec<Self::Stmt>
No statement: F# diagnoses neither an unused parameter nor an
unused local (measured, fsc 9.0.106,
--warnaserror+ --warn:5), so there is nothing here to say.
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 behaviour — through Some where the place
is an @optional member’s slot: the decoder answers a bare T
and F#’s 'T option needs it wrapped. Curried, as every call to
a generated codec is — fsharp::Expr::CurriedCall’s
documentation carries why.
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.
The trait’s default is C’s out-parameter shape; this column’s decoders answer their value, exactly as Zig’s, C#’s, D’s, Go’s, Java’s, Python’s and TypeScript’s do, for each backend’s own reason.
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>
v <- Array.zeroCreate<T> (int count), and the fill after it.
Array.zeroCreate answers an array of T’s own zero value —
null for a class-typed T, which the fill then overwrites
slot by slot before anything reads it, exactly as C’s
allocate-then-fill does.
Array.zeroCreate<T> n, and — where the elements are written
into rather than assigned whole — one constructed instance per
slot.
Array.zeroCreate gives every slot Unchecked.defaultof<T>,
which for the classes every aggregate becomes is null. A
decoder that then writes v.[i].Key <- … dereferences it:
measured on matrix/cases/map-key-long, whose three entries came
back as System.NullReferenceException and cost the read
direction of the cell. The C# column’s make_room fills the
slots for the same reason, and assigned_whole is the walk’s own
answer for when it need not — a primitive element is assigned as
a whole and has no null to dereference.
Source§fn keep_first(base: &str, count: Self::Expr) -> Vec<Self::Stmt>
fn keep_first(base: &str, count: Self::Expr) -> Vec<Self::Stmt>
v <- Array.sub v 0 (int count) — §7.3.1.2.1.12.3’s TRIM,
applied after every element has been read. Array.sub is
curried, like every F# standard-library array function.
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>)
The subscript, with nothing around it: an F# array element is a real settable place at every element type.
Source§fn routine(spec: Routine<Self>) -> Option<Self::Decl>
fn routine(spec: Routine<Self>) -> Option<Self::Decl>
let zd_enc_T (w: ZdWire.Writer) (v: T) : unit = … and
let zd_dec_T (r: ZdWire.Reader) (zd_tc: ZdWire.TryConstruct) : T = ….
A forward declaration is answered with nothing: module rec
gives every let in the file mutual visibility regardless of
where it is written, so a recursive type needs no declaration
ahead of its body — the module documentation of
crates/lang-cst/src/fsharp/mod.rs carries the measurement.
Unlike crate::emit::zig::Zig::routine, this does not scan the
body for mutability or unused names: F# diagnoses neither, so
every local the walk declares is a plain let — a reassignment
Self::perform built as an fsharp::Stmt::Assign against a
let-bound name is exactly the case the assembly pass below
corrects, by finding every name a body assigns through and
widening its declaration to let mutable.
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>
place <- zd_def_T () — the generated defaulter, not the value
inlined, so a member the stream skipped and one this same
decoder’s v already started as (Self::routine’s own call to
the same function) always agree, by construction, on what
Table 9’s value is.
§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 default_fsharp::member_value: a @default this column
cannot spell 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
Mode.IDLE — the enum’s own scope, which is where the
materialiser declared the case.
Source§type Expr = FsharpExpr
type Expr = FsharpExpr
Source§type Type = FsharpType
type Type = FsharpType
Source§fn value_type(ast: &Ast, id: Id<TypeNode>) -> Self::Type
fn value_type(ast: &Ast, id: Id<TypeNode>) -> Self::Type
id where a codec holds it. Read moreSource§fn type_name(ast: &Ast, id: Id<TypeNode>) -> String
fn type_name(ast: &Ast, id: Id<TypeNode>) -> String
id. Read moreSource§fn escape(name: &str) -> String
fn escape(name: &str) -> String
Source§fn whole(base: &str) -> Self::Expr
fn whole(base: &str) -> 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 until(condition: Self::Expr, body: Self::Block) -> Self::Stmt
fn until(condition: Self::Expr, body: Self::Block) -> Self::Stmt
Source§fn bool_less(left: Self::Expr, right: Self::Expr) -> Self::Expr
fn bool_less(left: Self::Expr, right: Self::Expr) -> Self::Expr
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 moreSource§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 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
type_. Read moreSource§fn storage(type_: Self::Type, name: &str) -> Self::Stmt
fn storage(type_: Self::Type, name: &str) -> Self::Stmt
Source§fn clear_union_cases(base: &str, fields: &[String]) -> Vec<Self::Stmt>
fn clear_union_cases(base: &str, fields: &[String]) -> Vec<Self::Stmt>
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 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
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
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.