Skip to content

Commit

Permalink
headless: Add a Maybe-type
Browse files Browse the repository at this point in the history
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}
  • Loading branch information
skyostil authored and Commit bot committed Apr 7, 2016
1 parent 0197ff7 commit d79e151
Show file tree
Hide file tree
Showing 3 changed files with 189 additions and 0 deletions.
14 changes: 14 additions & 0 deletions headless/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [
Expand All @@ -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",
]
}

Expand Down
92 changes: 92 additions & 0 deletions headless/public/util/maybe.h
Original file line number Diff line number Diff line change
@@ -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 <algorithm>

#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 <typename T>
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 <class U>
friend Maybe<U> Nothing();
template <class U>
friend Maybe<U> Just(const U& u);
template <class U>
friend Maybe<typename std::remove_reference<U>::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 <class T>
Maybe<T> Nothing() {
return Maybe<T>();
}

template <class T>
Maybe<T> Just(const T& t) {
return Maybe<T>(t);
}

template <class T>
Maybe<typename std::remove_reference<T>::type> Just(T&& t) {
return Maybe<typename std::remove_reference<T>::type>(std::move(t));
}

} // namespace headless

#endif // HEADLESS_PUBLIC_UTIL_MAYBE_H_
83 changes: 83 additions & 0 deletions headless/public/util/maybe_unittest.cc
Original file line number Diff line number Diff line change
@@ -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<int> maybe;
EXPECT_TRUE(maybe.IsNothing());
EXPECT_FALSE(maybe.IsJust());
}

TEST(MaybeTest, Just) {
Maybe<int> maybe = Just(1);
EXPECT_FALSE(maybe.IsNothing());
EXPECT_TRUE(maybe.IsJust());
EXPECT_EQ(1, maybe.FromJust());

const Maybe<int> const_maybe = Just(2);
EXPECT_EQ(2, const_maybe.FromJust());
}

TEST(MaybeTest, Equality) {
Maybe<int> a;
Maybe<int> 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<int> a = Just(1);
Maybe<int> b = Nothing<int>();
EXPECT_NE(a, b);

b = a;
EXPECT_EQ(a, b);
}

TEST(MaybeTest, MoveOnlyType) {
MoveOnlyType value;
Maybe<MoveOnlyType> a = Just(std::move(value));
EXPECT_TRUE(a.IsJust());

Maybe<MoveOnlyType> b = Just(MoveOnlyType());
EXPECT_TRUE(b.IsJust());

Maybe<MoveOnlyType> c = Nothing<MoveOnlyType>();
c = std::move(a);
EXPECT_TRUE(c.IsJust());

MoveOnlyType d = std::move(b.FromJust());
}

} // namespace headless

0 comments on commit d79e151

Please sign in to comment.