1/*
2 * Copyright (C) 2010, 2014-2015 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
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#include <utility>
29#include <wtf/Forward.h>
30#include <wtf/HashMap.h>
31#include <wtf/HashSet.h>
32#include <wtf/SHA1.h>
33#include <wtf/Seconds.h>
34#include <wtf/Vector.h>
35#include <wtf/WallTime.h>
36#include <wtf/persistence/PersistentDecoder.h>
37#include <wtf/persistence/PersistentEncoder.h>
38
39namespace WTF {
40namespace Persistence {
41
42template<typename T, typename U> struct Coder<std::pair<T, U>> {
43 static void encode(Encoder& encoder, const std::pair<T, U>& pair)
44 {
45 encoder << pair.first << pair.second;
46 }
47
48 static bool decode(Decoder& decoder, std::pair<T, U>& pair)
49 {
50 T first;
51 if (!decoder.decode(first))
52 return false;
53
54 U second;
55 if (!decoder.decode(second))
56 return false;
57
58 pair.first = first;
59 pair.second = second;
60 return true;
61 }
62};
63
64template<typename T> struct Coder<Optional<T>> {
65 static void encode(Encoder& encoder, const Optional<T>& optional)
66 {
67 if (!optional) {
68 encoder << false;
69 return;
70 }
71
72 encoder << true;
73 encoder << optional.value();
74 }
75
76 static bool decode(Decoder& decoder, Optional<T>& optional)
77 {
78 bool isEngaged;
79 if (!decoder.decode(isEngaged))
80 return false;
81
82 if (!isEngaged) {
83 optional = WTF::nullopt;
84 return true;
85 }
86
87 T value;
88 if (!decoder.decode(value))
89 return false;
90
91 optional = WTFMove(value);
92 return true;
93 }
94};
95
96template<typename KeyType, typename ValueType> struct Coder<WTF::KeyValuePair<KeyType, ValueType>> {
97 static void encode(Encoder& encoder, const WTF::KeyValuePair<KeyType, ValueType>& pair)
98 {
99 encoder << pair.key << pair.value;
100 }
101
102 static bool decode(Decoder& decoder, WTF::KeyValuePair<KeyType, ValueType>& pair)
103 {
104 KeyType key;
105 if (!decoder.decode(key))
106 return false;
107
108 ValueType value;
109 if (!decoder.decode(value))
110 return false;
111
112 pair.key = key;
113 pair.value = value;
114 return true;
115 }
116};
117
118template<bool fixedSizeElements, typename T, size_t inlineCapacity> struct VectorCoder;
119
120template<typename T, size_t inlineCapacity> struct VectorCoder<false, T, inlineCapacity> {
121 static void encode(Encoder& encoder, const Vector<T, inlineCapacity>& vector)
122 {
123 encoder << static_cast<uint64_t>(vector.size());
124 for (size_t i = 0; i < vector.size(); ++i)
125 encoder << vector[i];
126 }
127
128 static bool decode(Decoder& decoder, Vector<T, inlineCapacity>& vector)
129 {
130 uint64_t size;
131 if (!decoder.decode(size))
132 return false;
133
134 Vector<T, inlineCapacity> tmp;
135 for (size_t i = 0; i < size; ++i) {
136 T element;
137 if (!decoder.decode(element))
138 return false;
139
140 tmp.append(WTFMove(element));
141 }
142
143 tmp.shrinkToFit();
144 vector.swap(tmp);
145 return true;
146 }
147};
148
149template<typename T, size_t inlineCapacity> struct VectorCoder<true, T, inlineCapacity> {
150 static void encode(Encoder& encoder, const Vector<T, inlineCapacity>& vector)
151 {
152 encoder << static_cast<uint64_t>(vector.size());
153 encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(vector.data()), vector.size() * sizeof(T));
154 }
155
156 static bool decode(Decoder& decoder, Vector<T, inlineCapacity>& vector)
157 {
158 uint64_t decodedSize;
159 if (!decoder.decode(decodedSize))
160 return false;
161
162 auto size = safeCast<size_t>(decodedSize);
163
164 // Since we know the total size of the elements, we can allocate the vector in
165 // one fell swoop. Before allocating we must however make sure that the decoder buffer
166 // is big enough.
167 if (!decoder.bufferIsLargeEnoughToContain<T>(size))
168 return false;
169
170 Vector<T, inlineCapacity> temp;
171 temp.grow(size);
172
173 decoder.decodeFixedLengthData(reinterpret_cast<uint8_t*>(temp.data()), size * sizeof(T));
174
175 vector.swap(temp);
176 return true;
177 }
178};
179
180template<typename T, size_t inlineCapacity> struct Coder<Vector<T, inlineCapacity>> : VectorCoder<std::is_arithmetic<T>::value, T, inlineCapacity> { };
181
182template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg> struct Coder<HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>> {
183 typedef HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> HashMapType;
184
185 static void encode(Encoder& encoder, const HashMapType& hashMap)
186 {
187 encoder << static_cast<uint64_t>(hashMap.size());
188 for (typename HashMapType::const_iterator it = hashMap.begin(), end = hashMap.end(); it != end; ++it)
189 encoder << *it;
190 }
191
192 static bool decode(Decoder& decoder, HashMapType& hashMap)
193 {
194 uint64_t hashMapSize;
195 if (!decoder.decode(hashMapSize))
196 return false;
197
198 HashMapType tempHashMap;
199 tempHashMap.reserveInitialCapacity(static_cast<unsigned>(hashMapSize));
200 for (uint64_t i = 0; i < hashMapSize; ++i) {
201 KeyArg key;
202 MappedArg value;
203 if (!decoder.decode(key))
204 return false;
205 if (!decoder.decode(value))
206 return false;
207
208 if (!tempHashMap.add(key, value).isNewEntry) {
209 // The hash map already has the specified key, bail.
210 return false;
211 }
212 }
213
214 hashMap.swap(tempHashMap);
215 return true;
216 }
217};
218
219template<typename KeyArg, typename HashArg, typename KeyTraitsArg> struct Coder<HashSet<KeyArg, HashArg, KeyTraitsArg>> {
220 typedef HashSet<KeyArg, HashArg, KeyTraitsArg> HashSetType;
221
222 static void encode(Encoder& encoder, const HashSetType& hashSet)
223 {
224 encoder << static_cast<uint64_t>(hashSet.size());
225 for (typename HashSetType::const_iterator it = hashSet.begin(), end = hashSet.end(); it != end; ++it)
226 encoder << *it;
227 }
228
229 static bool decode(Decoder& decoder, HashSetType& hashSet)
230 {
231 uint64_t hashSetSize;
232 if (!decoder.decode(hashSetSize))
233 return false;
234
235 HashSetType tempHashSet;
236 for (uint64_t i = 0; i < hashSetSize; ++i) {
237 KeyArg key;
238 if (!decoder.decode(key))
239 return false;
240
241 if (!tempHashSet.add(key).isNewEntry) {
242 // The hash map already has the specified key, bail.
243 return false;
244 }
245 }
246
247 hashSet.swap(tempHashSet);
248 return true;
249 }
250};
251
252template<> struct Coder<Seconds> {
253 static void encode(Encoder& encoder, const Seconds& seconds)
254 {
255 encoder << seconds.value();
256 }
257
258 static bool decode(Decoder& decoder, Seconds& result)
259 {
260 double value;
261 if (!decoder.decode(value))
262 return false;
263
264 result = Seconds(value);
265 return true;
266 }
267};
268
269template<> struct Coder<WallTime> {
270 static void encode(Encoder& encoder, const WallTime& time)
271 {
272 encoder << time.secondsSinceEpoch().value();
273 }
274
275 static bool decode(Decoder& decoder, WallTime& result)
276 {
277 double value;
278 if (!decoder.decode(value))
279 return false;
280
281 result = WallTime::fromRawSeconds(value);
282 return true;
283 }
284};
285
286template<> struct Coder<AtomString> {
287 WTF_EXPORT_PRIVATE static void encode(Encoder&, const AtomString&);
288 WTF_EXPORT_PRIVATE static bool decode(Decoder&, AtomString&);
289};
290
291template<> struct Coder<CString> {
292 WTF_EXPORT_PRIVATE static void encode(Encoder&, const CString&);
293 WTF_EXPORT_PRIVATE static bool decode(Decoder&, CString&);
294};
295
296template<> struct Coder<String> {
297 WTF_EXPORT_PRIVATE static void encode(Encoder&, const String&);
298 WTF_EXPORT_PRIVATE static bool decode(Decoder&, String&);
299};
300
301template<> struct Coder<SHA1::Digest> {
302 WTF_EXPORT_PRIVATE static void encode(Encoder&, const SHA1::Digest&);
303 WTF_EXPORT_PRIVATE static bool decode(Decoder&, SHA1::Digest&);
304};
305
306}
307}
308