blob: 73e9d1e972aa2d9a0f6ab41c9f3904e738e52a97 [file] [log] [blame]
// Copyright 2018 The Fuchsia 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 LIB_FIDL_CPP_VECTOR_H_
#define LIB_FIDL_CPP_VECTOR_H_
#include <lib/fidl/cpp/builder.h>
#include <lib/fidl/cpp/comparison.h>
#include <lib/fit/optional.h>
#include <zircon/assert.h>
#include <utility>
#include <vector>
#include "lib/fidl/cpp/traits.h"
#include "lib/fidl/cpp/transition.h"
namespace fidl {
#if defined(FIDL_USE_FIT_OPTIONAL)
template <typename T>
class VectorPtr : public fit::optional<std::vector<T>> {
public:
constexpr VectorPtr() = default;
constexpr VectorPtr(fit::nullopt_t) noexcept {}
FIDL_FIT_OPTIONAL_DEPRECATED("Use fit::nullopt instead of nullptr")
constexpr VectorPtr(std::nullptr_t) noexcept {}
VectorPtr(const VectorPtr&) = default;
VectorPtr& operator=(const VectorPtr&) = default;
VectorPtr(VectorPtr&&) noexcept = default;
VectorPtr& operator=(VectorPtr&&) noexcept = default;
// Move construct and move assignment from the value type
constexpr VectorPtr(std::vector<T>&& value) : fit::optional<std::vector<T>>(std::move(value)) {}
constexpr VectorPtr& operator=(std::vector<T>&& value) {
fit::optional<std::vector<T>>::operator=(std::move(value));
return *this;
}
// Copy construct and copy assignment from the value type
constexpr VectorPtr(const std::vector<T>& value) : fit::optional<std::vector<T>>(value) {}
constexpr VectorPtr& operator=(const std::vector<T>& value) {
fit::optional<std::vector<T>>::operator=(value);
return *this;
}
explicit VectorPtr(size_t size) : fit::optional<std::vector<T>>(size) {}
// Override unchecked accessors with versions that check.
constexpr std::vector<T>* operator->() {
if (!fit::optional<std::vector<T>>::has_value()) {
__builtin_trap();
}
return fit::optional<std::vector<T>>::operator->();
}
constexpr const std::vector<T>* operator->() const {
if (!fit::optional<std::vector<T>>::has_value()) {
__builtin_trap();
}
return fit::optional<std::vector<T>>::operator->();
}
FIDL_FIT_OPTIONAL_DEPRECATED("Assign an empty std::vector")
VectorPtr& emplace() {
*this = std::move(std::vector<T>());
return *this;
}
FIDL_FIT_OPTIONAL_DEPRECATED("Assign an std::vector")
VectorPtr& emplace(std::initializer_list<std::vector<T>>&& ilist) {
*this = (std::move(std::vector<T>(ilist)));
return *this;
}
FIDL_FIT_OPTIONAL_DEPRECATED("Assign an std::vector")
VectorPtr& emplace(std::vector<T>&& value) {
*this = std::move(value);
return *this;
}
};
#else
// A representation of a FIDL vector that owns the memory for the vector.
//
// A VectorPtr has three states: (1) null, (2) empty, (3) contains data. You
// can check for the null state using the |is_null| method.
template <typename T>
class VectorPtr {
public:
VectorPtr() : is_null_if_empty_(true) {}
~VectorPtr() = default;
VectorPtr(std::nullptr_t) : is_null_if_empty_(true) {}
explicit VectorPtr(size_t size) : vec_(std::vector<T>(size)), is_null_if_empty_(false) {}
VectorPtr(std::vector<T>&& vec) : vec_(std::move(vec)), is_null_if_empty_(false) {}
VectorPtr(VectorPtr&& other) = default;
VectorPtr& operator=(VectorPtr&& other) = default;
// Copy construct and assignment from a const std::vector<T>&
VectorPtr(const std::vector<T>& other) : vec_(other), is_null_if_empty_(false) {}
VectorPtr& operator=(const std::vector<T>& other) {
vec_ = other;
is_null_if_empty_ = false;
return *this;
}
// Creates a VectorPtr of the given size.
//
// Equivalent to using the |VectorPtr(size_t)| constructor.
FIDL_FIT_OPTIONAL_DEPRECATED("use constructor")
static VectorPtr New(size_t size) { return VectorPtr(size); }
// Accesses the underlying std::vector object.
FIDL_FIT_OPTIONAL_DEPRECATED("use value_or")
const std::vector<T>& get() const { return vec_; }
// Takes the std::vector from the VectorPtr.
//
// After this method returns, the VectorPtr is null.
FIDL_FIT_OPTIONAL_DEPRECATED("use std::move(vecptr).value();vecptr.reset();")
std::vector<T> take() {
is_null_if_empty_ = true;
return std::move(vec_);
}
// Stores the given std::vector in this VectorPtr.
//
// After this method returns, the VectorPtr is non-null.
FIDL_FIT_OPTIONAL_DEPRECATED("use assignment or emplace()")
void reset(std::vector<T> vec) {
vec_ = std::move(vec);
is_null_if_empty_ = false;
}
VectorPtr& emplace() {
vec_.clear();
is_null_if_empty_ = false;
return *this;
}
VectorPtr& emplace(std::vector<T>&& vec) {
vec_ = std::move(vec);
is_null_if_empty_ = false;
return *this;
}
VectorPtr& emplace(std::initializer_list<T>&& ilist) {
vec_ = std::vector<T>(ilist);
is_null_if_empty_ = false;
return *this;
}
VectorPtr& operator=(std::vector<T>&& vec) {
vec_ = std::move(vec);
is_null_if_empty_ = false;
return *this;
}
void reset() {
vec_.clear();
is_null_if_empty_ = true;
}
// Resizes the underlying std::vector in this VectorPtr to the given size.
//
// After this method returns, the VectorPtr is non-null.
FIDL_FIT_OPTIONAL_DEPRECATED("initialize and use operator->")
void resize(size_t size) {
vec_.resize(size);
is_null_if_empty_ = false;
}
// Pushes |value| onto the back of this VectorPtr.
//
// If this vector was null, it will become non-null with a size of 1.
FIDL_FIT_OPTIONAL_DEPRECATED("initialize and use operator->")
void push_back(const T& value) {
vec_.push_back(value);
is_null_if_empty_ = false;
}
// Pushes |value| onto the back of this VectorPtr.
//
// If this vector was null, it will become non-null with a size of 1.
FIDL_FIT_OPTIONAL_DEPRECATED("initialize and use operator->")
void push_back(T&& value) {
vec_.push_back(std::forward<T>(value));
is_null_if_empty_ = false;
}
void swap(VectorPtr& other) {
using std::swap;
swap(vec_, other.vec_);
swap(is_null_if_empty_, other.is_null_if_empty_);
}
// Returns a copy of this VectorPtr.
//
// Unlike fidl::Clone, this function can never fail. However, this function
// works only if T is copiable.
FIDL_FIT_OPTIONAL_DEPRECATED("use fidl::Clone()")
VectorPtr Clone() const {
if (is_null())
return VectorPtr();
return VectorPtr(vec_);
}
// Whether this VectorPtr is null.
//
// The null state is separate from the empty state.
FIDL_FIT_OPTIONAL_DEPRECATED("use !has_value()")
bool is_null() const { return is_null_if_empty_ && vec_.empty(); }
bool has_value() const { return !is_null_if_empty_ || !vec_.empty(); }
// Tests as true if non-null, false if null.
explicit operator bool() const { return has_value(); }
// Provides access to the underlying std::vector.
std::vector<T>* operator->() { return &vec_; }
const std::vector<T>* operator->() const { return &vec_; }
// Provides access to the underlying std::vector.
std::vector<T>& operator*() { return vec_; }
const std::vector<T>& operator*() const { return vec_; }
std::vector<T>& value() & { return vec_; }
const std::vector<T>& value() const& { return vec_; }
std::vector<T>& value_or(std::vector<T>& default_value) & {
return has_value() ? vec_ : default_value;
}
const std::vector<T>& value_or(const std::vector<T>& default_value) const& {
return has_value() ? vec_ : default_value;
}
// Provides implicit conversion for accessing the underlying std::vector.
// To mutate the vector, use operator* or operator-> or one of the mutation
// functions.
FIDL_FIT_OPTIONAL_DEPRECATED("use value_or()")
operator const std::vector<T> &() const { return vec_; }
private:
std::vector<T> vec_;
bool is_null_if_empty_;
};
#endif
template <class T>
struct Equality<VectorPtr<T>> {
bool operator()(const VectorPtr<T>& lhs, const VectorPtr<T>& rhs) const {
if (!lhs.has_value() || !rhs.has_value()) {
return !lhs.has_value() == !rhs.has_value();
}
return ::fidl::Equality<std::vector<T>>{}(lhs.value(), rhs.value());
}
};
} // namespace fidl
#endif // LIB_FIDL_CPP_VECTOR_H_