1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef NETUTILS_HANDLE_H
18 #define NETUTILS_HANDLE_H
19 
20 #include <ostream>
21 
22 namespace android {
23 namespace netdutils {
24 
25 // Opaque, strongly typed wrapper for integer-like handles.
26 // Explicitly avoids implementing arithmetic operations.
27 //
28 // This class is intended to avoid common errors when reordering
29 // arguments to functions, typos and other cases where plain integer
30 // types would silently cover up the mistake.
31 //
32 // usage:
33 // DEFINE_HANDLE(ProductId, uint64_t);
34 // DEFINE_HANDLE(ThumbnailHash, uint64_t);
35 // void foo(ProductId p, ThumbnailHash th) {...}
36 //
37 // void test() {
38 //     ProductId p(88);
39 //     ThumbnailHash th1(100), th2(200);
40 //
41 //     foo(p, th1);        <- ok!
42 //     foo(th1, p);        <- disallowed!
43 //     th1 += 10;          <- disallowed!
44 //     p = th2;            <- disallowed!
45 //     assert(th1 != th2); <- ok!
46 // }
47 template <typename T, typename TagT>
48 class Handle {
49   public:
50     constexpr Handle() = default;
Handle(const T & value)51     constexpr Handle(const T& value) : mValue(value) {}
52 
get()53     const T get() const { return mValue; }
54 
55     bool operator==(const Handle& that) const { return get() == that.get(); }
56     bool operator!=(const Handle& that) const { return get() != that.get(); }
57 
58   private:
59     T mValue;
60 };
61 
62 #define DEFINE_HANDLE(name, type) \
63     struct _##name##Tag {};       \
64     using name = ::android::netdutils::Handle<type, _##name##Tag>;
65 
66 template <typename T, typename TagT>
67 inline std::ostream& operator<<(std::ostream& os, const Handle<T, TagT>& handle) {
68     return os << handle.get();
69 }
70 
71 }  // namespace netdutils
72 }  // namespace android
73 
74 #endif /* NETUTILS_HANDLE_H */
75