1 // Copyright 2017 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_INTERNAL_H_
6 #define LIB_FIDL_INTERNAL_H_
7
8 #include <assert.h>
9 #include <stdint.h>
10
11 #include <lib/fidl/coding.h>
12 #include <zircon/syscalls/object.h>
13 #include <zircon/types.h>
14
15 // All sizes here are given as uint32_t. Fidl message sizes are bounded to well below UINT32_MAX.
16 // This also applies to arrays and vectors. For arrays, element_count * element_size will always fit
17 // with 32 bits. For vectors, max_count * element_size will always fit within 32 bits.
18
19 // Pointers to other type tables within a type are always nonnull, with the exception of vectors.
20 // In that case, a null pointer indicates that the element type of the vector has no interesting
21 // information to be decoded (i.e. no pointers or handles). The vector type still needs to be
22 // emitted as it contains the information about the size of its secondary object. Contrast this with
23 // arrays: being inline, ones with no interesting coding information can be elided, just like a
24 // uint32 field in a struct is elided.
25
26 namespace fidl {
27
28 enum FidlNullability : uint32_t {
29 kNonnullable = 0u,
30 kNullable = 1u,
31 };
32
FidlAlign(uint32_t offset)33 inline uint64_t FidlAlign(uint32_t offset) {
34 constexpr uint64_t alignment_mask = FIDL_ALIGNMENT - 1;
35 return (offset + alignment_mask) & ~alignment_mask;
36 }
37
38 struct FidlField {
39 const fidl_type* type;
40 uint32_t offset;
41
FidlFieldFidlField42 constexpr FidlField(const fidl_type* type, uint32_t offset)
43 : type(type), offset(offset) {}
44 };
45
46 struct FidlTableField {
47 const fidl_type* type;
48 uint32_t ordinal;
49
FidlTableFieldFidlTableField50 constexpr FidlTableField(const fidl_type* type, uint32_t ordinal)
51 : type(type), ordinal(ordinal) {}
52 };
53
54 enum FidlTypeTag : uint32_t {
55 kFidlTypeStruct = 0u,
56 kFidlTypeStructPointer = 1u,
57 kFidlTypeTable = 8u,
58 kFidlTypeTablePointer = 9u,
59 kFidlTypeUnion = 2u,
60 kFidlTypeUnionPointer = 3u,
61 kFidlTypeArray = 4u,
62 kFidlTypeString = 5u,
63 kFidlTypeHandle = 6u,
64 kFidlTypeVector = 7u,
65 };
66
67 // Though the |size| is implied by the fields, computing that information is not the purview of this
68 // library. It's easier for the compiler to stash it.
69 struct FidlCodedStruct {
70 const FidlField* const fields;
71 const uint32_t field_count;
72 const uint32_t size;
73 const char* name; // may be nullptr if omitted at compile time
74
FidlCodedStructFidlCodedStruct75 constexpr FidlCodedStruct(const FidlField* fields, uint32_t field_count, uint32_t size,
76 const char* name)
77 : fields(fields), field_count(field_count), size(size), name(name) {}
78 };
79
80 struct FidlCodedStructPointer {
81 const FidlCodedStruct* const struct_type;
82
FidlCodedStructPointerFidlCodedStructPointer83 constexpr explicit FidlCodedStructPointer(const FidlCodedStruct* struct_type)
84 : struct_type(struct_type) {}
85 };
86
87 struct FidlCodedTable {
88 const FidlTableField* const fields;
89 const uint32_t field_count;
90 const char* name; // may be nullptr if omitted at compile time
91
FidlCodedTableFidlCodedTable92 constexpr FidlCodedTable(const FidlTableField* fields, uint32_t field_count,
93 const char* name)
94 : fields(fields), field_count(field_count), name(name) {}
95 };
96
97 struct FidlCodedTablePointer {
98 const FidlCodedTable* const table_type;
99
FidlCodedTablePointerFidlCodedTablePointer100 constexpr explicit FidlCodedTablePointer(const FidlCodedTable* table_type)
101 : table_type(table_type) {}
102 };
103
104 // Unlike structs, union members do not have different offsets, so this points to an array of
105 // |fidl_type*| rather than |FidlField|.
106 //
107 // On-the-wire unions begin with a tag which is an index into |types|.
108 // |data_offset| is the offset of the data in the wire format (tag + padding).
109 struct FidlCodedUnion {
110 const fidl_type* const* types;
111 const uint32_t type_count;
112 const uint32_t data_offset;
113 const uint32_t size;
114 const char* name; // may be nullptr if omitted at compile time
115
FidlCodedUnionFidlCodedUnion116 constexpr FidlCodedUnion(const fidl_type* const* types, uint32_t type_count,
117 uint32_t data_offset, uint32_t size, const char* name)
118 : types(types), type_count(type_count), data_offset(data_offset), size(size), name(name) {}
119 };
120
121 struct FidlCodedUnionPointer {
122 const FidlCodedUnion* const union_type;
123
FidlCodedUnionPointerFidlCodedUnionPointer124 constexpr explicit FidlCodedUnionPointer(const FidlCodedUnion* union_type)
125 : union_type(union_type) {}
126 };
127
128 // An array is essentially a struct with |array_size / element_size| of the same field, named at
129 // |element|.
130 struct FidlCodedArray {
131 const fidl_type* const element;
132 const uint32_t array_size;
133 const uint32_t element_size;
134
FidlCodedArrayFidlCodedArray135 constexpr FidlCodedArray(const fidl_type* element, uint32_t array_size, uint32_t element_size)
136 : element(element), array_size(array_size), element_size(element_size) {}
137 };
138
139 // Note: must keep in sync with fidlc types.h HandleSubtype.
140 enum FidlHandleSubtype : zx_obj_type_t {
141 // special case to indicate subtype is not specified.
142 kFidlHandleSubtypeHandle = ZX_OBJ_TYPE_NONE,
143
144 kFidlHandleSubtypeProcess = ZX_OBJ_TYPE_PROCESS,
145 kFidlHandleSubtypeThread = ZX_OBJ_TYPE_THREAD,
146 kFidlHandleSubtypeVmo = ZX_OBJ_TYPE_VMO,
147 kFidlHandleSubtypeChannel = ZX_OBJ_TYPE_CHANNEL,
148 kFidlHandleSubtypeEvent = ZX_OBJ_TYPE_EVENT,
149 kFidlHandleSubtypePort = ZX_OBJ_TYPE_PORT,
150 kFidlHandleSubtypeInterrupt = ZX_OBJ_TYPE_INTERRUPT,
151 kFidlHandleSubtypeLog = ZX_OBJ_TYPE_LOG,
152 kFidlHandleSubtypeSocket = ZX_OBJ_TYPE_SOCKET,
153 kFidlHandleSubtypeResource = ZX_OBJ_TYPE_RESOURCE,
154 kFidlHandleSubtypeEventpair = ZX_OBJ_TYPE_EVENTPAIR,
155 kFidlHandleSubtypeJob = ZX_OBJ_TYPE_JOB,
156 kFidlHandleSubtypeVmar = ZX_OBJ_TYPE_VMAR,
157 kFidlHandleSubtypeFifo = ZX_OBJ_TYPE_FIFO,
158 kFidlHandleSubtypeGuest = ZX_OBJ_TYPE_GUEST,
159 kFidlHandleSubtypeTimer = ZX_OBJ_TYPE_TIMER,
160 };
161
162 struct FidlCodedHandle {
163 const zx_obj_type_t handle_subtype;
164 const FidlNullability nullable;
165
FidlCodedHandleFidlCodedHandle166 constexpr FidlCodedHandle(uint32_t handle_subtype, FidlNullability nullable)
167 : handle_subtype(handle_subtype), nullable(nullable) {}
168
169 static_assert(ZX_OBJ_TYPE_LAST <= UINT32_MAX, "");
170 };
171
172 struct FidlCodedString {
173 const uint32_t max_size;
174 const FidlNullability nullable;
175
FidlCodedStringFidlCodedString176 constexpr FidlCodedString(uint32_t max_size, FidlNullability nullable)
177 : max_size(max_size), nullable(nullable) {}
178 };
179
180 // Note that |max_count * element_size| is guaranteed to fit into a uint32_t. Unlike other types,
181 // the |element| pointer may be null. This occurs when the element type contains no interesting bits
182 // (i.e. pointers or handles).
183 struct FidlCodedVector {
184 const fidl_type* const element;
185 const uint32_t max_count;
186 const uint32_t element_size;
187 const FidlNullability nullable;
188
FidlCodedVectorFidlCodedVector189 constexpr FidlCodedVector(const fidl_type* element, uint32_t max_count, uint32_t element_size,
190 FidlNullability nullable)
191 : element(element), max_count(max_count), element_size(element_size), nullable(nullable) {}
192 };
193
194 } // namespace fidl
195
196 struct fidl_type {
197 const fidl::FidlTypeTag type_tag;
198 const union {
199 const fidl::FidlCodedStruct coded_struct;
200 const fidl::FidlCodedStructPointer coded_struct_pointer;
201 const fidl::FidlCodedTable coded_table;
202 const fidl::FidlCodedTablePointer coded_table_pointer;
203 const fidl::FidlCodedUnion coded_union;
204 const fidl::FidlCodedUnionPointer coded_union_pointer;
205 const fidl::FidlCodedHandle coded_handle;
206 const fidl::FidlCodedString coded_string;
207 const fidl::FidlCodedArray coded_array;
208 const fidl::FidlCodedVector coded_vector;
209 };
210
fidl_typefidl_type211 constexpr fidl_type(fidl::FidlCodedStruct coded_struct)
212 : type_tag(fidl::kFidlTypeStruct), coded_struct(coded_struct) {}
213
fidl_typefidl_type214 constexpr fidl_type(fidl::FidlCodedStructPointer coded_struct_pointer)
215 : type_tag(fidl::kFidlTypeStructPointer), coded_struct_pointer(coded_struct_pointer) {}
216
fidl_typefidl_type217 constexpr fidl_type(fidl::FidlCodedTable coded_table)
218 : type_tag(fidl::kFidlTypeTable), coded_table(coded_table) {}
219
fidl_typefidl_type220 constexpr fidl_type(fidl::FidlCodedTablePointer coded_table_pointer)
221 : type_tag(fidl::kFidlTypeTablePointer), coded_table_pointer(coded_table_pointer) {}
222
fidl_typefidl_type223 constexpr fidl_type(fidl::FidlCodedUnion coded_union)
224 : type_tag(fidl::kFidlTypeUnion), coded_union(coded_union) {}
225
fidl_typefidl_type226 constexpr fidl_type(fidl::FidlCodedUnionPointer coded_union_pointer)
227 : type_tag(fidl::kFidlTypeUnionPointer), coded_union_pointer(coded_union_pointer) {}
228
fidl_typefidl_type229 constexpr fidl_type(fidl::FidlCodedHandle coded_handle)
230 : type_tag(fidl::kFidlTypeHandle), coded_handle(coded_handle) {}
231
fidl_typefidl_type232 constexpr fidl_type(fidl::FidlCodedString coded_string)
233 : type_tag(fidl::kFidlTypeString), coded_string(coded_string) {}
234
fidl_typefidl_type235 constexpr fidl_type(fidl::FidlCodedArray coded_array)
236 : type_tag(fidl::kFidlTypeArray), coded_array(coded_array) {}
237
fidl_typefidl_type238 constexpr fidl_type(fidl::FidlCodedVector coded_vector)
239 : type_tag(fidl::kFidlTypeVector), coded_vector(coded_vector) {}
240 };
241
242 #endif // LIB_FIDL_INTERNAL_H_
243