/** * Copyright (c) 2018-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the Apache 2.0 license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). * You may select, at your option, one of the above-listed licenses. */ #pragma once #include #include #include #include #include /** * Utility class that should be used in function that return * either error or value. Expected enforce developer to test for success and * check error if any. * * enum class TestError { SomeError = 1, AnotherError = 2 }; * Expected function() { * if (test) { * return "ok"; * } else { * return std::make_shared>(TestError::SomeError); * } * } * * Expected: * ExpectedUnique function() { * if (test) { * return std::make_unique(pid); * } else { * return std::make_shared>(TestError::AnotherError); * } * } * * auto result = function(); * if (result) { * ...use *result * } else { * auto error = result->getError(); * } */ namespace osquery { template class Expected final { public: Expected(ErrorCodeEnumType object) : object_(std::move(object)), hasError_(false) {} Expected(ErrorBase* error) = delete; Expected() : error_(nullptr), hasError_(false) {} Expected(std::shared_ptr error) : error_(std::move(error)), hasError_(true) {} Expected(std::unique_ptr error) : error_(std::move(error)), hasError_(true) {} template Expected(std::shared_ptr> error) : error_(std::static_pointer_cast(error)), hasError_(true){}; Expected(const Expected&) = delete; ~Expected() { assert(errorChecked_ && "Error was not checked"); } Expected& operator=(Expected&& other) { if (this != &other) { object_ = std::move(other.object_); error_ = std::move(other.error_); hasError_ = other.hasError_; } return *this; } Expected(Expected&& other) { object_ = std::move(other.object_); error_ = std::move(other.error_); hasError_ = other.hasError_; } std::shared_ptr getError() const { return error_; } explicit operator bool() const { errorChecked_ = true; return !hasError_; } ErrorCodeEnumType& get() { return object_; } const ErrorCodeEnumType& get() const { return object_; } ErrorCodeEnumType take() { return std::move(object_); } ErrorCodeEnumType* operator->() { return object_; } const ErrorCodeEnumType* operator->() const { return object_; } ErrorCodeEnumType& operator*() { return object_; } const ErrorCodeEnumType& operator*() const { return object_; } private: static const bool isPointer = std::is_pointer::value; static_assert(!isPointer, "Use shared/unique pointer"); ErrorCodeEnumType object_; std::shared_ptr error_; bool hasError_; mutable bool errorChecked_ = false; }; template using ExpectedShared = Expected>; template using ExpectedUnique = Expected>; } // namespace osquery