1// 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#include "fidl/names.h"
6
7namespace fidl {
8
9namespace {
10
11const char* NameNullability(types::Nullability nullability) {
12    switch (nullability) {
13    case types::Nullability::kNullable:
14        return "nullable";
15    case types::Nullability::kNonnullable:
16        return "nonnullable";
17    }
18}
19
20std::string NameSize(uint64_t size) {
21    if (size == std::numeric_limits<uint64_t>::max())
22        return "unbounded";
23    std::ostringstream name;
24    name << size;
25    return name.str();
26}
27
28} // namespace
29
30std::string StringJoin(const std::vector<StringView>& strings, StringView separator) {
31    std::string result;
32    bool first = true;
33    for (const auto& part : strings) {
34        if (!first) {
35            result += separator;
36        }
37        first = false;
38        result += part;
39    }
40    return result;
41}
42
43std::string NamePrimitiveCType(types::PrimitiveSubtype subtype) {
44    switch (subtype) {
45    case types::PrimitiveSubtype::kInt8:
46        return "int8_t";
47    case types::PrimitiveSubtype::kInt16:
48        return "int16_t";
49    case types::PrimitiveSubtype::kInt32:
50        return "int32_t";
51    case types::PrimitiveSubtype::kInt64:
52        return "int64_t";
53    case types::PrimitiveSubtype::kUint8:
54        return "uint8_t";
55    case types::PrimitiveSubtype::kUint16:
56        return "uint16_t";
57    case types::PrimitiveSubtype::kUint32:
58        return "uint32_t";
59    case types::PrimitiveSubtype::kUint64:
60        return "uint64_t";
61    case types::PrimitiveSubtype::kBool:
62        return "bool";
63    case types::PrimitiveSubtype::kFloat32:
64        return "float";
65    case types::PrimitiveSubtype::kFloat64:
66        return "double";
67    }
68}
69
70std::string NamePrimitiveSubtype(types::PrimitiveSubtype subtype) {
71    switch (subtype) {
72    case types::PrimitiveSubtype::kInt8:
73        return "int8";
74    case types::PrimitiveSubtype::kInt16:
75        return "int16";
76    case types::PrimitiveSubtype::kInt32:
77        return "int32";
78    case types::PrimitiveSubtype::kInt64:
79        return "int64";
80    case types::PrimitiveSubtype::kUint8:
81        return "uint8";
82    case types::PrimitiveSubtype::kUint16:
83        return "uint16";
84    case types::PrimitiveSubtype::kUint32:
85        return "uint32";
86    case types::PrimitiveSubtype::kUint64:
87        return "uint64";
88    case types::PrimitiveSubtype::kBool:
89        return "bool";
90    case types::PrimitiveSubtype::kFloat32:
91        return "float32";
92    case types::PrimitiveSubtype::kFloat64:
93        return "float64";
94    }
95}
96
97std::string NamePrimitiveIntegerCConstantMacro(types::PrimitiveSubtype subtype) {
98    switch (subtype) {
99    case types::PrimitiveSubtype::kInt8:
100        return "INT8_C";
101    case types::PrimitiveSubtype::kInt16:
102        return "INT16_C";
103    case types::PrimitiveSubtype::kInt32:
104        return "INT32_C";
105    case types::PrimitiveSubtype::kInt64:
106        return "INT64_C";
107    case types::PrimitiveSubtype::kUint8:
108        return "UINT8_C";
109    case types::PrimitiveSubtype::kUint16:
110        return "UINT16_C";
111    case types::PrimitiveSubtype::kUint32:
112        return "UINT32_C";
113    case types::PrimitiveSubtype::kUint64:
114        return "UINT64_C";
115    case types::PrimitiveSubtype::kBool:
116        assert(false && "Tried to generate an integer constant for a bool");
117        return "";
118    case types::PrimitiveSubtype::kFloat32:
119    case types::PrimitiveSubtype::kFloat64:
120        assert(false && "Tried to generate an integer constant for a float");
121        return "";
122    }
123}
124
125std::string NameHandleSubtype(types::HandleSubtype subtype) {
126    switch (subtype) {
127    case types::HandleSubtype::kHandle:
128        return "handle";
129    case types::HandleSubtype::kProcess:
130        return "process";
131    case types::HandleSubtype::kThread:
132        return "thread";
133    case types::HandleSubtype::kVmo:
134        return "vmo";
135    case types::HandleSubtype::kChannel:
136        return "channel";
137    case types::HandleSubtype::kEvent:
138        return "event";
139    case types::HandleSubtype::kPort:
140        return "port";
141    case types::HandleSubtype::kInterrupt:
142        return "interrupt";
143    case types::HandleSubtype::kLog:
144        return "log";
145    case types::HandleSubtype::kSocket:
146        return "socket";
147    case types::HandleSubtype::kResource:
148        return "resource";
149    case types::HandleSubtype::kEventpair:
150        return "eventpair";
151    case types::HandleSubtype::kJob:
152        return "job";
153    case types::HandleSubtype::kVmar:
154        return "vmar";
155    case types::HandleSubtype::kFifo:
156        return "fifo";
157    case types::HandleSubtype::kGuest:
158        return "guest";
159    case types::HandleSubtype::kTimer:
160        return "timer";
161    }
162}
163
164std::string NameRawLiteralKind(raw::Literal::Kind kind) {
165    switch (kind) {
166    case raw::Literal::Kind::kString:
167        return "string";
168    case raw::Literal::Kind::kNumeric:
169        return "numeric";
170    case raw::Literal::Kind::kTrue:
171        return "true";
172    case raw::Literal::Kind::kFalse:
173        return "false";
174    }
175}
176
177std::string NameFlatTypeKind(flat::Type::Kind kind) {
178    switch (kind) {
179    case flat::Type::Kind::kArray:
180        return "array";
181    case flat::Type::Kind::kVector:
182        return "vector";
183    case flat::Type::Kind::kString:
184        return "string";
185    case flat::Type::Kind::kHandle:
186        return "handle";
187    case flat::Type::Kind::kRequestHandle:
188        return "request";
189    case flat::Type::Kind::kPrimitive:
190        return "primitive";
191    case flat::Type::Kind::kIdentifier:
192        return "identifier";
193    }
194}
195
196std::string NameFlatConstantKind(flat::Constant::Kind kind) {
197    switch (kind) {
198    case flat::Constant::Kind::kIdentifier:
199        return "identifier";
200    case flat::Constant::Kind::kLiteral:
201        return "literal";
202    }
203}
204
205std::string NameHandleZXObjType(types::HandleSubtype subtype) {
206    switch (subtype) {
207    case types::HandleSubtype::kHandle:
208        return "ZX_OBJ_TYPE_NONE";
209    case types::HandleSubtype::kProcess:
210        return "ZX_OBJ_TYPE_PROCESS";
211    case types::HandleSubtype::kThread:
212        return "ZX_OBJ_TYPE_THREAD";
213    case types::HandleSubtype::kVmo:
214        return "ZX_OBJ_TYPE_VMO";
215    case types::HandleSubtype::kChannel:
216        return "ZX_OBJ_TYPE_CHANNEL";
217    case types::HandleSubtype::kEvent:
218        return "ZX_OBJ_TYPE_EVENT";
219    case types::HandleSubtype::kPort:
220        return "ZX_OBJ_TYPE_PORT";
221    case types::HandleSubtype::kInterrupt:
222        return "ZX_OBJ_TYPE_INTERRUPT";
223    case types::HandleSubtype::kLog:
224        return "ZX_OBJ_TYPE_LOG";
225    case types::HandleSubtype::kSocket:
226        return "ZX_OBJ_TYPE_SOCKET";
227    case types::HandleSubtype::kResource:
228        return "ZX_OBJ_TYPE_RESOURCE";
229    case types::HandleSubtype::kEventpair:
230        return "ZX_OBJ_TYPE_EVENTPAIR";
231    case types::HandleSubtype::kJob:
232        return "ZX_OBJ_TYPE_JOB";
233    case types::HandleSubtype::kVmar:
234        return "ZX_OBJ_TYPE_VMAR";
235    case types::HandleSubtype::kFifo:
236        return "ZX_OBJ_TYPE_FIFO";
237    case types::HandleSubtype::kGuest:
238        return "ZX_OBJ_TYPE_GUEST";
239    case types::HandleSubtype::kTimer:
240        return "ZX_OBJ_TYPE_TIMER";
241    }
242}
243
244std::string NameUnionTag(StringView union_name, const flat::Union::Member& member) {
245    return std::string(union_name) + "Tag_" + NameIdentifier(member.name);
246}
247
248std::string NameFlatCType(const flat::Type* type, flat::Decl::Kind decl_kind) {
249    for (;;) {
250        switch (type->kind) {
251        case flat::Type::Kind::kHandle:
252        case flat::Type::Kind::kRequestHandle:
253            return "zx_handle_t";
254
255        case flat::Type::Kind::kVector:
256            return "fidl_vector_t";
257        case flat::Type::Kind::kString:
258            return "fidl_string_t";
259
260        case flat::Type::Kind::kPrimitive: {
261            auto primitive_type = static_cast<const flat::PrimitiveType*>(type);
262            return NamePrimitiveCType(primitive_type->subtype);
263        }
264
265        case flat::Type::Kind::kArray: {
266            auto array_type = static_cast<const flat::ArrayType*>(type);
267            type = array_type->element_type.get();
268            continue;
269        }
270
271        case flat::Type::Kind::kIdentifier: {
272            auto identifier_type = static_cast<const flat::IdentifierType*>(type);
273            switch (decl_kind) {
274            case flat::Decl::Kind::kConst:
275            case flat::Decl::Kind::kEnum:
276            case flat::Decl::Kind::kStruct:
277            case flat::Decl::Kind::kTable:
278            case flat::Decl::Kind::kUnion: {
279                std::string name = NameName(identifier_type->name, "_", "_");
280                if (identifier_type->nullability == types::Nullability::kNullable) {
281                    name.push_back('*');
282                }
283                return name;
284            }
285            case flat::Decl::Kind::kInterface: {
286                return "zx_handle_t";
287            }
288            default: { abort(); }
289            }
290        }
291        }
292    }
293}
294
295std::string NameIdentifier(SourceLocation name) {
296    // TODO(TO-704) C name escaping and ergonomics.
297    return name.data();
298}
299
300std::string NameName(const flat::Name& name, StringView library_separator, StringView name_separator) {
301    std::string compiled_name = LibraryName(name.library(), library_separator);
302    compiled_name += name_separator;
303    compiled_name += name.name().data();
304    return compiled_name;
305}
306
307std::string NameLibrary(const std::vector<StringView>& library_name) {
308    return StringJoin(library_name, ".");
309}
310
311std::string NameLibraryCHeader(const std::vector<StringView>& library_name) {
312    return StringJoin(library_name, "/") + "/c/fidl.h";
313}
314
315std::string NameInterface(const flat::Interface& interface) {
316    return NameName(interface.name, "_", "_");
317}
318
319std::string NameDiscoverable(const flat::Interface& interface) {
320    return NameName(interface.name, ".", ".");
321}
322
323std::string NameMethod(StringView interface_name, const flat::Interface::Method& method) {
324    return std::string(interface_name) + NameIdentifier(method.name);
325}
326
327std::string NameOrdinal(StringView method_name) {
328    std::string ordinal_name(method_name);
329    ordinal_name += "Ordinal";
330    return ordinal_name;
331}
332
333std::string NameMessage(StringView method_name, types::MessageKind kind) {
334    std::string message_name(method_name);
335    switch (kind) {
336    case types::MessageKind::kRequest:
337        message_name += "Request";
338        break;
339    case types::MessageKind::kResponse:
340        message_name += "Response";
341        break;
342    case types::MessageKind::kEvent:
343        message_name += "Event";
344        break;
345    }
346    return message_name;
347}
348
349std::string NameTable(StringView type_name) {
350    return std::string(type_name) + "Table";
351}
352
353std::string NamePointer(StringView name) {
354    std::string pointer_name(name);
355    pointer_name += "Pointer";
356    return pointer_name;
357}
358
359std::string NameMembers(StringView name) {
360    std::string members_name(name);
361    members_name += "Members";
362    return members_name;
363}
364
365std::string NameFields(StringView name) {
366    std::string fields_name(name);
367    fields_name += "Fields";
368    return fields_name;
369}
370
371std::string NameCodedStruct(const flat::Struct* struct_decl) {
372    return NameName(struct_decl->name, "_", "_");
373}
374
375std::string NameCodedTable(const flat::Table* table_decl) {
376    return NameName(table_decl->name, "_", "_");
377}
378
379std::string NameCodedUnion(const flat::Union* union_decl) {
380    return NameName(union_decl->name, "_", "_");
381}
382
383std::string NameCodedHandle(types::HandleSubtype subtype, types::Nullability nullability) {
384    std::string name("Handle");
385    name += NameHandleSubtype(subtype);
386    name += NameNullability(nullability);
387    return name;
388}
389
390std::string NameCodedInterfaceHandle(StringView interface_name, types::Nullability nullability) {
391    std::string name(interface_name);
392    name += "Interface";
393    name += NameNullability(nullability);
394    return name;
395}
396
397std::string NameCodedRequestHandle(StringView interface_name, types::Nullability nullability) {
398    std::string name(interface_name);
399    name += "Request";
400    name += NameNullability(nullability);
401    return name;
402}
403
404std::string NameCodedArray(StringView element_name, uint64_t size) {
405    std::string name("Array");
406    name += element_name;
407    name += NameSize(size);
408    return name;
409}
410
411std::string NameCodedVector(StringView element_name, uint64_t max_size,
412                            types::Nullability nullability) {
413    std::string name("Vector");
414    name += element_name;
415    name += NameSize(max_size);
416    name += NameNullability(nullability);
417    return name;
418}
419
420std::string NameCodedString(uint64_t max_size, types::Nullability nullability) {
421    std::string name("String");
422    name += NameSize(max_size);
423    name += NameNullability(nullability);
424    return name;
425}
426
427} // namespace fidl
428