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), alignof(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 for (uint64_t i = 0; i < hashMapSize; ++i) {
200 KeyArg key;
201 MappedArg value;
202 if (!decoder.decode(key))
203 return false;
204 if (!decoder.decode(value))
205 return false;
206
207 if (!tempHashMap.add(key, value).isNewEntry) {
208 // The hash map already has the specified key, bail.
209 return false;
210 }
211 }
212
213 hashMap.swap(tempHashMap);
214 return true;
215 }
216};
217
218template<typename KeyArg, typename HashArg, typename KeyTraitsArg> struct Coder<HashSet<KeyArg, HashArg, KeyTraitsArg>> {
219 typedef HashSet<KeyArg, HashArg, KeyTraitsArg> HashSetType;
220
221 static void encode(Encoder& encoder, const HashSetType& hashSet)
222 {
223 encoder << static_cast<uint64_t>(hashSet.size());
224 for (typename HashSetType::const_iterator it = hashSet.begin(), end = hashSet.end(); it != end; ++it)
225 encoder << *it;
226 }
227
228 static bool decode(Decoder& decoder, HashSetType& hashSet)
229 {
230 uint64_t hashSetSize;
231 if (!decoder.decode(hashSetSize))
232 return false;
233
234 HashSetType tempHashSet;
235 for (uint64_t i = 0; i < hashSetSize; ++i) {
236 KeyArg key;
237 if (!decoder.decode(key))
238 return false;
239
240 if (!tempHashSet.add(key).isNewEntry) {
241 // The hash map already has the specified key, bail.
242 return false;
243 }
244 }
245
246 hashSet.swap(tempHashSet);
247 return true;
248 }
249};
250
251template<> struct Coder<Seconds> {
252 static void encode(Encoder& encoder, const Seconds& seconds)
253 {
254 encoder << seconds.value();
255 }
256
257 static bool decode(Decoder& decoder, Seconds& result)
258 {
259 double value;
260 if (!decoder.decode(value))
261 return false;
262
263 result = Seconds(value);
264 return true;
265 }
266};
267
268template<> struct Coder<WallTime> {
269 static void encode(Encoder& encoder, const WallTime& time)
270 {
271 encoder << time.secondsSinceEpoch().value();
272 }
273
274 static bool decode(Decoder& decoder, WallTime& result)
275 {
276 double value;
277 if (!decoder.decode(value))
278 return false;
279
280 result = WallTime::fromRawSeconds(value);
281 return true;
282 }
283};
284
285template<> struct Coder<AtomString> {
286 WTF_EXPORT_PRIVATE static void encode(Encoder&, const AtomString&);
287 WTF_EXPORT_PRIVATE static bool decode(Decoder&, AtomString&);
288};
289
290template<> struct Coder<CString> {
291 WTF_EXPORT_PRIVATE static void encode(Encoder&, const CString&);
292 WTF_EXPORT_PRIVATE static bool decode(Decoder&, CString&);
293};
294
295template<> struct Coder<String> {
296 WTF_EXPORT_PRIVATE static void encode(Encoder&, const String&);
297 WTF_EXPORT_PRIVATE static bool decode(Decoder&, String&);
298};
299
300template<> struct Coder<SHA1::Digest> {
301 WTF_EXPORT_PRIVATE static void encode(Encoder&, const SHA1::Digest&);
302 WTF_EXPORT_PRIVATE static bool decode(Decoder&, SHA1::Digest&);
303};
304
305}
306}
307