blob: 0a51f5a6a7352a38ad92845ad950a54288ed45a7 [file] [log] [blame]
Doug Horn1427b6a2018-12-11 13:19:16 -08001// Copyright 2018 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef LIB_FIDL_CPP_CODING_TRAITS_H_
6#define LIB_FIDL_CPP_CODING_TRAITS_H_
7
8#include <lib/fidl/cpp/array.h>
9
10#include <memory>
11
12#include "lib/fidl/cpp/decoder.h"
13#include "lib/fidl/cpp/encoder.h"
14#include "lib/fidl/cpp/traits.h"
15#include "lib/fidl/cpp/vector.h"
16
17namespace fidl {
18
19template <typename T, class Enable = void>
20struct CodingTraits;
21
22template <typename T>
23struct CodingTraits<T, typename std::enable_if<IsPrimitive<T>::value>::type> {
24 static constexpr size_t encoded_size = sizeof(T);
25 inline static void Encode(Encoder* encoder, T* value, size_t offset) {
26 *encoder->GetPtr<T>(offset) = *value;
27 }
28 inline static void Decode(Decoder* decoder, T* value, size_t offset) {
29 *value = *decoder->GetPtr<T>(offset);
30 }
31};
32
33template <>
34struct CodingTraits<bool> {
35 static constexpr size_t encoded_size = sizeof(bool);
36 inline static void Encode(Encoder* encoder, bool* value, size_t offset) {
37 *encoder->GetPtr<bool>(offset) = *value;
38 }
39 inline static void Encode(Encoder* encoder, std::vector<bool>::iterator value,
40 size_t offset) {
41 *encoder->GetPtr<bool>(offset) = *value;
42 }
43 inline static void Decode(Decoder* decoder, bool* value, size_t offset) {
44 *value = *decoder->GetPtr<bool>(offset);
45 }
46 inline static void Decode(Decoder* decoder, std::vector<bool>::iterator value,
47 size_t offset) {
48 *value = *decoder->GetPtr<bool>(offset);
49 }
50};
51
52#ifdef __Fuchsia__
53template <typename T>
54struct CodingTraits<T, typename std::enable_if<
55 std::is_base_of<zx::object_base, T>::value>::type> {
56 static constexpr size_t encoded_size = sizeof(zx_handle_t);
57 static void Encode(Encoder* encoder, zx::object_base* value, size_t offset) {
58 encoder->EncodeHandle(value, offset);
59 }
60 static void Decode(Decoder* decoder, zx::object_base* value, size_t offset) {
61 decoder->DecodeHandle(value, offset);
62 }
63};
64#endif
65
66template <typename T>
67struct CodingTraits<std::unique_ptr<T>> {
68 static constexpr size_t encoded_size = sizeof(uintptr_t);
69 static void Encode(Encoder* encoder, std::unique_ptr<T>* value,
70 size_t offset) {
71 if (value->get()) {
72 *encoder->GetPtr<uintptr_t>(offset) = FIDL_ALLOC_PRESENT;
73 size_t size = CodingTraits<T>::encoded_size;
74 CodingTraits<T>::Encode(encoder, value->get(), encoder->Alloc(size));
75 } else {
76 *encoder->GetPtr<uintptr_t>(offset) = FIDL_ALLOC_ABSENT;
77 }
78 }
79 static void Decode(Decoder* decoder, std::unique_ptr<T>* value,
80 size_t offset) {
81 uintptr_t ptr = *decoder->GetPtr<uintptr_t>(offset);
82 if (!ptr)
83 return value->reset();
84 *value = std::make_unique<T>();
85 CodingTraits<T>::Decode(decoder, value->get(), decoder->GetOffset(ptr));
86 }
87};
88
89void EncodeNullVector(Encoder* encoder, size_t offset);
90void EncodeVectorPointer(Encoder* encoder, size_t count, size_t offset);
91
92template <typename T>
93struct CodingTraits<VectorPtr<T>> {
94 static constexpr size_t encoded_size = sizeof(fidl_vector_t);
95 static void Encode(Encoder* encoder, VectorPtr<T>* value, size_t offset) {
96 if (value->is_null())
97 return EncodeNullVector(encoder, offset);
98 size_t count = (*value)->size();
99 EncodeVectorPointer(encoder, count, offset);
100 size_t stride = CodingTraits<T>::encoded_size;
101 size_t base = encoder->Alloc(count * stride);
102 for (size_t i = 0; i < count; ++i)
103 CodingTraits<T>::Encode(encoder, &(*value)->at(i), base + i * stride);
104 }
105 static void Decode(Decoder* decoder, VectorPtr<T>* value, size_t offset) {
106 fidl_vector_t* encoded = decoder->GetPtr<fidl_vector_t>(offset);
107 if (!encoded->data) {
108 *value = VectorPtr<T>();
109 return;
110 }
111 value->resize(encoded->count);
112 size_t stride = CodingTraits<T>::encoded_size;
113 size_t base = decoder->GetOffset(encoded->data);
114 size_t count = encoded->count;
115 for (size_t i = 0; i < count; ++i)
116 CodingTraits<T>::Decode(decoder, &(*value)->at(i), base + i * stride);
117 }
118};
119
120template <typename T, size_t N>
121struct CodingTraits<Array<T, N>> {
122 static constexpr size_t encoded_size = CodingTraits<T>::encoded_size * N;
123 static void Encode(Encoder* encoder, Array<T, N>* value, size_t offset) {
124 size_t stride = CodingTraits<T>::encoded_size;
125 for (size_t i = 0; i < N; ++i)
126 CodingTraits<T>::Encode(encoder, &value->at(i), offset + i * stride);
127 }
128 static void Decode(Decoder* decoder, Array<T, N>* value, size_t offset) {
129 size_t stride = CodingTraits<T>::encoded_size;
130 for (size_t i = 0; i < N; ++i)
131 CodingTraits<T>::Decode(decoder, &value->at(i), offset + i * stride);
132 }
133};
134
135template <typename T, size_t EncodedSize>
136struct EncodableCodingTraits {
137 static constexpr size_t encoded_size = EncodedSize;
138 static void Encode(Encoder* encoder, T* value, size_t offset) {
139 value->Encode(encoder, offset);
140 }
141 static void Decode(Decoder* decoder, T* value, size_t offset) {
142 T::Decode(decoder, value, offset);
143 }
144};
145
146template <typename T>
147void Encode(Encoder* encoder, T* value, size_t offset) {
148 CodingTraits<T>::Encode(encoder, value, offset);
149}
150
151template <typename T>
152void Decode(Decoder* decoder, T* value, size_t offset) {
153 CodingTraits<T>::Decode(decoder, value, offset);
154}
155
156template <typename T>
157T DecodeAs(Decoder* decoder, size_t offset) {
158 T value;
159 Decode(decoder, &value, offset);
160 return value;
161}
162
163} // namespace fidl
164
165#endif // LIB_FIDL_CPP_CODING_TRAITS_H_