1/* 2 * Copyright (C) 2013 University of Washington. All rights reserved. 3 * Copyright (C) 2014 Apple Inc. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 16 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 18 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28#ifndef EncodedValue_h 29#define EncodedValue_h 30 31#if ENABLE(WEB_REPLAY) 32 33#include "InspectorValues.h" 34#include <wtf/Forward.h> 35#include <wtf/Vector.h> 36 37namespace JSC { 38 39class NondeterministicInputBase; 40template<typename T> struct EncodingTraits; 41 42class EncodedValue final { 43public: 44 explicit EncodedValue(PassRefPtr<Inspector::InspectorValue> value) 45 : m_value(value) { } 46 47 EncodedValue() 48 : m_value(nullptr) { } 49 50 static EncodedValue createObject() 51 { 52 return EncodedValue(Inspector::InspectorObject::create()); 53 } 54 55 static EncodedValue createArray() 56 { 57 return EncodedValue(Inspector::InspectorArray::create()); 58 } 59 60 static EncodedValue createString(const String& value) 61 { 62 return EncodedValue(Inspector::InspectorString::create(value)); 63 } 64 65 static EncodedValue createString(const char* value) 66 { 67 return EncodedValue(Inspector::InspectorString::create(value)); 68 } 69 70 template<typename T> 71 void put(const String&, const typename EncodingTraits<T>::DecodedType&); 72 73 template<typename T> 74 void append(const typename EncodingTraits<T>::DecodedType&); 75 76 template<typename T> bool get(const String&, typename EncodingTraits<T>::DecodedType&); 77 template<typename T> bool get(const String&, std::unique_ptr<typename EncodingTraits<T>::DecodedType>&); 78 79 template<typename T> T convertTo(); 80 81 JS_EXPORT_PRIVATE PassRefPtr<Inspector::InspectorObject> asObject(); 82 JS_EXPORT_PRIVATE PassRefPtr<Inspector::InspectorArray> asArray(); 83 84private: 85 RefPtr<Inspector::InspectorValue> m_value; 86}; 87 88template<> JS_EXPORT_PRIVATE bool EncodedValue::convertTo<bool>(); 89template<> JS_EXPORT_PRIVATE double EncodedValue::convertTo<double>(); 90template<> JS_EXPORT_PRIVATE float EncodedValue::convertTo<float>(); 91template<> JS_EXPORT_PRIVATE int32_t EncodedValue::convertTo<int32_t>(); 92template<> JS_EXPORT_PRIVATE int64_t EncodedValue::convertTo<int64_t>(); 93template<> JS_EXPORT_PRIVATE uint32_t EncodedValue::convertTo<uint32_t>(); 94template<> JS_EXPORT_PRIVATE uint64_t EncodedValue::convertTo<uint64_t>(); 95template<> JS_EXPORT_PRIVATE unsigned long EncodedValue::convertTo<unsigned long>(); 96template<> JS_EXPORT_PRIVATE String EncodedValue::convertTo<String>(); 97 98template<typename T> 99struct EncodingTraits { 100 typedef T DecodedType; 101 102 static EncodedValue encodeValue(const DecodedType&); 103 104 static bool decodeValue(EncodedValue&, DecodedType&); 105 static bool decodeValue(EncodedValue&, std::unique_ptr<DecodedType>&); 106}; 107 108template<typename T, size_t inlineCapacity, typename OverflowHandler> 109struct EncodingTraits<Vector<T, inlineCapacity, OverflowHandler>> { 110 typedef Vector<typename EncodingTraits<T>::DecodedType, inlineCapacity, OverflowHandler> DecodedType; 111 112 static EncodedValue encodeValue(const DecodedType& vectorOfValues) 113 { 114 EncodedValue encodedVector = EncodedValue::createArray(); 115 for (const typename EncodingTraits<T>::DecodedType& value : vectorOfValues) 116 encodedVector.append<typename EncodingTraits<T>::DecodedType>(value); 117 118 return WTF::move(encodedVector); 119 } 120 121 static bool decodeValue(EncodedValue& encodedVector, DecodedType& decodedValue) 122 { 123 RefPtr<Inspector::InspectorArray> inspectorArray = encodedVector.asArray(); 124 decodedValue = Vector<typename EncodingTraits<T>::DecodedType, inlineCapacity, OverflowHandler>(inspectorArray->length()); 125 for (size_t i = 0; i < inspectorArray->length(); ++i) { 126 EncodedValue encodedElement(inspectorArray->get(i)); 127 if (!EncodingTraits<T>::decodeValue(encodedElement, decodedValue.at(i))) 128 return false; 129 } 130 return true; 131 } 132}; 133 134template<> struct EncodingTraits<EncodedValue> { 135 typedef EncodedValue DecodedType; 136 // We should never attempt to decode or encode an encoded value, 137 // so encodeValue and decodeValue are intentionally omitted here. 138}; 139 140template<typename T> 141struct ScalarEncodingTraits { 142 typedef T DecodedType; 143 144 static JS_EXPORT_PRIVATE EncodedValue encodeValue(const DecodedType& decodedValue); 145 static bool decodeValue(EncodedValue& encodedValue, DecodedType& decodedValue) 146 { 147 decodedValue = encodedValue.convertTo<DecodedType>(); 148 return true; 149 } 150}; 151 152template<> struct EncodingTraits<bool> : public ScalarEncodingTraits<bool> { }; 153template<> struct EncodingTraits<double> : public ScalarEncodingTraits<double> { }; 154template<> struct EncodingTraits<float> : public ScalarEncodingTraits<float> { }; 155template<> struct EncodingTraits<int32_t> : public ScalarEncodingTraits<int32_t> { }; 156template<> struct EncodingTraits<int64_t> : public ScalarEncodingTraits<int64_t> { }; 157template<> struct EncodingTraits<uint32_t> : public ScalarEncodingTraits<uint32_t> { }; 158template<> struct EncodingTraits<uint64_t> : public ScalarEncodingTraits<uint64_t> { }; 159template<> struct EncodingTraits<unsigned long> : public ScalarEncodingTraits<unsigned long> { }; 160 161template<> struct EncodingTraits<String> : public ScalarEncodingTraits<String> { 162 static EncodedValue encodeValue(const String& value) 163 { 164 return EncodedValue::createString(value); 165 } 166}; 167 168// Base cases for loading and storing values. 169template<> JS_EXPORT_PRIVATE 170void EncodedValue::put<EncodedValue>(const String& key, const typename EncodingTraits<EncodedValue>::DecodedType&); 171 172template<> JS_EXPORT_PRIVATE 173void EncodedValue::append<EncodedValue>(const typename EncodingTraits<EncodedValue>::DecodedType&); 174 175template<> JS_EXPORT_PRIVATE 176bool EncodedValue::get<EncodedValue>(const String& key, typename EncodingTraits<EncodedValue>::DecodedType&); 177 178// Load and store types with an accompanying EncodingTraits implementation. 179template<typename T> 180void EncodedValue::put(const String& key, const typename EncodingTraits<T>::DecodedType& value) 181{ 182 EncodedValue encodedValue = EncodingTraits<T>::encodeValue(value); 183 put<EncodedValue>(key, encodedValue); 184} 185 186template<typename T> 187void EncodedValue::append(const typename EncodingTraits<T>::DecodedType& value) 188{ 189 EncodedValue encodedValue = EncodingTraits<T>::encodeValue(value); 190 append<EncodedValue>(encodedValue); 191} 192 193template<typename T> 194bool EncodedValue::get(const String& key, typename EncodingTraits<T>::DecodedType& decodedValue) 195{ 196 EncodedValue encodedValue; 197 if (!get<EncodedValue>(key, encodedValue)) 198 return false; 199 200 return EncodingTraits<T>::decodeValue(encodedValue, decodedValue); 201} 202 203template<typename T> 204bool EncodedValue::get(const String& key, std::unique_ptr<typename EncodingTraits<T>::DecodedType>& decodedValue) 205{ 206 EncodedValue encodedValue; 207 if (!get<EncodedValue>(key, encodedValue)) 208 return false; 209 210 return EncodingTraits<T>::decodeValue(encodedValue, decodedValue); 211} 212 213} // namespace JSC 214 215using JSC::EncodedValue; 216using JSC::EncodingTraits; 217 218#endif // ENABLE(WEB_REPLAY) 219 220#endif // EncodedValue_h 221