blob: f430a91a63ed65fc75fabcd727fa1e535ef890ba [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 <lib/fidl/cpp/array.h>
#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);
inline static void Encode(Encoder* encoder, T* value, size_t offset) {
*encoder->GetPtr<T>(offset) = *value;
}
inline static void Decode(Decoder* decoder, T* value, size_t offset) {
*value = *decoder->GetPtr<T>(offset);
}
};
template <>
struct CodingTraits<bool> {
static constexpr size_t encoded_size = sizeof(bool);
inline static void Encode(Encoder* encoder, bool* value, size_t offset) {
*encoder->GetPtr<bool>(offset) = *value;
}
inline static void Encode(Encoder* encoder, std::vector<bool>::iterator value,
size_t offset) {
*encoder->GetPtr<bool>(offset) = *value;
}
inline static void Decode(Decoder* decoder, bool* value, size_t offset) {
*value = *decoder->GetPtr<bool>(offset);
}
inline static void Decode(Decoder* decoder, std::vector<bool>::iterator value,
size_t offset) {
*value = *decoder->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);
static void Encode(Encoder* encoder, std::unique_ptr<T>* value,
size_t offset) {
if (value->get()) {
*encoder->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->GetPtr<uintptr_t>(offset) = FIDL_ALLOC_ABSENT;
}
}
static void Decode(Decoder* decoder, std::unique_ptr<T>* value,
size_t offset) {
uintptr_t ptr = *decoder->GetPtr<uintptr_t>(offset);
if (!ptr)
return value->reset();
*value = std::make_unique<T>();
CodingTraits<T>::Decode(decoder, value->get(), decoder->GetOffset(ptr));
}
};
void EncodeNullVector(Encoder* encoder, size_t offset);
void EncodeVectorPointer(Encoder* encoder, size_t count, size_t offset);
template <typename T>
struct CodingTraits<VectorPtr<T>> {
static constexpr size_t encoded_size = sizeof(fidl_vector_t);
static void Encode(Encoder* 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);
}
static void Decode(Decoder* decoder, VectorPtr<T>* value, size_t offset) {
fidl_vector_t* encoded = decoder->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);
static void Encode(Encoder* 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);
}
static void Decode(Decoder* decoder, ::std::vector<T>* value, size_t offset) {
fidl_vector_t* encoded = decoder->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<Array<T, N>> {
static constexpr size_t encoded_size = CodingTraits<T>::encoded_size * N;
static void Encode(Encoder* encoder, 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);
}
static void Decode(Decoder* decoder, 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;
static void Encode(Encoder* encoder, T* value, size_t offset) {
value->Encode(encoder, offset);
}
static void Decode(Decoder* decoder, T* value, size_t offset) {
T::Decode(decoder, value, offset);
}
};
template <typename T>
void Encode(Encoder* encoder, T* value, size_t offset) {
CodingTraits<T>::Encode(encoder, value, offset);
}
template <typename T>
void Decode(Decoder* decoder, T* value, size_t offset) {
CodingTraits<T>::Decode(decoder, value, offset);
}
template <typename T>
T DecodeAs(Decoder* decoder, size_t offset) {
T value;
Decode(decoder, &value, offset);
return value;
}
} // namespace fidl
#endif // LIB_FIDL_CPP_CODING_TRAITS_H_