<commit_before>// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_VALUE_H_
#define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_VALUE_H_

#include "google/cloud/spanner/date.h"
#include "google/cloud/spanner/internal/tuple_utils.h"
#include "google/cloud/spanner/timestamp.h"
#include "google/cloud/spanner/version.h"
#include "google/cloud/internal/throw_delegate.h"
#include "google/cloud/optional.h"
#include "google/cloud/status_or.h"
#include <google/protobuf/struct.pb.h>
#include <google/protobuf/util/message_differencer.h>
#include <google/spanner/v1/type.pb.h>
#include <chrono>
#include <ostream>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility>

namespace google {
namespace cloud {
namespace spanner {
inline namespace SPANNER_CLIENT_NS {

class Value;  // Defined later in this file.
// Internal implementation details that callers should not use.
namespace internal {
Value FromProto(google::spanner::v1::Type t, google::protobuf::Value v);
std::pair<google::spanner::v1::Type, google::protobuf::Value> ToProto(Value v);
}  // namespace internal

/**
 * The Value class represents a type-safe, nullable Spanner value.
 *
 * It is conceptually similar to a `std::any` except the only allowed types are
 * those supported by Spanner, and a "null" value (similar to a `std::any`
 * without a value) still has an associated type that can be queried with
 * `Value::is<T>()`. The supported types are shown in the following table along
 * with how they map to the Spanner types
 * (https://cloud.google.com/spanner/docs/data-types):
 *
 * Spanner Type | C++ Type `T`
 * ------------ | ------------
 * BOOL         | `bool`
 * INT64        | `std::int64_t`
 * FLOAT64      | `double`
 * STRING       | `std::string`
 * TIMESTAMP    | `google::cloud::spanner::Timestamp`
 * DATE         | `google::cloud::spanner::Date`
 * ARRAY        | `std::vector<T>`  // [1]
 * STRUCT       | `std::tuple<Ts...>`
 *
 * [1] The type `T` may be any of the other supported types, except for
 *     ARRAY/`std::vector`.
 *
 * Value is a regular C++ value type with support for copy, move, equality,
 * etc. A default-constructed Value represents an empty value with no type.
 *
 * Callers may create instances by passing any of the supported values (shown
 * in the table above) to the constructor. "Null" values are created using the
 * `MakeNullValue<T>()` factory function or by passing an empty `optional<T>`
 * to the Value constructor..
 *
 * @par Example with a non-null value
 *
 * @code
 * std::string msg = "hello";
 * spanner::Value v(msg);
 * assert(v.is<std::string>());
 * assert(!v.is_null<std::string>());
 * StatusOr<std::string> copy = v.get<std::string>();
 * if (copy) {
 *   std::cout << *copy;  // prints "hello"
 * }
 * @endcode
 *
 * @par Example with a null
 *
 * @code
 * spanner::Value v = spanner::MakeNullValue<std::int64_t>();
 * assert(v.is<std::int64_t>());
 * assert(v.is_null<std::int64_t>());
 * StatusOr<std::int64_t> i = v.get<std::int64_t>();
 * assert(!i.ok());  // Can't get the value becuase v is null
 * StatusOr<optional<std::int64_t> j = v.get<optional<std::int64_t>>();
 * assert(j.ok());  // OK because an empty option can represent the null
 * @endcode
 *
 * @par Spanner Arrays (i.e., `std::vector<T>`)
 *
 * Spanner arrays are represented in C++ as a `std::vector<T>`, where the type
 * `T` may be any of the other allowed Spanner types, such as `bool`,
 * `std::int64_t`, etc. The only exception is that arrays may not directly
 * contain another array; to achieve a similar result you could create an array
 * of a 1-element struct holding an array. The following examples show usage of
 * arrays.
 *
 * @code
 * std::vector<std::int64_t> vec = {1, 2, 3, 4, 5};
 * spanner::Value v(vec);
 * assert(v.is<std::vector<std::int64_t>>());
 * auto copy = *v.get<std::vector<std::int64_t>>();
 * assert(vec == copy);
 * @endcode
 *
 * @par Spanner Structs (i.e., `std::tuple<Ts...>`)
 *
 * Spanner structs are represented in C++ as instances of `std::tuple` holding
 * zero or more of the allowed Spanner types, such as `bool`, `std::int64_t`,
 * `std::vector`, and even other `std::tuple` objects. Each tuple element
 * corresponds to a single field in a Spanner STRUCT.
 *
 * Spanner STRUCT fields may optionally contain a string indicating the field's
 * name. Fields names may be empty, unique, or repeated. A named field may be
 * specified as a tuple element of type `std::pair<std::string, T>`, where the
 * pair's `.first` member indicate's the field's name, and the `.second` member
 * is any valid Spanner type `T`.
 *
 * @code
 * using Struct = std::tuple<bool, std::pair<std::string, std::int64_t>>;
 * Struct s  = {true, {"Foo", 42}};
 * spanner::Value v(s);
 * assert(v.is<Struct>());
 * assert(s == *v.get<Struct>());
 * @endcode
 *
 * @note While a STRUCT's (optional) field names are not part of its C++ type,
 *   they are part of its Spanner STRUCT type. Array's (i.e., `std::vector`)
 *   must contain a single element type, therefore it is an error to construct
 *   a `std::vector` of `std::tuple` objects with differently named fields.
 */
class Value {
 public:
  /**
   * Constructs a non-null `Value` that holds nothing.
   *
   * All calls to `is<T>()`, `is_null<T>()`, and `get<T>()` will return false
   * or an error as appropriate.
   */
  Value() = default;

  // Copy and move.
  Value(Value const&) = default;
  Value(Value&&) = default;
  Value& operator=(Value const&) = default;
  Value& operator=(Value&&) = default;<commit_msg>Clarified docs about a default constructed Value. (googleapis/google-cloud-cpp-spanner#242)<commit_after>// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_VALUE_H_
#define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_VALUE_H_

#include "google/cloud/spanner/date.h"
#include "google/cloud/spanner/internal/tuple_utils.h"
#include "google/cloud/spanner/timestamp.h"
#include "google/cloud/spanner/version.h"
#include "google/cloud/internal/throw_delegate.h"
#include "google/cloud/optional.h"
#include "google/cloud/status_or.h"
#include <google/protobuf/struct.pb.h>
#include <google/protobuf/util/message_differencer.h>
#include <google/spanner/v1/type.pb.h>
#include <chrono>
#include <ostream>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility>

namespace google {
namespace cloud {
namespace spanner {
inline namespace SPANNER_CLIENT_NS {

class Value;  // Defined later in this file.
// Internal implementation details that callers should not use.
namespace internal {
Value FromProto(google::spanner::v1::Type t, google::protobuf::Value v);
std::pair<google::spanner::v1::Type, google::protobuf::Value> ToProto(Value v);
}  // namespace internal

/**
 * The Value class represents a type-safe, nullable Spanner value.
 *
 * It is conceptually similar to a `std::any` except the only allowed types are
 * those supported by Spanner, and a "null" value (similar to a `std::any`
 * without a value) still has an associated type that can be queried with
 * `Value::is<T>()`. The supported types are shown in the following table along
 * with how they map to the Spanner types
 * (https://cloud.google.com/spanner/docs/data-types):
 *
 * Spanner Type | C++ Type `T`
 * ------------ | ------------
 * BOOL         | `bool`
 * INT64        | `std::int64_t`
 * FLOAT64      | `double`
 * STRING       | `std::string`
 * TIMESTAMP    | `google::cloud::spanner::Timestamp`
 * DATE         | `google::cloud::spanner::Date`
 * ARRAY        | `std::vector<T>`  // [1]
 * STRUCT       | `std::tuple<Ts...>`
 *
 * [1] The type `T` may be any of the other supported types, except for
 *     ARRAY/`std::vector`.
 *
 * Value is a regular C++ value type with support for copy, move, equality,
 * etc. A default-constructed Value represents an empty value with no type.
 *
 * Callers may create instances by passing any of the supported values (shown
 * in the table above) to the constructor. "Null" values are created using the
 * `MakeNullValue<T>()` factory function or by passing an empty `optional<T>`
 * to the Value constructor..
 *
 * @par Example with a non-null value
 *
 * @code
 * std::string msg = "hello";
 * spanner::Value v(msg);
 * assert(v.is<std::string>());
 * assert(!v.is_null<std::string>());
 * StatusOr<std::string> copy = v.get<std::string>();
 * if (copy) {
 *   std::cout << *copy;  // prints "hello"
 * }
 * @endcode
 *
 * @par Example with a null
 *
 * @code
 * spanner::Value v = spanner::MakeNullValue<std::int64_t>();
 * assert(v.is<std::int64_t>());
 * assert(v.is_null<std::int64_t>());
 * StatusOr<std::int64_t> i = v.get<std::int64_t>();
 * assert(!i.ok());  // Can't get the value becuase v is null
 * StatusOr<optional<std::int64_t> j = v.get<optional<std::int64_t>>();
 * assert(j.ok());  // OK because an empty option can represent the null
 * @endcode
 *
 * @par Spanner Arrays (i.e., `std::vector<T>`)
 *
 * Spanner arrays are represented in C++ as a `std::vector<T>`, where the type
 * `T` may be any of the other allowed Spanner types, such as `bool`,
 * `std::int64_t`, etc. The only exception is that arrays may not directly
 * contain another array; to achieve a similar result you could create an array
 * of a 1-element struct holding an array. The following examples show usage of
 * arrays.
 *
 * @code
 * std::vector<std::int64_t> vec = {1, 2, 3, 4, 5};
 * spanner::Value v(vec);
 * assert(v.is<std::vector<std::int64_t>>());
 * auto copy = *v.get<std::vector<std::int64_t>>();
 * assert(vec == copy);
 * @endcode
 *
 * @par Spanner Structs (i.e., `std::tuple<Ts...>`)
 *
 * Spanner structs are represented in C++ as instances of `std::tuple` holding
 * zero or more of the allowed Spanner types, such as `bool`, `std::int64_t`,
 * `std::vector`, and even other `std::tuple` objects. Each tuple element
 * corresponds to a single field in a Spanner STRUCT.
 *
 * Spanner STRUCT fields may optionally contain a string indicating the field's
 * name. Fields names may be empty, unique, or repeated. A named field may be
 * specified as a tuple element of type `std::pair<std::string, T>`, where the
 * pair's `.first` member indicate's the field's name, and the `.second` member
 * is any valid Spanner type `T`.
 *
 * @code
 * using Struct = std::tuple<bool, std::pair<std::string, std::int64_t>>;
 * Struct s  = {true, {"Foo", 42}};
 * spanner::Value v(s);
 * assert(v.is<Struct>());
 * assert(s == *v.get<Struct>());
 * @endcode
 *
 * @note While a STRUCT's (optional) field names are not part of its C++ type,
 *   they are part of its Spanner STRUCT type. Array's (i.e., `std::vector`)
 *   must contain a single element type, therefore it is an error to construct
 *   a `std::vector` of `std::tuple` objects with differently named fields.
 */
class Value {
 public:
  /**
   * Constructs a non-null `Value` that holds nothing.
   *
   * The constructed object is logically empty. It will compare equal only to
   * another default constructed `Value`. All calls to `is<T>()`,
   * `is_null<T>()`, and `get<T>()` will return false or an error as
   * appropriate.
   */
  Value() = default;

  // Copy and move.
  Value(Value const&) = default;
  Value(Value&&) = default;
  Value& operator=(Value const&) = default;
  Value& operator=(Value&&) = default;
{'fraction_non_alphanumeric': 0.1470019342359768, 'fraction_numerical': 0.008784655061250805, 'mean_word_length': 3.9655862344937973, 'pattern_counts': {'":': 0, '<': 95, '<?xml version=': 0, '>': 89, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4123729', 'n_tokens_mistral': 4022, 'n_tokens_neox': 3914, 'n_words': 1368}