1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef MOJO_PUBLIC_BINDINGS_LIB_BINDINGS_SERIALIZATION_H_ 6#define MOJO_PUBLIC_BINDINGS_LIB_BINDINGS_SERIALIZATION_H_ 7 8#include <string.h> 9 10#include <vector> 11 12#include "mojo/public/bindings/lib/bindings.h" 13#include "mojo/public/bindings/lib/message.h" 14 15namespace mojo { 16namespace internal { 17 18size_t Align(size_t size); 19 20// Pointers are encoded as relative offsets. The offsets are relative to the 21// address of where the offset value is stored, such that the pointer may be 22// recovered with the expression: 23// 24// ptr = reinterpret_cast<char*>(offset) + *offset 25// 26// A null pointer is encoded as an offset value of 0. 27// 28void EncodePointer(const void* ptr, uint64_t* offset); 29const void* DecodePointerRaw(const uint64_t* offset); 30 31template <typename T> 32inline void DecodePointer(const uint64_t* offset, T** ptr) { 33 *ptr = reinterpret_cast<T*>(const_cast<void*>(DecodePointerRaw(offset))); 34} 35 36// Check that the given pointer references memory contained within the message. 37bool ValidatePointer(const void* ptr, const Message& message); 38 39// Handles are encoded as indices into a vector of handles. These functions 40// manipulate the value of |handle|, mapping it to and from an index. 41void EncodeHandle(Handle* handle, std::vector<Handle>* handles); 42bool DecodeHandle(Handle* handle, std::vector<Handle>* handles); 43 44// All objects (structs and arrays) support the following operations: 45// - computing size 46// - cloning 47// - encoding pointers and handles 48// - decoding pointers and handles 49// 50// The following functions are used to select the proper ObjectTraits<> 51// specialization. 52 53template <typename T> 54inline size_t ComputeSizeOf(const T* obj) { 55 return obj ? ObjectTraits<T>::ComputeSizeOf(obj) : 0; 56} 57 58template <typename T> 59inline T* Clone(const T* obj, Buffer* buf) { 60 return obj ? ObjectTraits<T>::Clone(obj, buf) : NULL; 61} 62 63template <typename T> 64inline void CloseHandles(T* obj) { 65 if (obj) 66 ObjectTraits<T>::CloseHandles(obj); 67} 68 69template <typename T> 70inline void EncodePointersAndHandles(T* obj, 71 std::vector<Handle>* handles) { 72 ObjectTraits<T>::EncodePointersAndHandles(obj, handles); 73} 74 75template <typename T> 76inline bool DecodePointersAndHandles(T* obj, Message* message) { 77 return ObjectTraits<T>::DecodePointersAndHandles(obj, message); 78} 79 80// The following 2 functions are used to encode/decode all objects (structs and 81// arrays) in a consistent manner. 82 83template <typename T> 84inline void Encode(T* obj, std::vector<Handle>* handles) { 85 if (obj->ptr) 86 EncodePointersAndHandles(obj->ptr, handles); 87 EncodePointer(obj->ptr, &obj->offset); 88} 89 90template <typename T> 91inline bool Decode(T* obj, Message* message) { 92 DecodePointer(&obj->offset, &obj->ptr); 93 if (obj->ptr) { 94 if (!ValidatePointer(obj->ptr, *message)) 95 return false; 96 if (!DecodePointersAndHandles(obj->ptr, message)) 97 return false; 98 } 99 return true; 100} 101 102// What follows is code to support the ObjectTraits<> specialization of 103// Array_Data<T>. There are two interesting cases: arrays of primitives and 104// arrays of objects. Arrays of objects are represented as arrays of pointers 105// to objects. 106 107template <typename T> 108struct ArrayHelper { 109 typedef T ElementType; 110 111 static size_t ComputeSizeOfElements(const ArrayHeader* header, 112 const ElementType* elements) { 113 return 0; 114 } 115 116 static void CloneElements(const ArrayHeader* header, 117 ElementType* elements, 118 Buffer* buf) { 119 } 120 121 static void EncodePointersAndHandles(const ArrayHeader* header, 122 ElementType* elements, 123 std::vector<Handle>* handles) { 124 } 125 static bool DecodePointersAndHandles(const ArrayHeader* header, 126 ElementType* elements, 127 Message* message) { 128 return true; 129 } 130}; 131 132template <> 133struct ArrayHelper<Handle> { 134 typedef Handle ElementType; 135 136 static size_t ComputeSizeOfElements(const ArrayHeader* header, 137 const ElementType* elements) { 138 return 0; 139 } 140 141 static void CloneElements(const ArrayHeader* header, 142 ElementType* elements, 143 Buffer* buf) { 144 } 145 146 static void EncodePointersAndHandles(const ArrayHeader* header, 147 ElementType* elements, 148 std::vector<Handle>* handles); 149 static bool DecodePointersAndHandles(const ArrayHeader* header, 150 ElementType* elements, 151 Message* message); 152}; 153 154template <typename P> 155struct ArrayHelper<P*> { 156 typedef StructPointer<P> ElementType; 157 158 static size_t ComputeSizeOfElements(const ArrayHeader* header, 159 const ElementType* elements) { 160 size_t result = 0; 161 for (uint32_t i = 0; i < header->num_elements; ++i) 162 result += ComputeSizeOf(elements[i].ptr); 163 return result; 164 } 165 166 static void CloneElements(const ArrayHeader* header, 167 ElementType* elements, 168 Buffer* buf) { 169 for (uint32_t i = 0; i < header->num_elements; ++i) 170 elements[i].ptr = Clone(elements[i].ptr, buf); 171 } 172 173 static void EncodePointersAndHandles(const ArrayHeader* header, 174 ElementType* elements, 175 std::vector<Handle>* handles) { 176 for (uint32_t i = 0; i < header->num_elements; ++i) 177 Encode(&elements[i], handles); 178 } 179 static bool DecodePointersAndHandles(const ArrayHeader* header, 180 ElementType* elements, 181 Message* message) { 182 for (uint32_t i = 0; i < header->num_elements; ++i) { 183 if (!Decode(&elements[i], message)) 184 return false; 185 } 186 return true; 187 } 188}; 189 190template <typename T> 191class ObjectTraits<Array_Data<T> > { 192 public: 193 static size_t ComputeSizeOf(const Array_Data<T>* array) { 194 return Align(array->header_.num_bytes) + 195 ArrayHelper<T>::ComputeSizeOfElements(&array->header_, 196 array->storage()); 197 } 198 199 static Array_Data<T>* Clone(const Array_Data<T>* array, Buffer* buf) { 200 Array_Data<T>* clone = Array_Data<T>::New(array->header_.num_elements, buf); 201 memcpy(clone->storage(), 202 array->storage(), 203 array->header_.num_bytes - sizeof(Array_Data<T>)); 204 205 ArrayHelper<T>::CloneElements(&clone->header_, clone->storage(), buf); 206 return clone; 207 } 208 209 static void CloseHandles(Array_Data<T>* array) { 210 // TODO(darin): Implement! 211 } 212 213 static void EncodePointersAndHandles(Array_Data<T>* array, 214 std::vector<Handle>* handles) { 215 ArrayHelper<T>::EncodePointersAndHandles(&array->header_, array->storage(), 216 handles); 217 } 218 219 static bool DecodePointersAndHandles(Array_Data<T>* array, 220 Message* message) { 221 return ArrayHelper<T>::DecodePointersAndHandles(&array->header_, 222 array->storage(), 223 message); 224 } 225}; 226 227} // namespace internal 228} // namespace mojo 229 230#endif // MOJO_PUBLIC_BINDINGS_LIB_BINDINGS_SERIALIZATION_H_ 231