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