blob: 965ad9d72be3bcdff0fc58162e0d320b92a327df [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <cstdint>
// TODO( We should revisit this namespace choice as part of improving code
// organization.
namespace fidl {
namespace flat {
struct Object;
struct StructMember;
struct TableMemberUsed;
struct UnionMemberUsed;
} // namespace flat
enum class WireFormat {
kV1NoEe, // The v1-no-ee wire format, where "union" is an extensible union on-the-wire,
// but without efficient envelope support.
kV1Header, // The v1 wire format, except where request and response structs do not receive
// any special treatment (e.g. having their size increased by 16 for the transactional
// header)
struct TypeShape {
explicit TypeShape(const flat::Object& object, WireFormat wire_format);
explicit TypeShape(const flat::Object* object, WireFormat wire_format);
// The inline size of this type, including padding for the type's minimum alignment. For example,
// "struct S { uint32 a; uint16 b; };" will have an inline_size of 8, not 6: the "packed" size of
// the struct is 6, but the alignment of its largest member is 4, so 6 is rounded up to 8.
uint32_t inline_size;
// The minimum alignment required by this type.
uint32_t alignment;
// These values are calculated incorporating both the current TypeShape, and recursively over
// all child fields. A value of std::numeric_limits<uint32_t>::max() means that the value is
// potentially unbounded, which can happen for self-recursive aggregate objects. For flexible
// types, these values is calculated based on the currently-defined members, and does _not_ take
// potential future members into account.
uint32_t depth;
uint32_t max_handles;
uint32_t max_out_of_line;
// |has_padding| is true if this type has _either_ inline or out-of-line padding. For flexible
// types, |has_padding| is calculated based on the currently-defined members, and does _not_ take
// potential future members into account. (If it did, |has_padding| would have to be true for all
// flexible types, which doesn't make it very useful.)
bool has_padding;
bool has_flexible_envelope;
// TODO( These accessors are for backward compatibility with current code, and
// could be removed in the future.
uint32_t InlineSize() const { return inline_size; }
uint32_t Alignment() const { return alignment; }
uint32_t Depth() const { return depth; }
uint32_t MaxHandles() const { return max_handles; }
uint32_t MaxOutOfLine() const { return max_out_of_line; }
bool HasPadding() const { return has_padding; }
bool HasFlexibleEnvelope() const { return has_flexible_envelope; }
// |FieldShape| describes the offset and padding information for members that are contained within
// an aggregate type (e.g. struct/union).
// TODO( We can update |FieldShape| to be a simple offset+padding struct, and
// remove the getter/setter methods since they're purely for backward-compatibility with existing
// code.
struct FieldShape {
explicit FieldShape(const flat::StructMember&, const WireFormat wire_format);
explicit FieldShape(const flat::TableMemberUsed&, const WireFormat wire_format);
explicit FieldShape(const flat::UnionMemberUsed&, const WireFormat wire_format);
uint32_t Offset() const { return offset; }
// Padding after this field until the next field or the end of the container.
// See
uint32_t Padding() const { return padding; }
void SetOffset(uint32_t updated_offset) { offset = updated_offset; }
void SetPadding(uint32_t updated_padding) { padding = updated_padding; }
uint32_t offset = 0;
uint32_t padding = 0;
constexpr uint32_t kMessageAlign = 8u;
// Returns depth according to the "old" wire format (with static unions). This is currently only
// supported to calculate the Layout=Simple/ForDeprecatedCBindings attribute constraint.
uint32_t OldWireFormatDepth(const flat::Object& object);
uint32_t OldWireFormatDepth(const flat::Object* object);
} // namespace fidl