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