blob: f1baf29c2a42f4366c24ab7da57fce1e3b7f5ac0 [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 encoded_size = 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 encoded_size = 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 encoded_size = 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>> {
static constexpr size_t encoded_size = 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;
size_t size = CodingTraits<T>::encoded_size;
CodingTraits<T>::Encode(encoder, value->get(), encoder->Alloc(size));
} 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 encoded_size = sizeof(fidl_vector_t);
template <class EncoderImpl>
static void Encode(EncoderImpl* encoder, VectorPtr<T>* value, size_t offset) {
if (value->is_null())
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->reset(std::move(vector));
}
};
template <typename T>
struct CodingTraits<::std::vector<T>> {
static constexpr size_t encoded_size = 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>::encoded_size;
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>::encoded_size;
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 encoded_size = CodingTraits<T>::encoded_size * N;
template <class EncoderImpl>
static void Encode(EncoderImpl* encoder, std::array<T, N>* value, size_t offset) {
size_t stride = CodingTraits<T>::encoded_size;
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>::encoded_size;
for (size_t i = 0; i < N; ++i)
CodingTraits<T>::Decode(decoder, &value->at(i), offset + i * stride);
}
};
template <typename T, size_t EncodedSize>
struct EncodableCodingTraits {
static constexpr size_t encoded_size = EncodedSize;
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>
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_