1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file. 4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 5e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ 6e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ 7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <new> 9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <vector> 10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "mojo/public/c/system/macros.h" 12e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "mojo/public/cpp/bindings/lib/bindings_internal.h" 13e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "mojo/public/cpp/bindings/lib/bindings_serialization.h" 1446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "mojo/public/cpp/bindings/lib/bounds_checker.h" 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "mojo/public/cpp/bindings/lib/buffer.h" 166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "mojo/public/cpp/bindings/lib/template_util.h" 1746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "mojo/public/cpp/bindings/lib/validation_errors.h" 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "mojo/public/cpp/environment/logging.h" 19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace mojo { 21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)template <typename T> class Array; 22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class String; 23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace internal { 25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 2603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// std::numeric_limits<uint32_t>::max() is not a compile-time constant (until 2703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// C++11). 2803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const uint32_t kMaxUint32 = 0xFFFFFFFF; 2903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 3003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)std::string MakeMessageWithArrayIndex(const char* message, 3103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) size_t size, 3203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) size_t index); 3303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 3403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)std::string MakeMessageWithExpectedArraySize(const char* message, 3503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) size_t size, 3603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) size_t expected_size); 3703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)template <typename T> 39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)struct ArrayDataTraits { 40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) typedef T StorageType; 41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) typedef T& Ref; 42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) typedef T const& ConstRef; 43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 4403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) static const uint32_t kMaxNumElements = 4503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) (kMaxUint32 - sizeof(ArrayHeader)) / sizeof(StorageType); 4603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 4703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) static uint32_t GetStorageSize(uint32_t num_elements) { 4803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) MOJO_DCHECK(num_elements <= kMaxNumElements); 4903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return sizeof(ArrayHeader) + sizeof(StorageType) * num_elements; 50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static Ref ToRef(StorageType* storage, size_t offset) { 52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return storage[offset]; 53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static ConstRef ToConstRef(const StorageType* storage, size_t offset) { 55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return storage[offset]; 56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)template <typename P> 60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)struct ArrayDataTraits<P*> { 61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) typedef StructPointer<P> StorageType; 62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) typedef P*& Ref; 63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) typedef P* const& ConstRef; 64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 6503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) static const uint32_t kMaxNumElements = 6603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) (kMaxUint32 - sizeof(ArrayHeader)) / sizeof(StorageType); 6703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 6803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) static uint32_t GetStorageSize(uint32_t num_elements) { 6903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) MOJO_DCHECK(num_elements <= kMaxNumElements); 7003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return sizeof(ArrayHeader) + sizeof(StorageType) * num_elements; 716d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 726d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) static Ref ToRef(StorageType* storage, size_t offset) { 736d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return storage[offset].ptr; 746d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 756d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) static ConstRef ToConstRef(const StorageType* storage, size_t offset) { 766d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return storage[offset].ptr; 776d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 786d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}; 796d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)template <typename T> 816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)struct ArrayDataTraits<Array_Data<T>*> { 826d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) typedef ArrayPointer<T> StorageType; 836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) typedef Array_Data<T>*& Ref; 846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) typedef Array_Data<T>* const& ConstRef; 856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 8603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) static const uint32_t kMaxNumElements = 8703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) (kMaxUint32 - sizeof(ArrayHeader)) / sizeof(StorageType); 8803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 8903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) static uint32_t GetStorageSize(uint32_t num_elements) { 9003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) MOJO_DCHECK(num_elements <= kMaxNumElements); 9103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return sizeof(ArrayHeader) + sizeof(StorageType) * num_elements; 92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static Ref ToRef(StorageType* storage, size_t offset) { 94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return storage[offset].ptr; 95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static ConstRef ToConstRef(const StorageType* storage, size_t offset) { 97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return storage[offset].ptr; 98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Specialization of Arrays for bools, optimized for space. It has the 102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// following differences from a generalized Array: 103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// * Each element takes up a single bit of memory. 104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// * Accessing a non-const single element uses a helper class |BitRef|, which 105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// emulates a reference to a bool. 106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)template <> 107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)struct ArrayDataTraits<bool> { 108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Helper class to emulate a reference to a bool, used for direct element 109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // access. 110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) class BitRef { 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public: 112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ~BitRef(); 113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) BitRef& operator=(bool value); 114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) BitRef& operator=(const BitRef& value); 115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) operator bool() const; 116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private: 117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) friend struct ArrayDataTraits<bool>; 118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) BitRef(uint8_t* storage, uint8_t mask); 119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) BitRef(); 120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) uint8_t* storage_; 121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) uint8_t mask_; 122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) }; 123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 12403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Because each element consumes only 1/8 byte. 12503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) static const uint32_t kMaxNumElements = kMaxUint32; 12603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) typedef uint8_t StorageType; 128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) typedef BitRef Ref; 129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) typedef bool ConstRef; 130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 13103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) static uint32_t GetStorageSize(uint32_t num_elements) { 13203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return sizeof(ArrayHeader) + ((num_elements + 7) / 8); 133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static BitRef ToRef(StorageType* storage, size_t offset) { 135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return BitRef(&storage[offset / 8], 1 << (offset % 8)); 136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static bool ToConstRef(const StorageType* storage, size_t offset) { 138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return (storage[offset / 8] & (1 << (offset % 8))) != 0; 139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Array type information needed for valdiation. 1436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)template <uint32_t in_expected_num_elements, 14403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) bool in_element_is_nullable, 1456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) typename InElementValidateParams> 1466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class ArrayValidateParams { 1476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) public: 1486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Validation information for elements. It is either another specialization of 1496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // ArrayValidateParams (if elements are arrays) or NoValidateParams. 1506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) typedef InElementValidateParams ElementValidateParams; 1516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // If |expected_num_elements| is not 0, the array is expected to have exactly 1536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // that number of elements. 1546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) static const uint32_t expected_num_elements = in_expected_num_elements; 1556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Whether the elements are nullable. 15603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) static const bool element_is_nullable = in_element_is_nullable; 1576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}; 1586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// NoValidateParams is used to indicate the end of an ArrayValidateParams chain. 1606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class NoValidateParams { 1616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}; 1626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// What follows is code to support the serialization of Array_Data<T>. There 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// are two interesting cases: arrays of primitives and arrays of objects. 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Arrays of objects are represented as arrays of pointers to objects. 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)template <typename T, bool is_handle> struct ArraySerializationHelper; 1680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <typename T> 1700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochstruct ArraySerializationHelper<T, false> { 1710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch typedef typename ArrayDataTraits<T>::StorageType ElementType; 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static void EncodePointersAndHandles(const ArrayHeader* header, 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ElementType* elements, 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<Handle>* handles) { 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 17846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) static void DecodePointersAndHandles(const ArrayHeader* header, 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ElementType* elements, 18046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) std::vector<Handle>* handles) { 18146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 18246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 18303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) template <bool element_is_nullable, typename ElementValidateParams> 18446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) static bool ValidateElements(const ArrayHeader* header, 18546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const ElementType* elements, 18646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) BoundsChecker* bounds_checker) { 18703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) MOJO_COMPILE_ASSERT(!element_is_nullable, 1886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) Primitive_type_should_be_non_nullable); 1896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) MOJO_COMPILE_ASSERT( 1906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) (IsSame<ElementValidateParams, NoValidateParams>::value), 1916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) Primitive_type_should_not_have_array_validate_params); 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <> 1970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochstruct ArraySerializationHelper<Handle, true> { 1980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch typedef ArrayDataTraits<Handle>::StorageType ElementType; 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static void EncodePointersAndHandles(const ArrayHeader* header, 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ElementType* elements, 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<Handle>* handles); 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 20446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) static void DecodePointersAndHandles(const ArrayHeader* header, 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ElementType* elements, 20646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) std::vector<Handle>* handles); 20746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 20803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) template <bool element_is_nullable, typename ElementValidateParams> 20946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) static bool ValidateElements(const ArrayHeader* header, 21046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const ElementType* elements, 2116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) BoundsChecker* bounds_checker) { 2126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) MOJO_COMPILE_ASSERT( 2136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) (IsSame<ElementValidateParams, NoValidateParams>::value), 2146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) Handle_type_should_not_have_array_validate_params); 2156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) for (uint32_t i = 0; i < header->num_elements; ++i) { 21703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!element_is_nullable && 2186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) elements[i].value() == kEncodedInvalidHandleValue) { 2191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ReportValidationError( 2201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE, 2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MakeMessageWithArrayIndex( 2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "invalid handle in array expecting valid handles", 2231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci header->num_elements, i).c_str()); 2246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return false; 2256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 2266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!bounds_checker->ClaimHandle(elements[i])) { 2276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ReportValidationError(VALIDATION_ERROR_ILLEGAL_HANDLE); 2286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return false; 2296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 2306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 2316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return true; 2326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochtemplate <typename H> 2360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochstruct ArraySerializationHelper<H, true> { 2370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch typedef typename ArrayDataTraits<H>::StorageType ElementType; 2380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch static void EncodePointersAndHandles(const ArrayHeader* header, 2400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ElementType* elements, 2410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<Handle>* handles) { 2420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ArraySerializationHelper<Handle, true>::EncodePointersAndHandles( 2430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch header, elements, handles); 2440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 2450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 24646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) static void DecodePointersAndHandles(const ArrayHeader* header, 2470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ElementType* elements, 24846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) std::vector<Handle>* handles) { 24946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ArraySerializationHelper<Handle, true>::DecodePointersAndHandles( 25046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) header, elements, handles); 25146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 25246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 25303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) template <bool element_is_nullable, typename ElementValidateParams> 25446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) static bool ValidateElements(const ArrayHeader* header, 25546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const ElementType* elements, 25646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) BoundsChecker* bounds_checker) { 2576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return ArraySerializationHelper<Handle, true>:: 25803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ValidateElements<element_is_nullable, ElementValidateParams>( 2596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) header, elements, bounds_checker); 2600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 2610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}; 2620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <typename P> 2640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochstruct ArraySerializationHelper<P*, false> { 2650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch typedef typename ArrayDataTraits<P*>::StorageType ElementType; 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static void EncodePointersAndHandles(const ArrayHeader* header, 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ElementType* elements, 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<Handle>* handles) { 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (uint32_t i = 0; i < header->num_elements; ++i) 2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Encode(&elements[i], handles); 2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 27446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) static void DecodePointersAndHandles(const ArrayHeader* header, 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ElementType* elements, 27646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) std::vector<Handle>* handles) { 27746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) for (uint32_t i = 0; i < header->num_elements; ++i) 27846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) Decode(&elements[i], handles); 27946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 28046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 28103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) template <bool element_is_nullable, typename ElementValidateParams> 28246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) static bool ValidateElements(const ArrayHeader* header, 28346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const ElementType* elements, 28446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) BoundsChecker* bounds_checker) { 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (uint32_t i = 0; i < header->num_elements; ++i) { 28603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!element_is_nullable && !elements[i].offset) { 2871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ReportValidationError( 2881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, 2891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MakeMessageWithArrayIndex( 2901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "null in array expecting valid pointers", 2911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci header->num_elements, i).c_str()); 2926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return false; 2936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 29446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!ValidateEncodedPointer(&elements[i].offset)) { 29546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ReportValidationError(VALIDATION_ERROR_ILLEGAL_POINTER); 29646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 29746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 2986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!ValidateCaller<P, ElementValidateParams>::Run( 2996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DecodePointerRaw(&elements[i].offset), bounds_checker)) { 3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 3016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) private: 3076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) template <typename T, typename Params> 3086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) struct ValidateCaller { 3096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) static bool Run(const void* data, BoundsChecker* bounds_checker) { 3106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) MOJO_COMPILE_ASSERT( 3116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) (IsSame<Params, NoValidateParams>::value), 3126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) Struct_type_should_not_have_array_validate_params); 3136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return T::Validate(data, bounds_checker); 3156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 3166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) }; 3176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) template <typename T, typename Params> 3196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) struct ValidateCaller<Array_Data<T>, Params> { 3206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) static bool Run(const void* data, BoundsChecker* bounds_checker) { 3216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return Array_Data<T>::template Validate<Params>(data, bounds_checker); 3226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 3236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) }; 3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 326a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)template <typename T> 327a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class Array_Data { 328a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public: 329a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) typedef ArrayDataTraits<T> Traits; 330a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) typedef typename Traits::StorageType StorageType; 331a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) typedef typename Traits::Ref Ref; 332a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) typedef typename Traits::ConstRef ConstRef; 333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) typedef ArraySerializationHelper<T, IsHandle<T>::value> Helper; 334a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 33503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Returns NULL if |num_elements| or the corresponding storage size cannot be 33603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // stored in uint32_t. 337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) static Array_Data<T>* New(size_t num_elements, Buffer* buf) { 33803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (num_elements > Traits::kMaxNumElements) 33903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return NULL; 34003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 34103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint32_t num_bytes = 34203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Traits::GetStorageSize(static_cast<uint32_t>(num_elements)); 34303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return new (buf->Allocate(num_bytes)) Array_Data<T>( 34403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) num_bytes, static_cast<uint32_t>(num_elements)); 345a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 346a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 3476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) template <typename Params> 3486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) static bool Validate(const void* data, BoundsChecker* bounds_checker) { 34946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!data) 35046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return true; 35146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!IsAligned(data)) { 35246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ReportValidationError(VALIDATION_ERROR_MISALIGNED_OBJECT); 35346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 35446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 35546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!bounds_checker->IsValidRange(data, sizeof(ArrayHeader))) { 35646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); 35746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 35846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 35946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const ArrayHeader* header = static_cast<const ArrayHeader*>(data); 36003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (header->num_elements > Traits::kMaxNumElements || 36103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) header->num_bytes < Traits::GetStorageSize(header->num_elements)) { 36246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ReportValidationError(VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER); 36346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 36446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 3656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (Params::expected_num_elements != 0 && 3666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) header->num_elements != Params::expected_num_elements) { 3671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ReportValidationError( 3681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER, 3691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MakeMessageWithExpectedArraySize( 3701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "fixed-size array has wrong number of elements", 3711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci header->num_elements, Params::expected_num_elements).c_str()); 372116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 373116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 37446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!bounds_checker->ClaimMemory(data, header->num_bytes)) { 37546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); 37646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 37746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 37846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 37946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const Array_Data<T>* object = static_cast<const Array_Data<T>*>(data); 3806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return Helper::template ValidateElements< 38103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Params::element_is_nullable, typename Params::ElementValidateParams>( 3826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) &object->header_, object->storage(), bounds_checker); 38346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 38446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 385a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) size_t size() const { return header_.num_elements; } 386a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 387a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Ref at(size_t offset) { 3885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOJO_DCHECK(offset < static_cast<size_t>(header_.num_elements)); 389a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return Traits::ToRef(storage(), offset); 390a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 391a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 392a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ConstRef at(size_t offset) const { 3935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOJO_DCHECK(offset < static_cast<size_t>(header_.num_elements)); 394a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return Traits::ToConstRef(storage(), offset); 395a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 396a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 397a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) StorageType* storage() { 398a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return reinterpret_cast<StorageType*>( 399a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) reinterpret_cast<char*>(this) + sizeof(*this)); 400a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 401a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 402a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const StorageType* storage() const { 403a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return reinterpret_cast<const StorageType*>( 404a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) reinterpret_cast<const char*>(this) + sizeof(*this)); 405a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 406a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void EncodePointersAndHandles(std::vector<Handle>* handles) { 4080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Helper::EncodePointersAndHandles(&header_, storage(), handles); 4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 410a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 41146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) void DecodePointersAndHandles(std::vector<Handle>* handles) { 41246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) Helper::DecodePointersAndHandles(&header_, storage(), handles); 4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 41603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Array_Data(uint32_t num_bytes, uint32_t num_elements) { 41703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) header_.num_bytes = num_bytes; 41803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) header_.num_elements = num_elements; 419a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 420a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ~Array_Data() {} 421a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 422a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) internal::ArrayHeader header_; 423a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 424a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Elements of type internal::ArrayDataTraits<T>::StorageType follow. 425a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 426a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)MOJO_COMPILE_ASSERT(sizeof(Array_Data<char>) == 8, bad_sizeof_Array_Data); 427a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 428a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// UTF-8 encoded 429a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)typedef Array_Data<char> String_Data; 430a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 431cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)template <typename T, bool kIsMoveOnlyType> struct ArrayTraits {}; 432a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 433cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)template <typename T> struct ArrayTraits<T, false> { 434cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) typedef T StorageType; 435cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) typedef typename std::vector<T>::reference RefType; 436cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) typedef typename std::vector<T>::const_reference ConstRefType; 437f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) typedef ConstRefType ForwardType; 438cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) static inline void Initialize(std::vector<T>* vec) { 4390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 440cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) static inline void Finalize(std::vector<T>* vec) { 441a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 442cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) static inline ConstRefType at(const std::vector<T>* vec, size_t offset) { 443cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return vec->at(offset); 444a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 445cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) static inline RefType at(std::vector<T>* vec, size_t offset) { 446cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return vec->at(offset); 447a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 448f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) static inline void Resize(std::vector<T>* vec, size_t size) { 449f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) vec->resize(size); 450f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 451f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) static inline void PushBack(std::vector<T>* vec, ForwardType value) { 452f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) vec->push_back(value); 453f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 454a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 455a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 456cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)template <typename T> struct ArrayTraits<T, true> { 457cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) struct StorageType { 458cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) char buf[sizeof(T) + (8 - (sizeof(T) % 8)) % 8]; // Make 8-byte aligned. 459cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) }; 460cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) typedef T& RefType; 461cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) typedef const T& ConstRefType; 462f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) typedef T ForwardType; 463cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) static inline void Initialize(std::vector<StorageType>* vec) { 464cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (size_t i = 0; i < vec->size(); ++i) 465cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) new (vec->at(i).buf) T(); 4660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 467cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) static inline void Finalize(std::vector<StorageType>* vec) { 468cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (size_t i = 0; i < vec->size(); ++i) 469cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reinterpret_cast<T*>(vec->at(i).buf)->~T(); 470a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 471cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) static inline ConstRefType at(const std::vector<StorageType>* vec, 472cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t offset) { 473cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return *reinterpret_cast<const T*>(vec->at(offset).buf); 4740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 475cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) static inline RefType at(std::vector<StorageType>* vec, size_t offset) { 476cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return *reinterpret_cast<T*>(vec->at(offset).buf); 477a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 478f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) static inline void Resize(std::vector<StorageType>* vec, size_t size) { 479f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t old_size = vec->size(); 480f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (size_t i = size; i < old_size; i++) 481f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) reinterpret_cast<T*>(vec->at(i).buf)->~T(); 482f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ResizeStorage(vec, size); 483f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (size_t i = old_size; i < vec->size(); i++) 484f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) new (vec->at(i).buf) T(); 485f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 486f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) static inline void PushBack(std::vector<StorageType>* vec, RefType value) { 487f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t old_size = vec->size(); 488f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ResizeStorage(vec, old_size + 1); 489f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) new (vec->at(old_size).buf) T(value.Pass()); 490f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 491f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) static inline void ResizeStorage(std::vector<StorageType>* vec, size_t size) { 492f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (size <= vec->capacity()) { 493f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) vec->resize(size); 494f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 495f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 496f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<StorageType> new_storage(size); 497f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (size_t i = 0; i < vec->size(); i++) 498f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) new (new_storage.at(i).buf) T(at(vec, i).Pass()); 499f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) vec->swap(new_storage); 500f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Finalize(&new_storage); 501f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 502a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 503a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 504cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)template <> struct WrapperTraits<String, false> { 505cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) typedef String_Data* DataType; 506a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 507a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 508a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace internal 509a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace mojo 510a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 511e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ 512