1 // Copyright 2019 The Chromium 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 DISCOVERY_DNSSD_IMPL_SERVICE_KEY_H_
6 #define DISCOVERY_DNSSD_IMPL_SERVICE_KEY_H_
7
8 #include <string>
9 #include <utility>
10
11 #include "absl/strings/string_view.h"
12 #include "platform/base/error.h"
13
14 namespace openscreen {
15 namespace discovery {
16
17 class DomainName;
18 class MdnsRecord;
19
20 // This class is intended to be used as the key of a std::unordered_map or a
21 // std::map when referencing data related to a service type
22 class ServiceKey {
23 public:
24 // NOTE: The record provided must have valid service domain labels.
25 explicit ServiceKey(const MdnsRecord& record);
26 explicit ServiceKey(const DomainName& domain);
27 virtual ~ServiceKey() = default;
28
29 // NOTE: The provided service and domain labels must be valid.
30 ServiceKey(absl::string_view service, absl::string_view domain);
31 ServiceKey(const ServiceKey& other);
32 ServiceKey(ServiceKey&& other);
33
34 ServiceKey& operator=(const ServiceKey& rhs);
35 ServiceKey& operator=(ServiceKey&& rhs);
36
37 virtual DomainName GetName() const;
38
service_id()39 const std::string& service_id() const { return service_id_; }
domain_id()40 const std::string& domain_id() const { return domain_id_; }
41
42 private:
43 static ErrorOr<ServiceKey> TryCreate(const MdnsRecord& record);
44 static ErrorOr<ServiceKey> TryCreate(const DomainName& domain);
45
46 std::string service_id_;
47 std::string domain_id_;
48
49 template <typename H>
50 friend H AbslHashValue(H h, const ServiceKey& key);
51
52 friend bool operator<(const ServiceKey& lhs, const ServiceKey& rhs);
53
54 // Validation method which needs the same code as CreateFromRecord(). Use a
55 // friend declaration to avoid duplicating this code while still keeping the
56 // factory private.
57 friend bool HasValidDnsRecordAddress(const MdnsRecord& record);
58 friend bool HasValidDnsRecordAddress(const DomainName& domain);
59 };
60
61 // Hashing functions to allow for using with absl::Hash<...>.
62 template <typename H>
AbslHashValue(H h,const ServiceKey & key)63 H AbslHashValue(H h, const ServiceKey& key) {
64 return H::combine(std::move(h), key.service_id_, key.domain_id_);
65 }
66
67 // Comparison operators for using above keys with an std::map
68 inline bool operator<(const ServiceKey& lhs, const ServiceKey& rhs) {
69 int comp = lhs.domain_id_.compare(rhs.domain_id_);
70 if (comp != 0) {
71 return comp < 0;
72 }
73 return lhs.service_id_ < rhs.service_id_;
74 }
75
76 inline bool operator>(const ServiceKey& lhs, const ServiceKey& rhs) {
77 return rhs < lhs;
78 }
79
80 inline bool operator<=(const ServiceKey& lhs, const ServiceKey& rhs) {
81 return !(rhs > lhs);
82 }
83
84 inline bool operator>=(const ServiceKey& lhs, const ServiceKey& rhs) {
85 return !(rhs < lhs);
86 }
87
88 inline bool operator==(const ServiceKey& lhs, const ServiceKey& rhs) {
89 return lhs <= rhs && lhs >= rhs;
90 }
91
92 inline bool operator!=(const ServiceKey& lhs, const ServiceKey& rhs) {
93 return !(lhs == rhs);
94 }
95
96 } // namespace discovery
97 } // namespace openscreen
98
99 #endif // DISCOVERY_DNSSD_IMPL_SERVICE_KEY_H_
100