| // Copyright 2019 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. |
| |
| #include <zircon/assert.h> |
| |
| #include "tools/kazoo/output_util.h" |
| #include "tools/kazoo/outputs.h" |
| #include "tools/kazoo/string_util.h" |
| |
| namespace { |
| |
| class Formatter { |
| public: |
| Formatter() = default; |
| |
| struct Names { |
| std::string base_name; // signals |
| std::string type_name; // zx_signals_t |
| }; |
| |
| Names Format(const Enum& e) { |
| return Names{ |
| .base_name = e.base_name(), |
| .type_name = "zx_" + e.base_name() + "_t", |
| }; |
| } |
| |
| Names Format(const Struct& s) { |
| return Names{ |
| .base_name = s.base_name(), |
| .type_name = "zx_" + s.base_name() + "_t", |
| }; |
| } |
| |
| Names Format(const Alias& alias) { |
| return Names{ |
| .base_name = alias.base_name(), |
| .type_name = "zx_" + alias.base_name() + "_t", |
| }; |
| } |
| |
| std::string RustName(const Type& type) { |
| struct { |
| public: |
| void operator()(const std::monostate&) { ret = "<TODO!>"; } |
| void operator()(const TypeBool&) { ret = "bool"; } |
| void operator()(const TypeChar&) { ret = "u8"; } |
| void operator()(const TypeInt32&) { ret = "i32"; } |
| void operator()(const TypeInt64&) { ret = "i64"; } |
| void operator()(const TypeSizeT&) { ret = "usize"; } |
| void operator()(const TypeUint16&) { ret = "u16"; } |
| void operator()(const TypeUint32&) { ret = "u32"; } |
| void operator()(const TypeUint64&) { ret = "u64"; } |
| void operator()(const TypeUint8&) { ret = "u8"; } |
| void operator()(const TypeVoid&) { ret = "u8"; } |
| // TODO(syscall-fidl-transition): This is what abigen does, not sure if there's something |
| // better that could be done. |
| void operator()(const TypeUintptrT&) { ret = "usize"; } |
| void operator()(const TypeZxBasicAlias& zx_basic_alias) { ret = zx_basic_alias.name(); } |
| |
| void operator()(const TypeAlias& alias) { |
| ret = formatter->Format(alias.alias_data()).type_name; |
| } |
| void operator()(const TypeEnum& enm) { ret = formatter->Format(enm.enum_data()).type_name; } |
| void operator()(const TypeHandle& handle) { |
| ret = "zx_handle_t"; |
| // TOOD(syscall-fidl-transition): Once we're not trying to match abigen, it might be nice to |
| // add the underlying handle type here like "zx_handle_t /*vmo*/" or similar. |
| } |
| void operator()(const TypePointer& pointer) { |
| ret = StringPrintf("*%s %s", constness == Constness::kConst ? "const" : "mut", |
| formatter->RustName(pointer.pointed_to_type()).c_str()); |
| } |
| void operator()(const TypeString&) { |
| ZX_ASSERT(false && "can't convert string directly"); |
| ret = "<!>"; |
| } |
| void operator()(const TypeStruct& strukt) { |
| ret = formatter->Format(strukt.struct_data()).type_name; |
| } |
| void operator()(const TypeVector&) { |
| ZX_ASSERT(false && "can't convert vector directly"); |
| ret = "<!>"; |
| } |
| |
| Constness constness; |
| Formatter* formatter; |
| std::string ret; |
| } name_visitor; |
| name_visitor.formatter = this; |
| name_visitor.constness = type.constness(); |
| std::visit(name_visitor, type.type_data()); |
| return name_visitor.ret; |
| } |
| }; |
| |
| } // namespace |
| |
| std::string mangle_identifier(std::string type) { |
| // type is a reserved name in rustc |
| if (type == "type") { |
| return "ty"; |
| } else { |
| return type; |
| } |
| } |
| |
| bool RustOutput(const SyscallLibrary& library, Writer* writer) { |
| CopyrightHeaderWithCppComments(writer); |
| |
| Formatter formatter; |
| constexpr const char indent[] = " "; |
| writer->Puts("// re-export the types defined in the fuchsia-zircon-types crate\n"); |
| writer->Puts("pub use fuchsia_zircon_types::*;\n"); |
| writer->Puts("// only link against zircon when targeting Fuchsia\n"); |
| writer->Puts("#[cfg(target_os = \"fuchsia\")]\n"); |
| writer->Puts("#[link(name = \"zircon\")]\n"); |
| writer->Puts("extern {\n"); |
| for (const auto& syscall : library.syscalls()) { |
| if (syscall->HasAttribute("internal")) { |
| continue; |
| } |
| |
| writer->Printf("%spub fn zx_%s(\n", indent, syscall->name().c_str()); |
| for (size_t i = 0; i < syscall->kernel_arguments().size(); ++i) { |
| const StructMember& arg = syscall->kernel_arguments()[i]; |
| const bool last = i == syscall->kernel_arguments().size() - 1; |
| writer->Printf("%s%s%s: %s%s\n", indent, indent, mangle_identifier(arg.name()).c_str(), |
| formatter.RustName(arg.type()).c_str(), last ? "" : ","); |
| } |
| writer->Printf("%s%s)", indent, indent); |
| if (!syscall->kernel_return_type().IsVoid()) { |
| writer->Printf(" -> %s", formatter.RustName(syscall->kernel_return_type()).c_str()); |
| } |
| writer->Puts(";\n\n"); |
| } |
| writer->Puts("}\n"); |
| |
| return true; |
| } |