1 #pragma once
2 
3 #include <cstdint> // uint8_t
4 #include <tuple> // tie
5 #include <utility> // move
6 
7 namespace nlohmann
8 {
9 
10 /*!
11 @brief an internal type for a backed binary type
12 
13 This type extends the template parameter @a BinaryType provided to `basic_json`
14 with a subtype used by BSON and MessagePack. This type exists so that the user
15 does not have to specify a type themselves with a specific naming scheme in
16 order to override the binary type.
17 
18 @tparam BinaryType container to store bytes (`std::vector<std::uint8_t>` by
19                    default)
20 
21 @since version 3.8.0
22 */
23 template<typename BinaryType>
24 class byte_container_with_subtype : public BinaryType
25 {
26   public:
27     /// the type of the underlying container
28     using container_type = BinaryType;
29 
byte_container_with_subtype()30     byte_container_with_subtype() noexcept(noexcept(container_type()))
31         : container_type()
32     {}
33 
byte_container_with_subtype(const container_type & b)34     byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
35         : container_type(b)
36     {}
37 
byte_container_with_subtype(container_type && b)38     byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
39         : container_type(std::move(b))
40     {}
41 
byte_container_with_subtype(const container_type & b,std::uint8_t subtype)42     byte_container_with_subtype(const container_type& b, std::uint8_t subtype) noexcept(noexcept(container_type(b)))
43         : container_type(b)
44         , m_subtype(subtype)
45         , m_has_subtype(true)
46     {}
47 
byte_container_with_subtype(container_type && b,std::uint8_t subtype)48     byte_container_with_subtype(container_type&& b, std::uint8_t subtype) noexcept(noexcept(container_type(std::move(b))))
49         : container_type(std::move(b))
50         , m_subtype(subtype)
51         , m_has_subtype(true)
52     {}
53 
operator ==(const byte_container_with_subtype & rhs) const54     bool operator==(const byte_container_with_subtype& rhs) const
55     {
56         return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
57                std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
58     }
59 
operator !=(const byte_container_with_subtype & rhs) const60     bool operator!=(const byte_container_with_subtype& rhs) const
61     {
62         return !(rhs == *this);
63     }
64 
65     /*!
66     @brief sets the binary subtype
67 
68     Sets the binary subtype of the value, also flags a binary JSON value as
69     having a subtype, which has implications for serialization.
70 
71     @complexity Constant.
72 
73     @exceptionsafety No-throw guarantee: this member function never throws
74     exceptions.
75 
76     @sa @ref subtype() -- return the binary subtype
77     @sa @ref clear_subtype() -- clears the binary subtype
78     @sa @ref has_subtype() -- returns whether or not the binary value has a
79     subtype
80 
81     @since version 3.8.0
82     */
set_subtype(std::uint8_t subtype)83     void set_subtype(std::uint8_t subtype) noexcept
84     {
85         m_subtype = subtype;
86         m_has_subtype = true;
87     }
88 
89     /*!
90     @brief return the binary subtype
91 
92     Returns the numerical subtype of the value if it has a subtype. If it does
93     not have a subtype, this function will return size_t(-1) as a sentinel
94     value.
95 
96     @return the numerical subtype of the binary value
97 
98     @complexity Constant.
99 
100     @exceptionsafety No-throw guarantee: this member function never throws
101     exceptions.
102 
103     @sa @ref set_subtype() -- sets the binary subtype
104     @sa @ref clear_subtype() -- clears the binary subtype
105     @sa @ref has_subtype() -- returns whether or not the binary value has a
106     subtype
107 
108     @since version 3.8.0
109     */
subtype() const110     constexpr std::uint8_t subtype() const noexcept
111     {
112         return m_subtype;
113     }
114 
115     /*!
116     @brief return whether the value has a subtype
117 
118     @return whether the value has a subtype
119 
120     @complexity Constant.
121 
122     @exceptionsafety No-throw guarantee: this member function never throws
123     exceptions.
124 
125     @sa @ref subtype() -- return the binary subtype
126     @sa @ref set_subtype() -- sets the binary subtype
127     @sa @ref clear_subtype() -- clears the binary subtype
128 
129     @since version 3.8.0
130     */
has_subtype() const131     constexpr bool has_subtype() const noexcept
132     {
133         return m_has_subtype;
134     }
135 
136     /*!
137     @brief clears the binary subtype
138 
139     Clears the binary subtype and flags the value as not having a subtype, which
140     has implications for serialization; for instance MessagePack will prefer the
141     bin family over the ext family.
142 
143     @complexity Constant.
144 
145     @exceptionsafety No-throw guarantee: this member function never throws
146     exceptions.
147 
148     @sa @ref subtype() -- return the binary subtype
149     @sa @ref set_subtype() -- sets the binary subtype
150     @sa @ref has_subtype() -- returns whether or not the binary value has a
151     subtype
152 
153     @since version 3.8.0
154     */
clear_subtype()155     void clear_subtype() noexcept
156     {
157         m_subtype = 0;
158         m_has_subtype = false;
159     }
160 
161   private:
162     std::uint8_t m_subtype = 0;
163     bool m_has_subtype = false;
164 };
165 
166 }  // namespace nlohmann
167