From d79e1515bc06265a1216c6910feb7a21232131e2 Mon Sep 17 00:00:00 2001 From: skyostil Date: Thu, 7 Apr 2016 10:50:58 -0700 Subject: [PATCH] headless: Add a Maybe-type Add a Maybe-type which will be used by the C++ DevTools client API for representing optional values. BUG=595353 Review URL: https://codereview.chromium.org/1866063002 Cr-Commit-Position: refs/heads/master@{#385797} --- headless/BUILD.gn | 14 ++++ headless/public/util/maybe.h | 92 ++++++++++++++++++++++++++ headless/public/util/maybe_unittest.cc | 83 +++++++++++++++++++++++ 3 files changed, 189 insertions(+) create mode 100644 headless/public/util/maybe.h create mode 100644 headless/public/util/maybe_unittest.cc diff --git a/headless/BUILD.gn b/headless/BUILD.gn index 0f59cabd72eb81..c035c2599f406c 100644 --- a/headless/BUILD.gn +++ b/headless/BUILD.gn @@ -84,6 +84,7 @@ static_library("headless_lib") { "public/headless_browser.h", "public/headless_export.h", "public/headless_web_contents.h", + "public/util/maybe.h", ] deps = [ @@ -110,6 +111,19 @@ group("headless_tests") { deps = [ ":headless_browsertests", + ":headless_unittests", + ] +} + +test("headless_unittests") { + sources = [ + "public/util/maybe_unittest.cc", + ] + + deps = [ + "//base/test:run_all_unittests", + "//base/test:test_support", + "//testing/gtest", ] } diff --git a/headless/public/util/maybe.h b/headless/public/util/maybe.h new file mode 100644 index 00000000000000..18540a3634f4d6 --- /dev/null +++ b/headless/public/util/maybe.h @@ -0,0 +1,92 @@ +// 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 HEADLESS_PUBLIC_UTIL_MAYBE_H_ +#define HEADLESS_PUBLIC_UTIL_MAYBE_H_ + +#include + +#include "base/logging.h" +#include "base/macros.h" + +namespace headless { + +// A simple Maybe which may or may not have a value. Based on v8::Maybe. +template +class Maybe { + public: + Maybe() : has_value_(false) {} + + bool IsNothing() const { return !has_value_; } + bool IsJust() const { return has_value_; } + + // Will crash if the Maybe<> is nothing. + T& FromJust() { + DCHECK(IsJust()); + return value_; + } + const T& FromJust() const { + DCHECK(IsJust()); + return value_; + } + + T FromMaybe(const T& default_value) const { + return has_value_ ? value_ : default_value; + } + + bool operator==(const Maybe& other) const { + return (IsJust() == other.IsJust()) && + (!IsJust() || FromJust() == other.FromJust()); + } + + bool operator!=(const Maybe& other) const { return !operator==(other); } + + Maybe& operator=(Maybe&& other) { + has_value_ = other.has_value_; + value_ = std::move(other.value_); + return *this; + } + + Maybe& operator=(const Maybe& other) { + has_value_ = other.has_value_; + value_ = other.value_; + return *this; + } + + Maybe(const Maybe& other) = default; + Maybe(Maybe&& other) = default; + + private: + template + friend Maybe Nothing(); + template + friend Maybe Just(const U& u); + template + friend Maybe::type> Just(U&& u); + + explicit Maybe(const T& t) : has_value_(true), value_(t) {} + explicit Maybe(T&& t) : has_value_(true), value_(std::move(t)) {} + + bool has_value_; + T value_; +}; + +template +Maybe Nothing() { + return Maybe(); +} + +template +Maybe Just(const T& t) { + return Maybe(t); +} + +template +Maybe::type> Just(T&& t) { + return Maybe::type>(std::move(t)); +} + +} // namespace headless + +#endif // HEADLESS_PUBLIC_UTIL_MAYBE_H_ diff --git a/headless/public/util/maybe_unittest.cc b/headless/public/util/maybe_unittest.cc new file mode 100644 index 00000000000000..fb926961df5c32 --- /dev/null +++ b/headless/public/util/maybe_unittest.cc @@ -0,0 +1,83 @@ +// 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. + +#include "headless/public/util/maybe.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace headless { +namespace { + +class MoveOnlyType { + public: + MoveOnlyType() {} + MoveOnlyType(MoveOnlyType&& other) {} + + void operator=(MoveOnlyType&& other) {} + + private: + DISALLOW_COPY_AND_ASSIGN(MoveOnlyType); +}; + +} // namespace + +TEST(MaybeTest, Nothing) { + Maybe maybe; + EXPECT_TRUE(maybe.IsNothing()); + EXPECT_FALSE(maybe.IsJust()); +} + +TEST(MaybeTest, Just) { + Maybe maybe = Just(1); + EXPECT_FALSE(maybe.IsNothing()); + EXPECT_TRUE(maybe.IsJust()); + EXPECT_EQ(1, maybe.FromJust()); + + const Maybe const_maybe = Just(2); + EXPECT_EQ(2, const_maybe.FromJust()); +} + +TEST(MaybeTest, Equality) { + Maybe a; + Maybe b; + EXPECT_EQ(a, b); + EXPECT_EQ(b, a); + + a = Just(1); + EXPECT_NE(a, b); + EXPECT_NE(b, a); + + b = Just(2); + EXPECT_NE(a, b); + EXPECT_NE(b, a); + + b = Just(1); + EXPECT_EQ(a, b); + EXPECT_EQ(b, a); +} + +TEST(MaybeTest, Assignment) { + Maybe a = Just(1); + Maybe b = Nothing(); + EXPECT_NE(a, b); + + b = a; + EXPECT_EQ(a, b); +} + +TEST(MaybeTest, MoveOnlyType) { + MoveOnlyType value; + Maybe a = Just(std::move(value)); + EXPECT_TRUE(a.IsJust()); + + Maybe b = Just(MoveOnlyType()); + EXPECT_TRUE(b.IsJust()); + + Maybe c = Nothing(); + c = std::move(a); + EXPECT_TRUE(c.IsJust()); + + MoveOnlyType d = std::move(b.FromJust()); +} + +} // namespace headless