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/ordinals.h"
6
7 #include <optional>
8
9 #define BORINGSSL_NO_CXX
10 #include <openssl/sha.h>
11
12 namespace fidl {
13 namespace ordinals {
14
GetSelector(const raw::AttributeList * attributes,SourceLocation name)15 std::string GetSelector(const raw::AttributeList* attributes, SourceLocation name) {
16 if (attributes != nullptr) {
17 const size_t size = attributes->attributes.size();
18 for (int i = 0; i < size; i++) {
19 if (attributes->attributes[i]->name == "Selector") {
20 return attributes->attributes[i]->value;
21 }
22 }
23 }
24 return std::string(name.data().data(), name.data().size());
25 }
26
GetOrdinal(const std::vector<StringView> & library_name,const StringView & interface_name,const raw::InterfaceMethod & method)27 raw::Ordinal GetOrdinal(const std::vector<StringView>& library_name,
28 const StringView& interface_name,
29 const raw::InterfaceMethod& method) {
30 if (method.ordinal != nullptr)
31 return *method.ordinal;
32
33 std::string method_name = GetSelector(method.attributes.get(), method.identifier->location());
34 std::string full_name;
35 bool once = false;
36 for (StringView id : library_name) {
37 if (once) {
38 full_name.push_back('.');
39 } else {
40 once = true;
41 }
42 full_name.append(id.data(), id.size());
43 }
44 full_name.append(".");
45 full_name.append(interface_name.data(), interface_name.size());
46 full_name.append("/");
47 full_name.append(method_name);
48
49 uint8_t digest[SHA256_DIGEST_LENGTH];
50 SHA256(reinterpret_cast<const uint8_t*>(full_name.data()), full_name.size(), digest);
51 // The following dance ensures that we treat the bytes as a little-endian
52 // int32 regardless of host byte order.
53 uint32_t ordinal = static_cast<uint32_t>(digest[0]) |
54 static_cast<uint32_t>(digest[1]) << 8 |
55 static_cast<uint32_t>(digest[2]) << 16 |
56 static_cast<uint32_t>(digest[3]) << 24;
57
58 ordinal &= 0x7fffffff;
59 return raw::Ordinal(*method.identifier, ordinal);
60 }
61
62 } // namespace ordinals
63 } // namespace fidl
64