1e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#ifndef ANDROID_PDX_UTILITY_H_
2e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#define ANDROID_PDX_UTILITY_H_
3e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
4e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <cstdint>
54535179ba093861ecdb408fb34adcc947957f86fCorey Tabaka#include <cstdlib>
6e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <iterator>
7e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
8e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/rpc/sequence.h>
9e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
10e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// Utilities for testing object serialization.
11e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
12e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace android {
13e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace pdx {
14e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
15e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass ByteBuffer {
16e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public:
17e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  using iterator = uint8_t*;
18e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  using const_iterator = const uint8_t*;
19e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  using size_type = size_t;
20e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
21e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ByteBuffer() = default;
22e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ByteBuffer(const ByteBuffer& other) {
23e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    resize(other.size());
24e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (other.size())
25e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      memcpy(data_, other.data(), other.size());
26e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
274535179ba093861ecdb408fb34adcc947957f86fCorey Tabaka  ~ByteBuffer() { std::free(data_); }
28e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
29e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ByteBuffer& operator=(const ByteBuffer& other) {
30e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    resize(other.size());
31e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (other.size())
32e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      memcpy(data_, other.data(), other.size());
33e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return *this;
34e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
35e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
36e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ByteBuffer& operator=(ByteBuffer&& other) {
37e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    std::swap(data_, other.data_);
38e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    std::swap(size_, other.size_);
39e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    std::swap(capacity_, other.capacity_);
40e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    other.clear();
41e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return *this;
42e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
43e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
44e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  inline const uint8_t* data() const { return data_; }
45e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  inline uint8_t* data() { return data_; }
46e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  inline size_t size() const { return size_; }
47e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  inline size_t capacity() const { return capacity_; }
48e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
49e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  iterator begin() { return data_; }
50e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const_iterator begin() const { return data_; }
51e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  iterator end() { return data_ + size_; }
52e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const_iterator end() const { return data_ + size_; }
53e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
54e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  inline bool operator==(const ByteBuffer& other) const {
55e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return size_ == other.size_ &&
56e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko           (size_ == 0 || memcmp(data_, other.data_, size_) == 0);
57e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
58e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
59e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  inline bool operator!=(const ByteBuffer& other) const {
60e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return !operator==(other);
61e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
62e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
63e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  inline void reserve(size_t size) {
64e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (size <= capacity_)
65e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return;
66e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // Find next power of 2 (assuming the size is 32 bits for now).
67e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size--;
68e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size |= size >> 1;
69e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size |= size >> 2;
70e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size |= size >> 4;
71e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size |= size >> 8;
72e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size |= size >> 16;
73e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size++;
744535179ba093861ecdb408fb34adcc947957f86fCorey Tabaka    void* new_data = data_ ? std::realloc(data_, size) : std::malloc(size);
75e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // TODO(avakulenko): Check for allocation failures.
76e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    data_ = static_cast<uint8_t*>(new_data);
77e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    capacity_ = size;
78e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
79e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
80e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  inline void resize(size_t size) {
81e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    reserve(size);
82e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size_ = size;
83e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
84e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
85e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  inline uint8_t* grow_by(size_t size_delta) {
86e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size_t old_size = size_;
87e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    resize(old_size + size_delta);
88e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return data_ + old_size;
89e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
90e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
91e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  inline void clear() { size_ = 0; }
92e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
93e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko private:
94e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  uint8_t* data_{nullptr};
95e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_t size_{0};
96e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_t capacity_{0};
97e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
98e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
99e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// Utility functions to increment/decrement void pointers to data buffers.
100e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkotemplate <typename OFFSET_T>
101e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoinline const void* AdvancePointer(const void* ptr, OFFSET_T offset) {
102e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return static_cast<const uint8_t*>(ptr) + offset;
103e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
104e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
105e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkotemplate <typename OFFSET_T>
106e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoinline void* AdvancePointer(void* ptr, OFFSET_T offset) {
107e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return static_cast<uint8_t*>(ptr) + offset;
108e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
109e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
110e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoinline ptrdiff_t PointerDistance(const void* end, const void* begin) {
111e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return static_cast<const uint8_t*>(end) - static_cast<const uint8_t*>(begin);
112e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
113e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
114e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// Utility to build sequences of types.
115e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkotemplate <typename, typename>
116e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostruct AppendTypeSequence;
117e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
118e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkotemplate <typename T, typename... S, template <typename...> class TT>
119e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostruct AppendTypeSequence<T, TT<S...>> {
120e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  using type = TT<S..., T>;
121e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
122e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
123e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// Utility to generate repeated types.
124e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkotemplate <typename T, std::size_t N, template <typename...> class TT>
125e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostruct RepeatedType {
126e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  using type = typename AppendTypeSequence<
127e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      T, typename RepeatedType<T, N - 1, TT>::type>::type;
128e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
129e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
130e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkotemplate <typename T, template <typename...> class TT>
131e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostruct RepeatedType<T, 0, TT> {
132e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  using type = TT<>;
133e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
134e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
135e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkotemplate <typename V, typename S>
136e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoinline V ReturnValueHelper(V value, S /*ignore*/) {
137e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return value;
138e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
139e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
140e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkotemplate <typename R, typename V, size_t... S>
141e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoinline R GetNTupleHelper(V value, rpc::IndexSequence<S...>) {
142e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return std::make_tuple(ReturnValueHelper(value, S)...);
143e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
144e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
145e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// Returns an N-tuple of type std::tuple<T,...T> containing |value| in each
146e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// element.
147e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkotemplate <size_t N, typename T,
148e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          typename R = typename RepeatedType<T, N, std::tuple>::type>
149e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoinline R GetNTuple(T value) {
150e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return GetNTupleHelper<R>(value, rpc::MakeIndexSequence<N>{});
151e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
152e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
153e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass NoOpOutputResourceMapper : public OutputResourceMapper {
154e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public:
155f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  Status<FileReference> PushFileHandle(const LocalHandle& handle) override {
156e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return handle.Get();
157e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
158e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
159f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  Status<FileReference> PushFileHandle(const BorrowedHandle& handle) override {
160e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return handle.Get();
161e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
162e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
163f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  Status<FileReference> PushFileHandle(const RemoteHandle& handle) override {
164e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return handle.Get();
165e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
166e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
167f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  Status<ChannelReference> PushChannelHandle(
168e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      const LocalChannelHandle& handle) override {
169e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return handle.value();
170e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
171e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
172f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  Status<ChannelReference> PushChannelHandle(
173e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      const BorrowedChannelHandle& handle) override {
174e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return handle.value();
175e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
176e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
177f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  Status<ChannelReference> PushChannelHandle(
178e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      const RemoteChannelHandle& handle) override {
179e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return handle.value();
180e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
181e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
182e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
183e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass NoOpInputResourceMapper : public InputResourceMapper {
184e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public:
185e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  bool GetFileHandle(FileReference ref, LocalHandle* handle) override {
186e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    *handle = LocalHandle{ref};
187e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return true;
188e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
189e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
190e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  bool GetChannelHandle(ChannelReference ref,
191e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                        LocalChannelHandle* handle) override {
192e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    *handle = LocalChannelHandle{nullptr, ref};
193e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return true;
194e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
195e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
196e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
197e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass NoOpResourceMapper : public NoOpOutputResourceMapper,
198e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                           public NoOpInputResourceMapper {};
199e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
200e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// Simple implementation of the payload interface, required by
201e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// Serialize/Deserialize. This is intended for test cases, where compatibility
202e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// with std::vector is helpful.
203e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass Payload : public MessageWriter,
204e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                public MessageReader,
205e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                public OutputResourceMapper {
206e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public:
207e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  using BaseType = ByteBuffer;
208e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  using iterator = typename BaseType::iterator;
209e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  using const_iterator = typename BaseType::const_iterator;
210e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  using size_type = typename BaseType::size_type;
211e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
212e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Payload() = default;
213e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  explicit Payload(size_type count, uint8_t value = 0) { Append(count, value); }
214e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Payload(const Payload& other) : buffer_(other.buffer_) {}
215e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Payload(const std::initializer_list<uint8_t>& initializer) {
216e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    buffer_.resize(initializer.size());
217e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    std::copy(initializer.begin(), initializer.end(), buffer_.begin());
218e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
219e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
220e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Payload& operator=(const Payload& other) {
221e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    buffer_ = other.buffer_;
222e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    read_pos_ = 0;
223e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return *this;
224e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
225e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Payload& operator=(const std::initializer_list<uint8_t>& initializer) {
226e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    buffer_.resize(initializer.size());
227e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    std::copy(initializer.begin(), initializer.end(), buffer_.begin());
228e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    read_pos_ = 0;
229e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return *this;
230e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
231e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
232e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Compares Payload with Payload.
233e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  bool operator==(const Payload& other) const {
234e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return buffer_ == other.buffer_;
235e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
236e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  bool operator!=(const Payload& other) const {
237e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return buffer_ != other.buffer_;
238e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
239e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
240e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Compares Payload with std::vector.
241e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  template <typename Type, typename AllocatorType>
242e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  typename std::enable_if<sizeof(Type) == sizeof(uint8_t), bool>::type
243e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  operator==(const std::vector<Type, AllocatorType>& other) const {
244e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return buffer_.size() == other.size() &&
245e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko           memcmp(buffer_.data(), other.data(), other.size()) == 0;
246e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
247e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  template <typename Type, typename AllocatorType>
248e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  typename std::enable_if<sizeof(Type) == sizeof(uint8_t), bool>::type
249e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  operator!=(const std::vector<Type, AllocatorType>& other) const {
250e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return !operator!=(other);
251e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
252e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
253e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  iterator begin() { return buffer_.begin(); }
254e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const_iterator begin() const { return buffer_.begin(); }
255e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  iterator end() { return buffer_.end(); }
256e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const_iterator end() const { return buffer_.end(); }
257e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
258e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void Append(size_type count, uint8_t value) {
259e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    auto* data = buffer_.grow_by(count);
260e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    std::fill(data, data + count, value);
261e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
262e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
263e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void Clear() {
264e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    buffer_.clear();
265e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    file_handles_.clear();
266e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    read_pos_ = 0;
267e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
268e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
269e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void Rewind() { read_pos_ = 0; }
270e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
271e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  uint8_t* Data() { return buffer_.data(); }
272e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const uint8_t* Data() const { return buffer_.data(); }
273e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_type Size() const { return buffer_.size(); }
274e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
275e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // MessageWriter
276e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void* GetNextWriteBufferSection(size_t size) override {
277e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return buffer_.grow_by(size);
278e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
279e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
280e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  OutputResourceMapper* GetOutputResourceMapper() override { return this; }
281e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
282e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // OutputResourceMapper
283f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  Status<FileReference> PushFileHandle(const LocalHandle& handle) override {
284e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (handle) {
285e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      const int ref = file_handles_.size();
286e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      file_handles_.push_back(handle.Get());
287e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return ref;
288e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    } else {
289e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return handle.Get();
290e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
291e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
292e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
293f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  Status<FileReference> PushFileHandle(const BorrowedHandle& handle) override {
294e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (handle) {
295e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      const int ref = file_handles_.size();
296e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      file_handles_.push_back(handle.Get());
297e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return ref;
298e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    } else {
299e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return handle.Get();
300e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
301e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
302e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
303f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  Status<FileReference> PushFileHandle(const RemoteHandle& handle) override {
304e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return handle.Get();
305e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
306e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
307f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  Status<ChannelReference> PushChannelHandle(
308e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      const LocalChannelHandle& handle) override {
309e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (handle) {
310e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      const int ref = file_handles_.size();
311e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      file_handles_.push_back(handle.value());
312e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return ref;
313e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    } else {
314e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return handle.value();
315e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
316e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
317e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
318f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  Status<ChannelReference> PushChannelHandle(
319e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      const BorrowedChannelHandle& handle) override {
320e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (handle) {
321e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      const int ref = file_handles_.size();
322e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      file_handles_.push_back(handle.value());
323e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return ref;
324e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    } else {
325e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return handle.value();
326e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
327e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
328e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
329f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  Status<ChannelReference> PushChannelHandle(
330e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      const RemoteChannelHandle& handle) override {
331e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return handle.value();
332e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
333e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
334e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // MessageReader
335e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  BufferSection GetNextReadBufferSection() override {
336e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return {buffer_.data() + read_pos_, &*buffer_.end()};
337e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
338e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
339e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void ConsumeReadBufferSectionData(const void* new_start) override {
340e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    read_pos_ = PointerDistance(new_start, buffer_.data());
341e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
342e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
343e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  InputResourceMapper* GetInputResourceMapper() override {
344e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return &input_resource_mapper_;
345e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
346e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
347e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const int* FdArray() const { return file_handles_.data(); }
348e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::size_t FdCount() const { return file_handles_.size(); }
349e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
350e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko private:
351e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  NoOpInputResourceMapper input_resource_mapper_;
352e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ByteBuffer buffer_;
353e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::vector<int> file_handles_;
354e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_t read_pos_{0};
355e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
356e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
357e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace pdx
358e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace android
359e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
360e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// Helper macros for branch prediction hinting.
361e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#ifdef __GNUC__
362e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#define PDX_LIKELY(x) __builtin_expect(!!(x), true)
363e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#define PDX_UNLIKELY(x) __builtin_expect(!!(x), false)
364e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#else
365e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#define PDX_LIKELY(x) (x)
366e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#define PDX_UNLIKELY(x) (x)
367e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#endif
368e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
369e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#endif  // ANDROID_PDX_UTILITY_H_
370