cbor: migrate base or absl optional to std::optional

libchrome base::Optional is replaced by absl::optional on chromium
upstream and removed in r885735.
Since Chrome OS uses c++17, it can also use std::optional (as opposed to
Chrome which uses c++14). See go/use-std-optional-in-cros for
discussion.

Note, libchrome uses absl::optional because upstream chromium uses C++14
and does not have std::optional. However, absl switched to always use
std::optional implementation in crrev.com/c/2967691 so they are
equivalent.

LSC proposal: go/chromeos-lsc-optional-migration

BUG=b:192529039
TEST=FEATURES=test emerge-hatch cbor

Change-Id: I4b152a0306753e95e2e5d325c02e5af34af310b1
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/cbor/+/3531333
Tested-by: Grace Cham <hscham@chromium.org>
Reviewed-by: Tom Hughes <tomhughes@chromium.org>
Commit-Queue: Grace Cham <hscham@chromium.org>
diff --git a/diagnostic_writer_unittest.cc b/diagnostic_writer_unittest.cc
index 4569cf7..acad41e 100644
--- a/diagnostic_writer_unittest.cc
+++ b/diagnostic_writer_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "cbor/diagnostic_writer.h"
 
+#include <optional>
+
 #include "cbor/reader.h"
 #include "cbor/values.h"
 
@@ -64,7 +66,7 @@
   static const uint8_t kInvalidUTF8[] = {0x62, 0xe2, 0x80};
   cbor::Reader::Config config;
   config.allow_invalid_utf8 = true;
-  base::Optional<cbor::Value> maybe_value =
+  std::optional<cbor::Value> maybe_value =
       cbor::Reader::Read(kInvalidUTF8, config);
 
   ASSERT_TRUE(maybe_value);
diff --git a/reader.cc b/reader.cc
index 5161fae..03c0995 100644
--- a/reader.cc
+++ b/reader.cc
@@ -7,6 +7,7 @@
 #include <math.h>
 
 #include <map>
+#include <optional>
 #include <utility>
 
 #include "base/check_op.h"
@@ -72,9 +73,9 @@
 Reader::~Reader() {}
 
 // static
-base::Optional<Value> Reader::Read(base::span<uint8_t const> data,
-                                   DecoderError* error_code_out,
-                                   int max_nesting_level) {
+std::optional<Value> Reader::Read(base::span<uint8_t const> data,
+                                  DecoderError* error_code_out,
+                                  int max_nesting_level) {
   Config config;
   config.error_code_out = error_code_out;
   config.max_nesting_level = max_nesting_level;
@@ -83,10 +84,10 @@
 }
 
 // static
-base::Optional<Value> Reader::Read(base::span<uint8_t const> data,
-                                   size_t* num_bytes_consumed,
-                                   DecoderError* error_code_out,
-                                   int max_nesting_level) {
+std::optional<Value> Reader::Read(base::span<uint8_t const> data,
+                                  size_t* num_bytes_consumed,
+                                  DecoderError* error_code_out,
+                                  int max_nesting_level) {
   DCHECK(num_bytes_consumed);
 
   Config config;
@@ -98,10 +99,10 @@
 }
 
 // static
-base::Optional<Value> Reader::Read(base::span<uint8_t const> data,
-                                   const Config& config) {
+std::optional<Value> Reader::Read(base::span<uint8_t const> data,
+                                  const Config& config) {
   Reader reader(data);
-  base::Optional<Value> value =
+  std::optional<Value> value =
       reader.DecodeCompleteDataItem(config, config.max_nesting_level);
 
   auto error = reader.GetErrorCode();
@@ -123,16 +124,16 @@
   return value;
 }
 
-base::Optional<Value> Reader::DecodeCompleteDataItem(const Config& config,
-                                                     int max_nesting_level) {
+std::optional<Value> Reader::DecodeCompleteDataItem(const Config& config,
+                                                    int max_nesting_level) {
   if (max_nesting_level < 0 || max_nesting_level > kCBORMaxDepth) {
     error_code_ = DecoderError::TOO_MUCH_NESTING;
-    return base::nullopt;
+    return std::nullopt;
   }
 
-  base::Optional<DataItemHeader> header = DecodeDataItemHeader();
+  std::optional<DataItemHeader> header = DecodeDataItemHeader();
   if (!header.has_value()) {
-    return base::nullopt;
+    return std::nullopt;
   }
 
   switch (header->type) {
@@ -157,29 +158,29 @@
   }
 
   error_code_ = DecoderError::UNSUPPORTED_MAJOR_TYPE;
-  return base::nullopt;
+  return std::nullopt;
 }
 
-base::Optional<Reader::DataItemHeader> Reader::DecodeDataItemHeader() {
-  const base::Optional<uint8_t> initial_byte = ReadByte();
+std::optional<Reader::DataItemHeader> Reader::DecodeDataItemHeader() {
+  const std::optional<uint8_t> initial_byte = ReadByte();
   if (!initial_byte) {
-    return base::nullopt;
+    return std::nullopt;
   }
 
   const auto major_type = GetMajorType(initial_byte.value());
   const uint8_t additional_info = GetAdditionalInfo(initial_byte.value());
 
-  base::Optional<uint64_t> value = ReadVariadicLengthInteger(additional_info);
-  return value ? base::make_optional(
+  std::optional<uint64_t> value = ReadVariadicLengthInteger(additional_info);
+  return value ? std::make_optional(
                      DataItemHeader{major_type, additional_info, value.value()})
-               : base::nullopt;
+               : std::nullopt;
 }
 
-base::Optional<uint64_t> Reader::ReadVariadicLengthInteger(
+std::optional<uint64_t> Reader::ReadVariadicLengthInteger(
     uint8_t additional_info) {
   uint8_t additional_bytes = 0;
   if (additional_info < 24) {
-    return base::make_optional(additional_info);
+    return std::make_optional(additional_info);
   } else if (additional_info == 24) {
     additional_bytes = 1;
   } else if (additional_info == 25) {
@@ -190,13 +191,13 @@
     additional_bytes = 8;
   } else {
     error_code_ = DecoderError::UNKNOWN_ADDITIONAL_INFO;
-    return base::nullopt;
+    return std::nullopt;
   }
 
-  const base::Optional<base::span<const uint8_t>> bytes =
+  const std::optional<base::span<const uint8_t>> bytes =
       ReadBytes(additional_bytes);
   if (!bytes) {
-    return base::nullopt;
+    return std::nullopt;
   }
 
   uint64_t int_data = 0;
@@ -206,36 +207,35 @@
   }
 
   return IsEncodingMinimal(additional_bytes, int_data)
-             ? base::make_optional(int_data)
-             : base::nullopt;
+             ? std::make_optional(int_data)
+             : std::nullopt;
 }
 
-base::Optional<Value> Reader::DecodeValueToNegative(uint64_t value) {
+std::optional<Value> Reader::DecodeValueToNegative(uint64_t value) {
   auto negative_value = -base::CheckedNumeric<int64_t>(value) - 1;
   if (!negative_value.IsValid()) {
     error_code_ = DecoderError::OUT_OF_RANGE_INTEGER_VALUE;
-    return base::nullopt;
+    return std::nullopt;
   }
   return Value(negative_value.ValueOrDie());
 }
 
-base::Optional<Value> Reader::DecodeValueToUnsigned(uint64_t value) {
+std::optional<Value> Reader::DecodeValueToUnsigned(uint64_t value) {
   auto unsigned_value = base::CheckedNumeric<int64_t>(value);
   if (!unsigned_value.IsValid()) {
     error_code_ = DecoderError::OUT_OF_RANGE_INTEGER_VALUE;
-    return base::nullopt;
+    return std::nullopt;
   }
   return Value(unsigned_value.ValueOrDie());
 }
 
-base::Optional<Value> Reader::DecodeToSimpleValue(
-    const DataItemHeader& header) {
+std::optional<Value> Reader::DecodeToSimpleValue(const DataItemHeader& header) {
   // ReadVariadicLengthInteger provides this bound.
   CHECK_LE(header.additional_info, 27);
   // Floating point numbers are not supported.
   if (header.additional_info > 24) {
     error_code_ = DecoderError::UNSUPPORTED_FLOATING_POINT_VALUE;
-    return base::nullopt;
+    return std::nullopt;
   }
 
   // Since |header.additional_info| <= 24, ReadVariadicLengthInteger also
@@ -254,16 +254,15 @@
   }
 
   error_code_ = DecoderError::UNSUPPORTED_SIMPLE_VALUE;
-  return base::nullopt;
+  return std::nullopt;
 }
 
-base::Optional<Value> Reader::ReadStringContent(
-    const Reader::DataItemHeader& header,
-    const Config& config) {
+std::optional<Value> Reader::ReadStringContent(
+    const Reader::DataItemHeader& header, const Config& config) {
   uint64_t num_bytes = header.value;
-  const base::Optional<base::span<const uint8_t>> bytes = ReadBytes(num_bytes);
+  const std::optional<base::span<const uint8_t>> bytes = ReadBytes(num_bytes);
   if (!bytes) {
-    return base::nullopt;
+    return std::nullopt;
   }
 
   std::string cbor_string(bytes->begin(), bytes->end());
@@ -276,22 +275,22 @@
   }
 
   error_code_ = DecoderError::INVALID_UTF8;
-  return base::nullopt;
+  return std::nullopt;
 }
 
-base::Optional<Value> Reader::ReadByteStringContent(
+std::optional<Value> Reader::ReadByteStringContent(
     const Reader::DataItemHeader& header) {
   uint64_t num_bytes = header.value;
-  const base::Optional<base::span<const uint8_t>> bytes = ReadBytes(num_bytes);
+  const std::optional<base::span<const uint8_t>> bytes = ReadBytes(num_bytes);
   if (!bytes) {
-    return base::nullopt;
+    return std::nullopt;
   }
 
   std::vector<uint8_t> cbor_byte_string(bytes->begin(), bytes->end());
   return Value(std::move(cbor_byte_string));
 }
 
-base::Optional<Value> Reader::ReadArrayContent(
+std::optional<Value> Reader::ReadArrayContent(
     const Reader::DataItemHeader& header,
     const Config& config,
     int max_nesting_level) {
@@ -299,17 +298,17 @@
 
   Value::ArrayValue cbor_array;
   for (uint64_t i = 0; i < length; ++i) {
-    base::Optional<Value> cbor_element =
+    std::optional<Value> cbor_element =
         DecodeCompleteDataItem(config, max_nesting_level - 1);
     if (!cbor_element.has_value()) {
-      return base::nullopt;
+      return std::nullopt;
     }
     cbor_array.push_back(std::move(cbor_element.value()));
   }
   return Value(std::move(cbor_array));
 }
 
-base::Optional<Value> Reader::ReadMapContent(
+std::optional<Value> Reader::ReadMapContent(
     const Reader::DataItemHeader& header,
     const Config& config,
     int max_nesting_level) {
@@ -317,12 +316,12 @@
 
   std::map<Value, Value, Value::Less> cbor_map;
   for (uint64_t i = 0; i < length; ++i) {
-    base::Optional<Value> key =
+    std::optional<Value> key =
         DecodeCompleteDataItem(config, max_nesting_level - 1);
-    base::Optional<Value> value =
+    std::optional<Value> value =
         DecodeCompleteDataItem(config, max_nesting_level - 1);
     if (!key.has_value() || !value.has_value()) {
-      return base::nullopt;
+      return std::nullopt;
     }
 
     switch (key.value().type()) {
@@ -333,17 +332,17 @@
         break;
       case Value::Type::INVALID_UTF8:
         error_code_ = DecoderError::INVALID_UTF8;
-        return base::nullopt;
+        return std::nullopt;
       default:
         error_code_ = DecoderError::INCORRECT_MAP_KEY_TYPE;
-        return base::nullopt;
+        return std::nullopt;
     }
     if (IsDuplicateKey(key.value(), cbor_map))
-      return base::nullopt;
+      return std::nullopt;
 
     if (!config.allow_and_canonicalize_out_of_order_keys &&
         !IsKeyInOrder(key.value(), cbor_map)) {
-      return base::nullopt;
+      return std::nullopt;
     }
 
     cbor_map.emplace(std::move(key.value()), std::move(value.value()));
@@ -358,16 +357,15 @@
   return Value(std::move(map));
 }
 
-base::Optional<uint8_t> Reader::ReadByte() {
-  const base::Optional<base::span<const uint8_t>> bytes = ReadBytes(1);
-  return bytes ? base::make_optional(bytes.value()[0]) : base::nullopt;
+std::optional<uint8_t> Reader::ReadByte() {
+  const std::optional<base::span<const uint8_t>> bytes = ReadBytes(1);
+  return bytes ? std::make_optional(bytes.value()[0]) : std::nullopt;
 }
 
-base::Optional<base::span<const uint8_t>> Reader::ReadBytes(
-    uint64_t num_bytes) {
+std::optional<base::span<const uint8_t>> Reader::ReadBytes(uint64_t num_bytes) {
   if (base::strict_cast<uint64_t>(rest_.size()) < num_bytes) {
     error_code_ = DecoderError::INCOMPLETE_CBOR_DATA;
-    return base::nullopt;
+    return std::nullopt;
   }
   const base::span<const uint8_t> ret = rest_.first(num_bytes);
   rest_ = rest_.subspan(num_bytes);
diff --git a/reader.h b/reader.h
index bd9d6d9..7487630 100644
--- a/reader.h
+++ b/reader.h
@@ -8,9 +8,9 @@
 #include <stddef.h>
 
 #include <map>
+#include <optional>
 
 #include "base/containers/span.h"
-#include "base/optional.h"
 #include "cbor/cbor_export.h"
 #include "cbor/values.h"
 
@@ -141,21 +141,21 @@
   //
   // Returns an empty Optional if not all the data was consumed, and sets
   // |error_code_out| to EXTRANEOUS_DATA in this case.
-  static base::Optional<Value> Read(base::span<const uint8_t> input_data,
-                                    DecoderError* error_code_out = nullptr,
-                                    int max_nesting_level = kCBORMaxDepth);
+  static std::optional<Value> Read(base::span<const uint8_t> input_data,
+                                   DecoderError* error_code_out = nullptr,
+                                   int max_nesting_level = kCBORMaxDepth);
 
   // A version of |Read|, above, that takes a |Config| structure to allow
   // additional controls.
-  static base::Optional<Value> Read(base::span<const uint8_t> input_data,
-                                    const Config& config);
+  static std::optional<Value> Read(base::span<const uint8_t> input_data,
+                                   const Config& config);
 
   // A version of |Read| that takes some fields of |Config| as parameters to
   // avoid having to construct a |Config| object explicitly.
-  static base::Optional<Value> Read(base::span<const uint8_t> input_data,
-                                    size_t* num_bytes_consumed,
-                                    DecoderError* error_code_out = nullptr,
-                                    int max_nesting_level = kCBORMaxDepth);
+  static std::optional<Value> Read(base::span<const uint8_t> input_data,
+                                   size_t* num_bytes_consumed,
+                                   DecoderError* error_code_out = nullptr,
+                                   int max_nesting_level = kCBORMaxDepth);
 
   // Translates errors to human-readable error messages.
   static const char* ErrorCodeToString(DecoderError error_code);
@@ -178,24 +178,24 @@
     uint64_t value;
   };
 
-  base::Optional<DataItemHeader> DecodeDataItemHeader();
-  base::Optional<Value> DecodeCompleteDataItem(const Config& config,
-                                               int max_nesting_level);
-  base::Optional<Value> DecodeValueToNegative(uint64_t value);
-  base::Optional<Value> DecodeValueToUnsigned(uint64_t value);
-  base::Optional<Value> DecodeToSimpleValue(const DataItemHeader& header);
-  base::Optional<uint64_t> ReadVariadicLengthInteger(uint8_t additional_info);
-  base::Optional<Value> ReadByteStringContent(const DataItemHeader& header);
-  base::Optional<Value> ReadStringContent(const DataItemHeader& header,
-                                          const Config& config);
-  base::Optional<Value> ReadArrayContent(const DataItemHeader& header,
-                                         const Config& config,
-                                         int max_nesting_level);
-  base::Optional<Value> ReadMapContent(const DataItemHeader& header,
-                                       const Config& config,
-                                       int max_nesting_level);
-  base::Optional<uint8_t> ReadByte();
-  base::Optional<base::span<const uint8_t>> ReadBytes(uint64_t num_bytes);
+  std::optional<DataItemHeader> DecodeDataItemHeader();
+  std::optional<Value> DecodeCompleteDataItem(const Config& config,
+                                              int max_nesting_level);
+  std::optional<Value> DecodeValueToNegative(uint64_t value);
+  std::optional<Value> DecodeValueToUnsigned(uint64_t value);
+  std::optional<Value> DecodeToSimpleValue(const DataItemHeader& header);
+  std::optional<uint64_t> ReadVariadicLengthInteger(uint8_t additional_info);
+  std::optional<Value> ReadByteStringContent(const DataItemHeader& header);
+  std::optional<Value> ReadStringContent(const DataItemHeader& header,
+                                         const Config& config);
+  std::optional<Value> ReadArrayContent(const DataItemHeader& header,
+                                        const Config& config,
+                                        int max_nesting_level);
+  std::optional<Value> ReadMapContent(const DataItemHeader& header,
+                                      const Config& config,
+                                      int max_nesting_level);
+  std::optional<uint8_t> ReadByte();
+  std::optional<base::span<const uint8_t>> ReadBytes(uint64_t num_bytes);
   bool IsKeyInOrder(const Value& new_key,
                     const std::map<Value, Value, Value::Less>& map);
   // Check if `new_key` is a duplicate of a key that already exists in the
diff --git a/reader_fuzzer.cc b/reader_fuzzer.cc
index 0df3d3f..cc8925a 100644
--- a/reader_fuzzer.cc
+++ b/reader_fuzzer.cc
@@ -3,7 +3,9 @@
 // found in the LICENSE file.
 
 #include <stdint.h>
+
 #include <algorithm>
+#include <optional>
 
 #include "cbor/reader.h"  // nogncheck
 #include "cbor/writer.h"  // nogncheck
@@ -13,9 +15,9 @@
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
   std::vector<uint8_t> input(data, data + size);
 
-  base::Optional<Value> cbor = Reader::Read(input);
+  std::optional<Value> cbor = Reader::Read(input);
   if (cbor.has_value()) {
-    base::Optional<std::vector<uint8_t>> serialized_cbor =
+    std::optional<std::vector<uint8_t>> serialized_cbor =
         Writer::Write(cbor.value());
     CHECK(serialized_cbor.has_value());
     if (serialized_cbor.has_value()) {
@@ -27,10 +29,10 @@
 
   Reader::Config config;
   config.allow_and_canonicalize_out_of_order_keys = true;
-  base::Optional<Value> cbor_1 = Reader::Read(input, config);
+  std::optional<Value> cbor_1 = Reader::Read(input, config);
 
   if (cbor_1.has_value()) {
-    base::Optional<std::vector<uint8_t>> serialized_cbor =
+    std::optional<std::vector<uint8_t>> serialized_cbor =
         Writer::Write(cbor_1.value());
     CHECK(serialized_cbor.has_value());
     if (serialized_cbor.has_value()) {
diff --git a/reader_unittest.cc b/reader_unittest.cc
index d36e172..2849aba 100644
--- a/reader_unittest.cc
+++ b/reader_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include <limits>
+#include <optional>
 #include <utility>
 
 #include "cbor/reader.h"
@@ -52,7 +53,7 @@
   for (const UintTestCase& test_case : kUintTestCases) {
     SCOPED_TRACE(testing::Message() << "testing uint: " << test_case.value);
 
-    base::Optional<Value> cbor = Reader::Read(test_case.cbor_data);
+    std::optional<Value> cbor = Reader::Read(test_case.cbor_data);
     ASSERT_TRUE(cbor.has_value());
     ASSERT_EQ(cbor.value().type(), Value::Type::UNSIGNED);
     EXPECT_EQ(cbor.value().GetInteger(), test_case.value);
@@ -117,7 +118,7 @@
     SCOPED_TRACE(testing::Message()
                  << "testing element at index : " << test_case_index++);
 
-    base::Optional<Value> cbor = Reader::Read(non_minimal_uint, &error_code);
+    std::optional<Value> cbor = Reader::Read(non_minimal_uint, &error_code);
     EXPECT_FALSE(cbor.has_value());
     EXPECT_EQ(error_code, Reader::DecoderError::NON_MINIMAL_CBOR_ENCODING);
   }
@@ -144,7 +145,7 @@
     SCOPED_TRACE(testing::Message()
                  << "testing negative int : " << test_case.negative_int);
 
-    base::Optional<Value> cbor = Reader::Read(test_case.cbor_data);
+    std::optional<Value> cbor = Reader::Read(test_case.cbor_data);
     ASSERT_TRUE(cbor.has_value());
     ASSERT_EQ(cbor.value().type(), Value::Type::NEGATIVE);
     EXPECT_EQ(cbor.value().GetInteger(), test_case.negative_int);
@@ -184,7 +185,7 @@
     SCOPED_TRACE(testing::Message()
                  << "testing string test case at : " << element_index++);
 
-    base::Optional<Value> cbor = Reader::Read(test_case.cbor_data);
+    std::optional<Value> cbor = Reader::Read(test_case.cbor_data);
     ASSERT_TRUE(cbor.has_value());
     ASSERT_EQ(cbor.value().type(), Value::Type::BYTE_STRING);
     EXPECT_EQ(cbor.value().GetBytestring(), test_case.value);
@@ -226,7 +227,7 @@
     SCOPED_TRACE(testing::Message()
                  << "testing string value : " << test_case.value);
 
-    base::Optional<Value> cbor = Reader::Read(test_case.cbor_data);
+    std::optional<Value> cbor = Reader::Read(test_case.cbor_data);
     ASSERT_TRUE(cbor.has_value());
     ASSERT_EQ(cbor.value().type(), Value::Type::STRING);
     EXPECT_EQ(cbor.value().GetString(), test_case.value);
@@ -271,7 +272,7 @@
     SCOPED_TRACE(testing::Message()
                  << "testing string with nul bytes :" << test_case.value);
 
-    base::Optional<Value> cbor = Reader::Read(test_case.cbor_data);
+    std::optional<Value> cbor = Reader::Read(test_case.cbor_data);
     ASSERT_TRUE(cbor.has_value());
     ASSERT_EQ(cbor.value().type(), Value::Type::STRING);
     EXPECT_EQ(cbor.value().GetString(), test_case.value);
@@ -301,7 +302,7 @@
   static const std::vector<uint8_t> string_with_invalid_continuation_byte = {
       0x63, 0x00, 0x00, 0xA6};
   Reader::DecoderError error_code;
-  base::Optional<Value> cbor =
+  std::optional<Value> cbor =
       Reader::Read(string_with_invalid_continuation_byte, &error_code);
   EXPECT_FALSE(cbor.has_value());
   EXPECT_EQ(error_code, Reader::DecoderError::INVALID_UTF8);
@@ -317,7 +318,7 @@
       // clang-format on
   };
 
-  base::Optional<Value> cbor = Reader::Read(kArrayTestCaseCbor);
+  std::optional<Value> cbor = Reader::Read(kArrayTestCaseCbor);
   ASSERT_TRUE(cbor.has_value());
   const Value cbor_array = std::move(cbor.value());
   ASSERT_EQ(cbor_array.type(), Value::Type::ARRAY);
@@ -366,7 +367,7 @@
       // clang-format on
   };
 
-  base::Optional<Value> cbor = Reader::Read(kMapTestCaseCbor);
+  std::optional<Value> cbor = Reader::Read(kMapTestCaseCbor);
   ASSERT_TRUE(cbor.has_value());
   const Value cbor_val = std::move(cbor.value());
   ASSERT_EQ(cbor_val.type(), Value::Type::MAP);
@@ -428,7 +429,7 @@
       // clang-format on
   };
 
-  base::Optional<Value> cbor = Reader::Read(kMapWithIntegerKeyCbor);
+  std::optional<Value> cbor = Reader::Read(kMapWithIntegerKeyCbor);
   ASSERT_TRUE(cbor.has_value());
   const Value cbor_val = std::move(cbor.value());
   ASSERT_EQ(cbor_val.type(), Value::Type::MAP);
@@ -487,7 +488,7 @@
       // clang-format on
   };
 
-  base::Optional<Value> cbor = Reader::Read(kMapWithIntegerKeyCbor);
+  std::optional<Value> cbor = Reader::Read(kMapWithIntegerKeyCbor);
   ASSERT_TRUE(cbor.has_value());
   const Value cbor_val = std::move(cbor.value());
   ASSERT_EQ(cbor_val.type(), Value::Type::MAP);
@@ -541,7 +542,7 @@
       // clang-format on
   };
 
-  base::Optional<Value> cbor = Reader::Read(kMapArrayTestCaseCbor);
+  std::optional<Value> cbor = Reader::Read(kMapArrayTestCaseCbor);
   ASSERT_TRUE(cbor.has_value());
   const Value cbor_val = std::move(cbor.value());
   ASSERT_EQ(cbor_val.type(), Value::Type::MAP);
@@ -594,7 +595,7 @@
   };
 
   Reader::DecoderError error_code;
-  base::Optional<Value> cbor = Reader::Read(kMapTestCase, &error_code);
+  std::optional<Value> cbor = Reader::Read(kMapTestCase, &error_code);
   ASSERT_TRUE(cbor.has_value());
   ASSERT_EQ(cbor->type(), Value::Type::MAP);
   ASSERT_EQ(cbor->GetMap().size(), 2u);
@@ -637,7 +638,7 @@
   };
 
   Reader::DecoderError error_code;
-  base::Optional<Value> cbor = Reader::Read(kMapTestCase, &error_code);
+  std::optional<Value> cbor = Reader::Read(kMapTestCase, &error_code);
   ASSERT_TRUE(cbor.has_value());
   ASSERT_EQ(cbor->type(), Value::Type::MAP);
   ASSERT_EQ(cbor->GetMap().size(), 2u);
@@ -710,7 +711,7 @@
   };
 
   Reader::DecoderError error_code;
-  base::Optional<Value> cbor = Reader::Read(kMapTestCase, &error_code);
+  std::optional<Value> cbor = Reader::Read(kMapTestCase, &error_code);
   ASSERT_TRUE(cbor.has_value());
   ASSERT_EQ(cbor->type(), Value::Type::MAP);
   ASSERT_EQ(cbor->GetMap().size(), 6u);
@@ -763,7 +764,7 @@
       // clang-format on
   };
 
-  base::Optional<Value> cbor = Reader::Read(kNestedMapTestCase);
+  std::optional<Value> cbor = Reader::Read(kNestedMapTestCase);
   ASSERT_TRUE(cbor.has_value());
   const Value cbor_val = std::move(cbor.value());
   ASSERT_EQ(cbor_val.type(), Value::Type::MAP);
@@ -800,11 +801,11 @@
   static const std::vector<uint8_t> kMinNegativeInt = {
       0x3b, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
 
-  base::Optional<Value> max_positive_int = Reader::Read(kMaxPositiveInt);
+  std::optional<Value> max_positive_int = Reader::Read(kMaxPositiveInt);
   ASSERT_TRUE(max_positive_int.has_value());
   EXPECT_EQ(max_positive_int.value().GetInteger(), INT64_MAX);
 
-  base::Optional<Value> min_negative_int = Reader::Read(kMinNegativeInt);
+  std::optional<Value> min_negative_int = Reader::Read(kMinNegativeInt);
   ASSERT_TRUE(min_negative_int.has_value());
   EXPECT_EQ(min_negative_int.value().GetInteger(), INT64_MIN);
 }
@@ -817,12 +818,12 @@
       0x3b, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 
   Reader::DecoderError error_code;
-  base::Optional<Value> positive_int_out_of_range_cbor =
+  std::optional<Value> positive_int_out_of_range_cbor =
       Reader::Read(kOutOfRangePositiveInt, &error_code);
   EXPECT_FALSE(positive_int_out_of_range_cbor.has_value());
   EXPECT_EQ(error_code, Reader::DecoderError::OUT_OF_RANGE_INTEGER_VALUE);
 
-  base::Optional<Value> negative_int_out_of_range_cbor =
+  std::optional<Value> negative_int_out_of_range_cbor =
       Reader::Read(kOutOfRangeNegativeInt, &error_code);
   EXPECT_FALSE(negative_int_out_of_range_cbor.has_value());
   EXPECT_EQ(error_code, Reader::DecoderError::OUT_OF_RANGE_INTEGER_VALUE);
@@ -844,7 +845,7 @@
     SCOPED_TRACE(testing::Message()
                  << "testing simple value at index : " << test_element_index++);
 
-    base::Optional<Value> cbor = Reader::Read(test_case.cbor_data);
+    std::optional<Value> cbor = Reader::Read(test_case.cbor_data);
     ASSERT_TRUE(cbor.has_value());
     ASSERT_EQ(cbor.value().type(), Value::Type::SIMPLE_VALUE);
     EXPECT_EQ(cbor.value().GetSimpleValue(), test_case.value);
@@ -880,7 +881,7 @@
                  << "testing unsupported floating point : "
                  << testing::PrintToString(unsupported_floating_point));
     Reader::DecoderError error_code;
-    base::Optional<Value> cbor =
+    std::optional<Value> cbor =
         Reader::Read(unsupported_floating_point, &error_code);
     EXPECT_FALSE(cbor.has_value());
     EXPECT_EQ(error_code,
@@ -925,7 +926,7 @@
                                     << test_element_index++);
 
     Reader::DecoderError error_code;
-    base::Optional<Value> cbor = Reader::Read(incomplete_data, &error_code);
+    std::optional<Value> cbor = Reader::Read(incomplete_data, &error_code);
     EXPECT_FALSE(cbor.has_value());
     EXPECT_EQ(error_code, Reader::DecoderError::INCOMPLETE_CBOR_DATA);
   }
@@ -947,7 +948,7 @@
   };
 
   Reader::DecoderError error_code;
-  base::Optional<Value> cbor = Reader::Read(kMapWithUintKey, &error_code);
+  std::optional<Value> cbor = Reader::Read(kMapWithUintKey, &error_code);
   EXPECT_FALSE(cbor.has_value());
   EXPECT_EQ(error_code, Reader::DecoderError::INCORRECT_MAP_KEY_TYPE);
 }
@@ -979,7 +980,7 @@
                  << "testing data at index : " << test_element_index++);
 
     Reader::DecoderError error_code;
-    base::Optional<Value> cbor = Reader::Read(incorrect_cbor, &error_code);
+    std::optional<Value> cbor = Reader::Read(incorrect_cbor, &error_code);
     EXPECT_FALSE(cbor.has_value());
     EXPECT_EQ(error_code, Reader::DecoderError::UNKNOWN_ADDITIONAL_INFO);
   }
@@ -1004,7 +1005,7 @@
     SCOPED_TRACE(testing::Message()
                  << "testing zero nested data : " << test_element_index++);
     Reader::DecoderError error_code;
-    base::Optional<Value> cbor = Reader::Read(zero_depth_data, &error_code, 0);
+    std::optional<Value> cbor = Reader::Read(zero_depth_data, &error_code, 0);
     EXPECT_TRUE(cbor.has_value());
     EXPECT_EQ(error_code, Reader::DecoderError::CBOR_NO_ERROR);
   }
@@ -1026,12 +1027,12 @@
   };
 
   Reader::DecoderError error_code;
-  base::Optional<Value> cbor_single_layer_max =
+  std::optional<Value> cbor_single_layer_max =
       Reader::Read(kNestedCBORData, &error_code, 1);
   EXPECT_FALSE(cbor_single_layer_max.has_value());
   EXPECT_EQ(error_code, Reader::DecoderError::TOO_MUCH_NESTING);
 
-  base::Optional<Value> cbor_double_layer_max =
+  std::optional<Value> cbor_double_layer_max =
       Reader::Read(kNestedCBORData, &error_code, 2);
   EXPECT_TRUE(cbor_double_layer_max.has_value());
   EXPECT_EQ(error_code, Reader::DecoderError::CBOR_NO_ERROR);
@@ -1089,7 +1090,7 @@
     // Expect `OUT_OF_ORDER_KEY`.
     {
       Reader::DecoderError error_code;
-      base::Optional<Value> cbor =
+      std::optional<Value> cbor =
           Reader::Read(unsorted_map, &error_code);
       EXPECT_FALSE(cbor.has_value());
       EXPECT_EQ(error_code, Reader::DecoderError::OUT_OF_ORDER_KEY);
@@ -1103,7 +1104,7 @@
       config.error_code_out = &error_code;
       config.allow_and_canonicalize_out_of_order_keys = true;
 
-      base::Optional<Value> cbor =
+      std::optional<Value> cbor =
           Reader::Read(unsorted_map, config);
       EXPECT_TRUE(cbor);
       EXPECT_EQ(error_code, Reader::DecoderError::CBOR_NO_ERROR);
@@ -1147,7 +1148,7 @@
     // Expect `OUT_OF_ORDER_KEY`.
     {
       Reader::DecoderError error_code;
-      base::Optional<Value> cbor =
+      std::optional<Value> cbor =
           Reader::Read(unsorted_map, &error_code);
       EXPECT_FALSE(cbor.has_value());
       EXPECT_EQ(error_code, Reader::DecoderError::OUT_OF_ORDER_KEY);
@@ -1161,7 +1162,7 @@
       config.error_code_out = &error_code;
       config.allow_and_canonicalize_out_of_order_keys = true;
 
-      base::Optional<Value> cbor =
+      std::optional<Value> cbor =
           Reader::Read(unsorted_map, config);
       EXPECT_FALSE(cbor);
       EXPECT_EQ(error_code, Reader::DecoderError::DUPLICATE_KEY);
@@ -1195,8 +1196,7 @@
 
   {
     Reader::DecoderError error_code;
-    base::Optional<Value> cbor =
-        Reader::Read(kMapWithDuplicateKey, &error_code);
+    std::optional<Value> cbor = Reader::Read(kMapWithDuplicateKey, &error_code);
     EXPECT_FALSE(cbor.has_value());
     EXPECT_EQ(error_code, Reader::DecoderError::DUPLICATE_KEY);
   }
@@ -1207,7 +1207,7 @@
     config.error_code_out = &error_code;
     config.allow_and_canonicalize_out_of_order_keys = true;
 
-    base::Optional<Value> cbor = Reader::Read(kMapWithDuplicateKey, config);
+    std::optional<Value> cbor = Reader::Read(kMapWithDuplicateKey, config);
     EXPECT_FALSE(cbor.has_value());
     EXPECT_EQ(error_code, Reader::DecoderError::DUPLICATE_KEY);
   }
@@ -1231,7 +1231,7 @@
     SCOPED_TRACE(testing::Message() << "testing cbor data utf8 encoding : "
                                     << test_element_index++);
 
-    base::Optional<Value> correctly_encoded_cbor =
+    std::optional<Value> correctly_encoded_cbor =
         Reader::Read(cbor_byte, &error_code);
     EXPECT_TRUE(correctly_encoded_cbor.has_value());
     EXPECT_EQ(error_code, Reader::DecoderError::CBOR_NO_ERROR);
@@ -1239,7 +1239,7 @@
 
   // Incorrect UTF8 encoding referenced by section 3.5.3 of the stress test.
   std::vector<uint8_t> impossible_utf_byte{0x64, 0xfe, 0xfe, 0xff, 0xff};
-  base::Optional<Value> incorrectly_encoded_cbor =
+  std::optional<Value> incorrectly_encoded_cbor =
       Reader::Read(impossible_utf_byte, &error_code);
   EXPECT_FALSE(incorrectly_encoded_cbor.has_value());
   EXPECT_EQ(error_code, Reader::DecoderError::INVALID_UTF8);
@@ -1265,8 +1265,7 @@
                  << "testing cbor extraneous data : " << test_element_index++);
 
     Reader::DecoderError error_code;
-    base::Optional<Value> cbor =
-        Reader::Read(extraneous_cbor_data, &error_code);
+    std::optional<Value> cbor = Reader::Read(extraneous_cbor_data, &error_code);
     EXPECT_FALSE(cbor.has_value());
     EXPECT_EQ(error_code, Reader::DecoderError::EXTRANEOUS_DATA);
   }
@@ -1300,7 +1299,7 @@
                  << ::testing::PrintToString(unsupported_simple_val));
 
     Reader::DecoderError error_code;
-    base::Optional<Value> cbor =
+    std::optional<Value> cbor =
         Reader::Read(unsupported_simple_val, &error_code);
     EXPECT_FALSE(cbor.has_value());
     EXPECT_EQ(error_code, Reader::DecoderError::UNSUPPORTED_SIMPLE_VALUE);
@@ -1316,7 +1315,7 @@
   };
   for (const auto& test_case : kTestCases) {
     Reader::DecoderError error_code;
-    base::Optional<Value> cbor = Reader::Read(test_case, &error_code);
+    std::optional<Value> cbor = Reader::Read(test_case, &error_code);
     EXPECT_FALSE(cbor.has_value());
     EXPECT_EQ(error_code, Reader::DecoderError::INCOMPLETE_CBOR_DATA);
   }
@@ -1340,7 +1339,7 @@
   Reader::Config config;
   config.error_code_out = &error;
 
-  base::Optional<Value> cbor = Reader::Read(kInvalidUTF8, config);
+  std::optional<Value> cbor = Reader::Read(kInvalidUTF8, config);
   EXPECT_FALSE(cbor);
   EXPECT_EQ(Reader::DecoderError::INVALID_UTF8, error);
 
diff --git a/writer.cc b/writer.cc
index 1ae21c6..ff6a6f5 100644
--- a/writer.cc
+++ b/writer.cc
@@ -4,6 +4,7 @@
 
 #include "cbor/writer.h"
 
+#include <optional>
 #include <string>
 
 #include "base/check_op.h"
@@ -17,20 +18,20 @@
 Writer::~Writer() {}
 
 // static
-base::Optional<std::vector<uint8_t>> Writer::Write(const Value& node,
-                                                   const Config& config) {
+std::optional<std::vector<uint8_t>> Writer::Write(const Value& node,
+                                                  const Config& config) {
   std::vector<uint8_t> cbor;
   Writer writer(&cbor);
   if (!writer.EncodeCBOR(node, config.max_nesting_level,
                          config.allow_invalid_utf8_for_testing)) {
-    return base::nullopt;
+    return std::nullopt;
   }
   return cbor;
 }
 
 // static
-base::Optional<std::vector<uint8_t>> Writer::Write(const Value& node,
-                                                   size_t max_nesting_level) {
+std::optional<std::vector<uint8_t>> Writer::Write(const Value& node,
+                                                  size_t max_nesting_level) {
   Config config;
   config.max_nesting_level = base::checked_cast<int>(max_nesting_level);
   return Write(node, config);
diff --git a/writer.h b/writer.h
index 7a8a02f..cd16f86 100644
--- a/writer.h
+++ b/writer.h
@@ -8,9 +8,9 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <optional>
 #include <vector>
 
-#include "base/optional.h"
 #include "cbor/cbor_export.h"
 #include "cbor/values.h"
 
@@ -80,13 +80,12 @@
   // Returns the CBOR byte string representation of |node|, unless its nesting
   // depth is greater than |max_nesting_level|, in which case an empty optional
   // value is returned.
-  static base::Optional<std::vector<uint8_t>> Write(
-      const Value& node,
-      size_t max_nesting_level = kDefaultMaxNestingDepth);
+  static std::optional<std::vector<uint8_t>> Write(
+      const Value& node, size_t max_nesting_level = kDefaultMaxNestingDepth);
 
   // A version of |Write| above that takes a Config.
-  static base::Optional<std::vector<uint8_t>> Write(const Value& node,
-                                                    const Config& config);
+  static std::optional<std::vector<uint8_t>> Write(const Value& node,
+                                                   const Config& config);
 
  private:
   explicit Writer(std::vector<uint8_t>* cbor);