// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MOJO_PUBLIC_CPP_BINDINGS_ARRAY_DATA_VIEW_H_
#define MOJO_PUBLIC_CPP_BINDINGS_ARRAY_DATA_VIEW_H_
#include <type_traits>
#include "mojo/public/cpp/bindings/lib/array_internal.h"
#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
#include "mojo/public/cpp/bindings/lib/serialization_context.h"
#include "mojo/public/cpp/bindings/lib/serialization_forward.h"
namespace mojo {
namespace internal {
template <typename T, typename EnableType = void>
class ArrayDataViewImpl;
template <typename T>
class ArrayDataViewImpl<
T,
typename std::enable_if<
BelongsTo<T, MojomTypeCategory::POD>::value>::type> {
public:
using Data_ = typename MojomTypeTraits<ArrayDataView<T>>::Data;
ArrayDataViewImpl(Data_* data, SerializationContext* context)
: data_(data), context_(context) {}
T operator[](size_t index) const { return data_->at(index); }
const T* data() const { return data_->storage(); }
protected:
Data_* data_;
SerializationContext* context_;
};
template <typename T>
class ArrayDataViewImpl<
T,
typename std::enable_if<
BelongsTo<T, MojomTypeCategory::BOOLEAN>::value>::type> {
public:
using Data_ = typename MojomTypeTraits<ArrayDataView<T>>::Data;
ArrayDataViewImpl(Data_* data, SerializationContext* context)
: data_(data), context_(context) {}
bool operator[](size_t index) const { return data_->at(index); }
protected:
Data_* data_;
SerializationContext* context_;
};
template <typename T>
class ArrayDataViewImpl<
T,
typename std::enable_if<
BelongsTo<T, MojomTypeCategory::ENUM>::value>::type> {
public:
static_assert(sizeof(T) == sizeof(int32_t), "Unexpected enum size");
using Data_ = typename MojomTypeTraits<ArrayDataView<T>>::Data;
ArrayDataViewImpl(Data_* data, SerializationContext* context)
: data_(data), context_(context) {}
T operator[](size_t index) const { return static_cast<T>(data_->at(index)); }
const T* data() const { return reinterpret_cast<const T*>(data_->storage()); }
template <typename U>
bool Read(size_t index, U* output) {
return Deserialize<T>(data_->at(index), output);
}
protected:
Data_* data_;
SerializationContext* context_;
};
template <typename T>
class ArrayDataViewImpl<
T,
typename std::enable_if<
BelongsTo<T,
MojomTypeCategory::ASSOCIATED_INTERFACE |
MojomTypeCategory::ASSOCIATED_INTERFACE_REQUEST |
MojomTypeCategory::INTERFACE |
MojomTypeCategory::INTERFACE_REQUEST>::value>::type> {
public:
using Data_ = typename MojomTypeTraits<ArrayDataView<T>>::Data;
ArrayDataViewImpl(Data_* data, SerializationContext* context)
: data_(data), context_(context) {}
template <typename U>
U Take(size_t index) {
U result;
bool ret = Deserialize<T>(&data_->at(index), &result, context_);
DCHECK(ret);
return result;
}
protected:
Data_* data_;
SerializationContext* context_;
};
template <typename T>
class ArrayDataViewImpl<
T,
typename std::enable_if<
BelongsTo<T, MojomTypeCategory::HANDLE>::value>::type> {
public:
using Data_ = typename MojomTypeTraits<ArrayDataView<T>>::Data;
ArrayDataViewImpl(Data_* data, SerializationContext* context)
: data_(data), context_(context) {}
T Take(size_t index) {
T result;
bool ret = Deserialize<T>(&data_->at(index), &result, context_);
DCHECK(ret);
return result;
}
protected:
Data_* data_;
SerializationContext* context_;
};
template <typename T>
class ArrayDataViewImpl<T,
typename std::enable_if<BelongsTo<
T,
MojomTypeCategory::ARRAY | MojomTypeCategory::MAP |
MojomTypeCategory::STRING |
MojomTypeCategory::STRUCT>::value>::type> {
public:
using Data_ = typename MojomTypeTraits<ArrayDataView<T>>::Data;
ArrayDataViewImpl(Data_* data, SerializationContext* context)
: data_(data), context_(context) {}
void GetDataView(size_t index, T* output) {
*output = T(data_->at(index).Get(), context_);
}
template <typename U>
bool Read(size_t index, U* output) {
return Deserialize<T>(data_->at(index).Get(), output, context_);
}
protected:
Data_* data_;
SerializationContext* context_;
};
template <typename T>
class ArrayDataViewImpl<
T,
typename std::enable_if<
BelongsTo<T, MojomTypeCategory::UNION>::value>::type> {
public:
using Data_ = typename MojomTypeTraits<ArrayDataView<T>>::Data;
ArrayDataViewImpl(Data_* data, SerializationContext* context)
: data_(data), context_(context) {}
void GetDataView(size_t index, T* output) {
*output = T(&data_->at(index), context_);
}
template <typename U>
bool Read(size_t index, U* output) {
return Deserialize<T>(&data_->at(index), output, context_);
}
protected:
Data_* data_;
SerializationContext* context_;
};
} // namespace internal
template <typename K, typename V>
class MapDataView;
template <typename T>
class ArrayDataView : public internal::ArrayDataViewImpl<T> {
public:
using Element = T;
using Data_ = typename internal::ArrayDataViewImpl<T>::Data_;
ArrayDataView() : internal::ArrayDataViewImpl<T>(nullptr, nullptr) {}
ArrayDataView(Data_* data, internal::SerializationContext* context)
: internal::ArrayDataViewImpl<T>(data, context) {}
bool is_null() const { return !this->data_; }
size_t size() const { return this->data_->size(); }
// Methods to access elements are different for different element types. They
// are inherited from internal::ArrayDataViewImpl:
// POD types except boolean and enums:
// T operator[](size_t index) const;
// const T* data() const;
// Boolean:
// bool operator[](size_t index) const;
// Enums:
// T operator[](size_t index) const;
// const T* data() const;
// template <typename U>
// bool Read(size_t index, U* output);
// Handles:
// T Take(size_t index);
// Interfaces:
// template <typename U>
// U Take(size_t index);
// Object types:
// void GetDataView(size_t index, T* output);
// template <typename U>
// bool Read(size_t index, U* output);
private:
template <typename K, typename V>
friend class MapDataView;
};
} // namespace mojo
#endif // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_DATA_VIEW_H_