1// Copyright 2017 The Chromium Authors. All rights reserved.
2// Copyright (C) 2018 Apple Inc. All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8// * Redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above
11// copyright notice, this list of conditions and the following disclaimer
12// in the documentation and/or other materials provided with the
13// distribution.
14// * Neither the name of Google Inc. nor the names of its
15// contributors may be used to endorse or promote products derived from
16// this software without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30#include "config.h"
31#include "CBORValue.h"
32
33#if ENABLE(WEB_AUTHN)
34
35#include <new>
36#include <utility>
37
38namespace cbor {
39
40CBORValue::CBORValue()
41 : m_type(Type::None)
42{
43}
44
45CBORValue::CBORValue(CBORValue&& that)
46{
47 internalMoveConstructFrom(WTFMove(that));
48}
49
50CBORValue::CBORValue(Type type)
51 : m_type(type)
52{
53 // Initialize with the default value.
54 switch (m_type) {
55 case Type::Unsigned:
56 case Type::Negative:
57 m_integerValue = 0;
58 return;
59 case Type::ByteString:
60 new (&m_byteStringValue) BinaryValue();
61 return;
62 case Type::String:
63 new (&m_stringValue) String();
64 return;
65 case Type::Array:
66 new (&m_arrayValue) ArrayValue();
67 return;
68 case Type::Map:
69 new (&m_mapValue) MapValue();
70 return;
71 case Type::SimpleValue:
72 m_simpleValue = CBORValue::SimpleValue::Undefined;
73 return;
74 case Type::None:
75 return;
76 }
77 ASSERT_NOT_REACHED();
78}
79
80CBORValue::CBORValue(int integerValue)
81 : CBORValue(static_cast<int64_t>(integerValue))
82{
83}
84
85CBORValue::CBORValue(int64_t integerValue)
86 : m_integerValue(integerValue)
87{
88 m_type = integerValue >= 0 ? Type::Unsigned : Type::Negative;
89}
90
91CBORValue::CBORValue(const BinaryValue& inBytes)
92 : m_type(Type::ByteString)
93 , m_byteStringValue(inBytes)
94{
95}
96
97CBORValue::CBORValue(BinaryValue&& inBytes)
98 : m_type(Type::ByteString)
99 , m_byteStringValue(WTFMove(inBytes))
100{
101}
102
103CBORValue::CBORValue(const char* inString)
104 : CBORValue(String(inString))
105{
106}
107
108CBORValue::CBORValue(String&& inString)
109 : m_type(Type::String)
110 , m_stringValue(WTFMove(inString))
111{
112}
113
114CBORValue::CBORValue(const String& inString)
115 : m_type(Type::String)
116 , m_stringValue(inString)
117{
118}
119
120CBORValue::CBORValue(const ArrayValue& inArray)
121 : m_type(Type::Array)
122 , m_arrayValue()
123{
124 m_arrayValue.reserveCapacity(inArray.size());
125 for (const auto& val : inArray)
126 m_arrayValue.append(val.clone());
127}
128
129CBORValue::CBORValue(ArrayValue&& inArray)
130 : m_type(Type::Array)
131 , m_arrayValue(WTFMove(inArray))
132{
133}
134
135CBORValue::CBORValue(const MapValue& inMap)
136 : m_type(Type::Map)
137 , m_mapValue()
138{
139 for (const auto& it : inMap)
140 m_mapValue.emplace_hint(m_mapValue.end(), it.first.clone(), it.second.clone());
141}
142
143CBORValue::CBORValue(MapValue&& inMap)
144 : m_type(Type::Map)
145 , m_mapValue(WTFMove(inMap))
146{
147}
148
149CBORValue::CBORValue(SimpleValue inSimple)
150 : m_type(Type::SimpleValue)
151 , m_simpleValue(inSimple)
152{
153 ASSERT(static_cast<int>(inSimple) >= 20 && static_cast<int>(inSimple) <= 23);
154}
155
156CBORValue::CBORValue(bool inBool)
157 : m_type(Type::SimpleValue)
158{
159 m_simpleValue = inBool ? CBORValue::SimpleValue::TrueValue : CBORValue::SimpleValue::FalseValue;
160}
161
162CBORValue& CBORValue::operator=(CBORValue&& that)
163{
164 internalCleanup();
165 internalMoveConstructFrom(WTFMove(that));
166
167 return *this;
168}
169
170CBORValue::~CBORValue()
171{
172 internalCleanup();
173}
174
175CBORValue CBORValue::clone() const
176{
177 switch (m_type) {
178 case Type::None:
179 return CBORValue();
180 case Type::Unsigned:
181 case Type::Negative:
182 return CBORValue(m_integerValue);
183 case Type::ByteString:
184 return CBORValue(m_byteStringValue);
185 case Type::String:
186 return CBORValue(m_stringValue);
187 case Type::Array:
188 return CBORValue(m_arrayValue);
189 case Type::Map:
190 return CBORValue(m_mapValue);
191 case Type::SimpleValue:
192 return CBORValue(m_simpleValue);
193 }
194
195 ASSERT_NOT_REACHED();
196 return CBORValue();
197}
198
199const int64_t& CBORValue::getInteger() const
200{
201 ASSERT(isInteger());
202 return m_integerValue;
203}
204
205const int64_t& CBORValue::getUnsigned() const
206{
207 ASSERT(isUnsigned());
208 ASSERT(m_integerValue >= 0);
209 return m_integerValue;
210}
211
212const int64_t& CBORValue::getNegative() const
213{
214 ASSERT(isNegative());
215 ASSERT(m_integerValue < 0);
216 return m_integerValue;
217}
218
219const String& CBORValue::getString() const
220{
221 ASSERT(isString());
222 return m_stringValue;
223}
224
225const CBORValue::BinaryValue& CBORValue::getByteString() const
226{
227 ASSERT(isByteString());
228 return m_byteStringValue;
229}
230
231const CBORValue::ArrayValue& CBORValue::getArray() const
232{
233 ASSERT(isArray());
234 return m_arrayValue;
235}
236
237const CBORValue::MapValue& CBORValue::getMap() const
238{
239 ASSERT(isMap());
240 return m_mapValue;
241}
242
243CBORValue::SimpleValue CBORValue::getSimpleValue() const
244{
245 ASSERT(isSimple());
246 return m_simpleValue;
247}
248
249bool CBORValue::getBool() const
250{
251 ASSERT(isBool());
252 return m_simpleValue == SimpleValue::TrueValue;
253}
254
255void CBORValue::internalMoveConstructFrom(CBORValue&& that)
256{
257 m_type = that.m_type;
258
259 switch (m_type) {
260 case Type::Unsigned:
261 case Type::Negative:
262 m_integerValue = that.m_integerValue;
263 return;
264 case Type::ByteString:
265 new (&m_byteStringValue) BinaryValue(WTFMove(that.m_byteStringValue));
266 return;
267 case Type::String:
268 new (&m_stringValue) String(WTFMove(that.m_stringValue));
269 return;
270 case Type::Array:
271 new (&m_arrayValue) ArrayValue(WTFMove(that.m_arrayValue));
272 return;
273 case Type::Map:
274 new (&m_mapValue) MapValue(WTFMove(that.m_mapValue));
275 return;
276 case Type::SimpleValue:
277 m_simpleValue = that.m_simpleValue;
278 return;
279 case Type::None:
280 return;
281 }
282 ASSERT_NOT_REACHED();
283}
284
285void CBORValue::internalCleanup()
286{
287 switch (m_type) {
288 case Type::ByteString:
289 m_byteStringValue.~BinaryValue();
290 break;
291 case Type::String:
292 m_stringValue.~String();
293 break;
294 case Type::Array:
295 m_arrayValue.~ArrayValue();
296 break;
297 case Type::Map:
298 m_mapValue.~MapValue();
299 break;
300 case Type::None:
301 case Type::Unsigned:
302 case Type::Negative:
303 case Type::SimpleValue:
304 break;
305 }
306 m_type = Type::None;
307}
308
309} // namespace cbor
310
311#endif // ENABLE(WEB_AUTHN)
312