|  | // 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_ |