blob: a8d339567123565bf3acfbcf30326fe4780ca8e4 [file] [log] [blame]
// Copyright 2019 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.
#ifndef SRC_LIB_FIDL_CODEC_ENCODER_H_
#define SRC_LIB_FIDL_CODEC_ENCODER_H_
#include <optional>
#include <vector>
#include "lib/fit/function.h"
#include "src/lib/fidl_codec/visitor.h"
namespace fidl_codec {
class Encoder : public Visitor {
public:
struct Result {
std::vector<uint8_t> bytes;
std::vector<zx_handle_info_t> handles;
};
static Result EncodeMessage(uint32_t tx_id, uint64_t ordinal, uint8_t flags[3], uint8_t magic,
const Object& object);
private:
Encoder(bool union_as_xunion) : union_as_xunion_(union_as_xunion) {}
// Pad the current buffer so the next value will be aligned to an 8-byte boundary.
void Align8();
// Write an immediate value to the buffer, naturally aligned.
template <typename T>
void Write(T t);
// Write data into our buffer.
void WriteData(const uint8_t* data, size_t size);
void WriteData(const std::optional<std::vector<uint8_t>>& data, size_t size);
// Write a literal value into our buffer.
template <typename T>
void WriteValue(std::optional<T>);
// Execute all functions in the deferred queue. Manipulates the queue such that additional
// deferred actions caused by each call are executed depth-first. Also pads to 8-byte alignment
// before each call.
void Pump();
// Visit a union which is known to be non-null and which we want encoded immediately at the
// current position.
void VisitUnionBody(const UnionValue* node);
// Visit an object which is known to be non-null and which we want encoded immediately at the
// current position. If existing_size is specified, it indicates some number of bytes which have
// already been written that should be considered part of the object for the purpose of
// calculating member offsets.
void VisitObjectBody(const Object* node, size_t existing_size = 0);
// Visit any union and encode it as an XUnion.
void VisitUnionAsXUnion(const UnionValue* node);
// Enqueue some work in the deferred queue. Used to defer the encoding of out-of-line data until
// the in-line data has been fully encoded. Before each callback is called the data will be padded
// to an 8-byte alignment.
void Defer(fit::function<void()> cb) { deferred_.push_back(std::move(cb)); }
// Visitor overrides.
void VisitRawValue(const RawValue* node) override;
void VisitStringValue(const StringValue* node) override;
void VisitBoolValue(const BoolValue* node) override;
void VisitEnvelopeValue(const EnvelopeValue* node) override;
void VisitTableValue(const TableValue* node) override;
void VisitUnionValue(const UnionValue* node) override;
void VisitXUnionValue(const XUnionValue* node) override;
void VisitArrayValue(const ArrayValue* node) override;
void VisitVectorValue(const VectorValue* node) override;
void VisitEnumValue(const EnumValue* node) override;
void VisitBitsValue(const BitsValue* node) override;
void VisitHandleValue(const HandleValue* node) override;
void VisitObject(const Object* node) override;
void VisitU8Value(const NumericValue<uint8_t>* node) override;
void VisitU16Value(const NumericValue<uint16_t>* node) override;
void VisitU32Value(const NumericValue<uint32_t>* node) override;
void VisitU64Value(const NumericValue<uint64_t>* node) override;
void VisitI8Value(const NumericValue<int8_t>* node) override;
void VisitI16Value(const NumericValue<int16_t>* node) override;
void VisitI32Value(const NumericValue<int32_t>* node) override;
void VisitI64Value(const NumericValue<int64_t>* node) override;
void VisitF32Value(const NumericValue<float>* node) override;
void VisitF64Value(const NumericValue<double>* node) override;
const bool union_as_xunion_;
std::vector<fit::function<void()>> deferred_;
std::vector<uint8_t> bytes_;
std::vector<zx_handle_info_t> handles_;
};
} // namespace fidl_codec
#endif // SRC_LIB_FIDL_CODEC_ENCODER_H_