blob: 59df778ccbc431832c9524703a74a3f10f9852a9 [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.
#ifndef LIB_FIDL_CPP_CODING_TRAITS_H_
#define LIB_FIDL_CPP_CODING_TRAITS_H_
#include <array>
#include <memory>
#include "lib/fidl/cpp/decoder.h"
#include "lib/fidl/cpp/encoder.h"
#include "lib/fidl/cpp/traits.h"
#include "lib/fidl/cpp/vector.h"
namespace fidl {
template <typename T, class Enable = void>
struct CodingTraits;
template <typename T>
struct CodingTraits<T, typename std::enable_if<IsPrimitive<T>::value>::type> {
static constexpr size_t inline_size_v1_no_ee = sizeof(T);
template <class EncoderImpl>
static void Encode(EncoderImpl* encoder, T* value, size_t offset) {
*encoder->template GetPtr<T>(offset) = *value;
}
template <class DecoderImpl>
static void Decode(DecoderImpl* decoder, T* value, size_t offset) {
*value = *decoder->template GetPtr<T>(offset);
}
};
template <>
struct CodingTraits<bool> {
static constexpr size_t inline_size_v1_no_ee = sizeof(bool);
template <class EncoderImpl>
static void Encode(EncoderImpl* encoder, bool* value, size_t offset) {
*encoder->template GetPtr<bool>(offset) = *value;
}
template <class EncoderImpl>
static void Encode(EncoderImpl* encoder, std::vector<bool>::iterator value, size_t offset) {
*encoder->template GetPtr<bool>(offset) = *value;
}
template <class DecoderImpl>
static void Decode(DecoderImpl* decoder, bool* value, size_t offset) {
*value = *decoder->template GetPtr<bool>(offset);
}
template <class DecoderImpl>
static void Decode(DecoderImpl* decoder, std::vector<bool>::iterator value, size_t offset) {
*value = *decoder->template GetPtr<bool>(offset);
}
};
#ifdef __Fuchsia__
template <typename T>
struct CodingTraits<T, typename std::enable_if<std::is_base_of<zx::object_base, T>::value>::type> {
static constexpr size_t inline_size_v1_no_ee = sizeof(zx_handle_t);
static void Encode(Encoder* encoder, zx::object_base* value, size_t offset) {
encoder->EncodeHandle(value, offset);
}
static void Decode(Decoder* decoder, zx::object_base* value, size_t offset) {
decoder->DecodeHandle(value, offset);
}
};
#endif
template <typename T>
struct CodingTraits<std::unique_ptr<T>, typename std::enable_if<!IsFidlXUnion<T>::value>::type> {
static constexpr size_t inline_size_v1_no_ee = sizeof(uintptr_t);
template <class EncoderImpl>
static void Encode(EncoderImpl* encoder, std::unique_ptr<T>* value, size_t offset) {
if (value->get()) {
*encoder->template GetPtr<uintptr_t>(offset) = FIDL_ALLOC_PRESENT;
CodingTraits<T>::Encode(encoder, value->get(),
encoder->Alloc(CodingTraits<T>::inline_size_v1_no_ee));
} else {
*encoder->template GetPtr<uintptr_t>(offset) = FIDL_ALLOC_ABSENT;
}
}
template <class DecoderImpl>
static void Decode(DecoderImpl* decoder, std::unique_ptr<T>* value, size_t offset) {
uintptr_t ptr = *decoder->template GetPtr<uintptr_t>(offset);
if (!ptr)
return value->reset();
*value = std::make_unique<T>();
CodingTraits<T>::Decode(decoder, value->get(), decoder->GetOffset(ptr));
}
};
template <class EncoderImpl>
void EncodeNullVector(EncoderImpl* encoder, size_t offset) {
fidl_vector_t* vector = encoder->template GetPtr<fidl_vector_t>(offset);
vector->count = 0u;
vector->data = reinterpret_cast<void*>(FIDL_ALLOC_ABSENT);
}
template <class EncoderImpl>
void EncodeVectorPointer(EncoderImpl* encoder, size_t count, size_t offset) {
fidl_vector_t* vector = encoder->template GetPtr<fidl_vector_t>(offset);
vector->count = count;
vector->data = reinterpret_cast<void*>(FIDL_ALLOC_PRESENT);
}
template <typename T>
struct CodingTraits<VectorPtr<T>> {
static constexpr size_t inline_size_v1_no_ee = sizeof(fidl_vector_t);
template <class EncoderImpl>
static void Encode(EncoderImpl* encoder, VectorPtr<T>* value, size_t offset) {
if (!value->has_value())
return EncodeNullVector(encoder, offset);
std::vector<T>& vector = **value;
CodingTraits<::std::vector<T>>::Encode(encoder, &vector, offset);
}
template <class DecoderImpl>
static void Decode(DecoderImpl* decoder, VectorPtr<T>* value, size_t offset) {
fidl_vector_t* encoded = decoder->template GetPtr<fidl_vector_t>(offset);
if (!encoded->data) {
*value = VectorPtr<T>();
return;
}
std::vector<T> vector;
CodingTraits<std::vector<T>>::Decode(decoder, &vector, offset);
(*value) = std::move(vector);
}
};
template <typename T>
struct CodingTraits<::std::vector<T>> {
static constexpr size_t inline_size_v1_no_ee = sizeof(fidl_vector_t);
template <class EncoderImpl>
static void Encode(EncoderImpl* encoder, ::std::vector<T>* value, size_t offset) {
size_t count = value->size();
EncodeVectorPointer(encoder, count, offset);
size_t stride = CodingTraits<T>::inline_size_v1_no_ee;
size_t base = encoder->Alloc(count * stride);
for (size_t i = 0; i < count; ++i)
CodingTraits<T>::Encode(encoder, &value->at(i), base + i * stride);
}
template <class DecoderImpl>
static void Decode(DecoderImpl* decoder, ::std::vector<T>* value, size_t offset) {
fidl_vector_t* encoded = decoder->template GetPtr<fidl_vector_t>(offset);
value->resize(encoded->count);
size_t stride = CodingTraits<T>::inline_size_v1_no_ee;
size_t base = decoder->GetOffset(encoded->data);
size_t count = encoded->count;
for (size_t i = 0; i < count; ++i)
CodingTraits<T>::Decode(decoder, &value->at(i), base + i * stride);
}
};
template <typename T, size_t N>
struct CodingTraits<::std::array<T, N>> {
static constexpr size_t inline_size_v1_no_ee = CodingTraits<T>::inline_size_v1_no_ee * N;
template <class EncoderImpl>
static void Encode(EncoderImpl* encoder, std::array<T, N>* value, size_t offset) {
size_t stride;
stride = CodingTraits<T>::inline_size_v1_no_ee;
for (size_t i = 0; i < N; ++i)
CodingTraits<T>::Encode(encoder, &value->at(i), offset + i * stride);
}
template <class DecoderImpl>
static void Decode(DecoderImpl* decoder, std::array<T, N>* value, size_t offset) {
size_t stride = CodingTraits<T>::inline_size_v1_no_ee;
for (size_t i = 0; i < N; ++i)
CodingTraits<T>::Decode(decoder, &value->at(i), offset + i * stride);
}
};
template <typename T, size_t InlineSizeV1NoEE>
struct EncodableCodingTraits {
static constexpr size_t inline_size_v1_no_ee = InlineSizeV1NoEE;
template <class EncoderImpl>
static void Encode(EncoderImpl* encoder, T* value, size_t offset) {
value->Encode(encoder, offset);
}
template <class DecoderImpl>
static void Decode(DecoderImpl* decoder, T* value, size_t offset) {
T::Decode(decoder, value, offset);
}
};
template <typename T, class EncoderImpl = Encoder>
size_t EncodingInlineSize(EncoderImpl* encoder) {
return CodingTraits<T>::inline_size_v1_no_ee;
}
template <typename T, class DecoderImpl = Decoder>
size_t DecodingInlineSize(DecoderImpl* decoder) {
return CodingTraits<T>::inline_size_v1_no_ee;
}
template <typename T, class EncoderImpl>
void Encode(EncoderImpl* encoder, T* value, size_t offset) {
CodingTraits<T>::Encode(encoder, value, offset);
}
template <typename T, class DecoderImpl>
void Decode(DecoderImpl* decoder, T* value, size_t offset) {
CodingTraits<T>::Decode(decoder, value, offset);
}
template <typename T, class DecoderImpl>
T DecodeAs(DecoderImpl* decoder, size_t offset) {
T value;
Decode(decoder, &value, offset);
return value;
}
} // namespace fidl
#endif // LIB_FIDL_CPP_CODING_TRAITS_H_