Skip to main content

Cpp

Struct Cpp 

Source
pub struct Cpp;
Expand description

The C++ backend.

Trait Implementations§

Source§

impl Clone for Cpp

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 Cpp

Source§

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

The fixed-width types, from the materialiser’s own table.

Index and Size are both std::size_t here: C++ has an unsigned type for each, so the distinction C needs — a uint32_t counter against a size_t position — costs nothing to collapse and a std::vector::size() returns the latter.

Source§

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

The handles are types of the runtime’s namespace, not nested in the writer: zerodds::wire::DHeader.

Source§

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

A free function of the runtime’s namespace.

zerodds::wire::no_dheader() and not Writer::no_dheader(), which is what this used to write. C++ has free functions, so an operation the walk describes as having no receiver is one; and the writer’s qualification was wrong the moment a reader asked for one — Writer::pid_is_user_member names a static member the writer has no business declaring.

Source§

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

A policy value, in the runtime’s namespace.

Source§

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

strcmp is the walk’s name for a three-way code-unit comparison and is not a name this column’s strings answer to: the key is a std::string, and a.compare(b) is char_traits<char>::compare — the same unsigned octet order C11 §7.24.4 gives strcmp, with the same sign convention.

Source§

fn carries_hdds_axes() -> bool

runtime/cpp carries the three HDDS axes: begin_packed_element and finish_packed_element on the writer and the reader, the DHEADER pair for a sequence element’s own length, and write_wstring_utf8_octets / read_wstring_utf8_octets.

Source§

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

A reference, so a member is . and never ->.

Source§

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

UINT64_C is C’s; C++ writes the suffix.

−2^63 takes no suffix, because it is not a literal: -9223372036854775808LL is a minus over a literal one past LLONG_MAX. zerodds_lang_render::cpp::integer_text carries the clause and the measurement and answers with the subtraction. The result is a parenthesised expression rather than a literal, which every site this reaches admits: the walk puts it inside a static_cast in an if condition and never where C++ requires a token — the generated union reader is a chain of comparisons and carries no case label.

Source§

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

The storage behind the accessor of a case (adapter::cpp::union_storage): the codec reads and writes the storage and not the accessor, whose setter selects the case.

Source§

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

A std::vector and a std::array both answer .size(), so the bound the materialiser fixed is not needed and not used.

Source§

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

The tree has no unary node; !a is a == false and -a is 0 - a, which is what both mean. !a as a == false, and every other operator as itself.

The negation is spelled out because ! on a value the walk hands over is operator! on whatever type it has, and == false says the same thing for a bool without depending on that. The rest go through cpp::Expr::Unary, which is what a complement needs: the form this used before wrote 0 ~ a, which no compiler reads.

Source§

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

The bracket is written, because the walk asked for it.

This returned the expression unchanged, on the reading that “the renderer brackets by precedence”. It does not — zerodds-lang-cst says so in as many words, on Expr::Paren: “this tree holds no operator precedence, so a renderer walking it cannot know where a bracket is needed. A builder that needs one says so.”

What that cost: a bitmask’s reader asks for paren(zd_bits & ~UINT64_C(131)) != 0 and got zd_bits & ~UINT64_C(131) != 0, which C++ groups as zd_bits & (~131 != 0) — a different number, and one that would have accepted every undeclared bit. -Wparentheses -Werror made it a build failure rather than a wrong value, which is the only reason it was found at the compiler and not in a byte comparison.

Source§

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

A reference takes the value either way: there is no address to take and no array to decay.

Source§

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

write_char takes a char32_t, so the code point is a cast to it and the runtime keeps what the width allows.

Source§

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

The integer form is two static_casts — through the unsigned type of the source’s width first, which is what masks a negative value to its two’s-complement octets instead of sign-extending it — and the float forms are the runtime’s bit_pattern_f32 and bit_pattern_f64, because C++ has no expression that reads a float’s bits without std::memcpy.

Source§

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

for (std::size_t i = 0; i < bound; i = i + 1), the step written out for the reason C’s is: the tree has no increment node, and one spelling across the backends keeps two columns’ generated source comparable by eye when their octets disagree.

Source§

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

v.x != nullptr. XTypes 1.3 §7.5.1.2.4.2: “A NULL pointer shall indicate an omitted value.”

Source§

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

Nothing on the way in — Cpp::make_indirection makes the object — and zerodds::wire::destroy(v.x); on the way out, which deletes what the member held and leaves it NULL.

Source§

fn optionals_are_pointers() -> bool

An @optional member is a plain pointer (§7.5.1.2.4.2).

Source§

fn value_is_pointer(_ast: &Ast, _id: Id<TypeNode>) -> bool

A std::string is a value, so an @optional string is a std::string * like any other.

Source§

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

if (!(v.x != nullptr)) { throw zerodds::wire::UnsetExternal(...); }

Source§

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

The vector is the elements. .value() and not *: the two are the same inside a guarded branch and the first says which one it is. A std::pair, so first and second.

Source§

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

The member, the pointer; Cpp::behind_indirection dereferences it.

Source§

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

*place — the object an optional pointer points at.

Source§

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

zerodds::wire::pointer_slot(place) — the pointer made to point at a new object when it points nowhere, and the object.

Source§

fn holds_a_cycle_externally() -> bool

true: an @external member is a std::shared_ptr, and a member on a cycle needs the same: std::optional<T> and a plain T both want T complete. crate::adapter::held_externally is the rule the adapter and the defaulter ask as well.

Source§

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

*v.x — the shared pointer dereferenced, for @external with and without @optional alike: the member’s codec takes the value, and crates/lang-rules/src/adapter/cpp.rs gives an @external member one indirection and no std::optional around it.

Source§

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

zerodds::wire::external_slot(v.x) — the slot filled and the place handed back, in one expression.

The counterpart of Cpp::optional_destination’s emplace: a pointer member has nothing to write into until it points at something. A function of the runtime and not std::make_shared<T>() written here, because this seam is handed the member and not its type.

Source§

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

*v.x for a branch too: a union arm’s @external field is the same std::shared_ptr<T> a structure member is.

Source§

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

The same allocation and the same place as Cpp::external_destination.

Source§

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

v.x != nullptr: the pointer is the absence, with no std::optional around it to carry a second one.

Source§

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

Nothing on the way in — Cpp::external_destination allocates — and v.x = nullptr; on the way out.

Source§

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

v[i], except for the one container C++ specialises.

std::vector<bool> packs its elements into bits — [vector.bool] — and operator[] hands back a proxy object rather than a bool &. A generated decoder takes its destination by reference, so there is nothing for it to point at, and the call does not compile. Read into a local and assign it back: one statement either side, and only where the element really is bool.

Not solved by changing what a sequence<boolean> maps to. The element codec is named by the IDL kind — zd_dec_p_boolean — takes a bool &, and is the same function whether the value is a member, an array element or a map’s value, so a container holding anything but bool would not match it either. The proxy is the container’s, so the work-around belongs at the container.

Source§

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

v.resize(count);, which is make_room again in the shortening direction. A std::vector owns its elements, so the ones past the bound are destroyed rather than left where C leaves them.

Source§

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

The member: Cpp::make_indirection makes it point somewhere.

Source§

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

w.write_octets(v.data(), n): std::vector<std::uint8_t> and std::array<std::uint8_t, N> both hold their octets contiguously.

Source§

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

r.read_octets(v.data(), n), after make_room has resized v.

Source§

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

One statement: resize throws rather than returning nothing, so there is no guard and the fill follows unconditionally.

Source§

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

Nothing to check. Every value this column’s reader materialises is a std::string or a std::vector, which own their storage and are never absent; the read either produced one or threw.

Source§

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

static void zd_enc_T(zerodds::wire::Writer &w, const T &v).

A prototype, unlike Java’s, is emitted: C++ resolves a call to a free function by what is declared above it, so a recursive or mutually recursive type needs the declaration ahead of the body exactly as C does.

Source§

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

std::pair<K, V> — the type the materialiser spells the entry as. The tag map_entry_name answers is a name for generated identifiers (zd_dec_map_string_long), not a declared type, so the default’s named(tag) declared the scratch entry with an identifier no compiler finds.

Source§

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

C++ has namespaces, so a module needs no prefix in a name.

Source§

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

::a::b::Colour::red.

The enumeration’s own name is in the middle, which is what makes this a seam rather than a prefix and a bare identifier: adapter/cpp.rs declares a scoped enumeration, so an enumerator is a member of the type. Its reason is written there — an unscoped enum would put every enumerator of every enumeration of a module in one namespace, where two IDL-legal names collide.

Source§

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

A call to the generated defaulter, as the C column does it.

Not place = T{}. Value-initialisation is not Table 9 — an enumeration whose first literal is not zero, a union’s selected branch and a member’s own @default are three rows it gets wrong — and two columns answering the same table by different mechanisms is a divergence no byte comparison shows, because both produce a value. crate::default_cpp carries the whole argument.

§Errors

Never here. The defaulter is a call, and whether the type has one is settled where the function is built — crate::default_cpp::cpp_defaulters_called_by reads the calls this emitted and refuses there, by name.

Source§

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

§Errors

EncodeError::NoWriter where a @default names a value C++ cannot spell — a long double literal is the one the corpus reaches.

Source§

type Expr = Expr

An expression.
Source§

type Stmt = Statement

A statement.
Source§

type Block = Block

A sequence of statements.
Source§

type Type = Type

A type, as written in a declaration.
Source§

type Decl = Decl

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

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

A type named by the materialiser.
Source§

fn nothing() -> Self::Type

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

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

The unsigned type wide enough to hold bits of a bit set. Read more
Source§

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

A bare name.
Source§

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

An integer literal.
Source§

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

Any other literal the common tree can hold.
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 discriminant(base: &str) -> Self::Expr

A union’s discriminant. Read more
Source§

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

a[i]
Source§

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

a op b, written as given.
Source§

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

A conversion the target requires and the walk knows is exact.
Source§

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

A local declaration with an optional initialiser.
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 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 elements(base: &str) -> Self::Expr

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

fn absent() -> Self::Expr

The value that says a target holds nothing. Read more
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 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 escape(name: &str) -> String

An IDL identifier as this target spells a member or a field. 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 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 unsigned_int(value: i128) -> Self::Expr

A count, in whatever spelling keeps the target’s conversions quiet. Read more
Source§

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

A 64-bit pattern, in a spelling wide enough to survive itself. Read more
Source§

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

A signed 64-bit constant, as CodecTarget::wide_unsigned.
Source§

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

A value read for its effect and not kept. Read more
Source§

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

How this target says a parameter is deliberately not read. Read more
Source§

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

zd_dec_<T>(r, <destination>, <behaviour>); — one nested decoder run, with its answer put where place says. Read more
Source§

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

The whole sample handed straight on to another type’s decoder. Read more
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 store(place: Self::Expr, type_: Self::Type, value: Self::Expr) -> Self::Stmt

One scalar, as it comes off the runtime, into a place of type_. Read more
Source§

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

A local the body writes into rather than assigns. Read more
Source§

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

One field of a header the runtime handed back. Read more
Source§

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

Statements that leave every case member of a union unset, before the member the discriminator selects is read. Read more
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 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 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 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 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 inherited_path(depth: usize) -> Option<String>

The path from a derived structure to the base members depth levels up, for a column that binds inheritance as a first member parent (XTypes 1.3 §7.5.1.4.1.3), ending in the separator: parent. for the base, parent.parent. for its base. None, the default, is a column that declares the base’s members in the derived structure.
Source§

impl Copy for Cpp

Source§

impl Debug for Cpp

Source§

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

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

impl Eq for Cpp

Source§

impl PartialEq for Cpp

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 Cpp

Auto Trait Implementations§

§

impl Freeze for Cpp

§

impl RefUnwindSafe for Cpp

§

impl Send for Cpp

§

impl Sync for Cpp

§

impl Unpin for Cpp

§

impl UnsafeUnpin for Cpp

§

impl UnwindSafe for Cpp

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.