blob: eef5b62cc0b8fbba46cbaa76e6e3cbd31e2a724c [file] [log] [blame]
// Copyright 2019 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 UI_VIEWS_METADATA_TYPE_CONVERSION_H_
#define UI_VIEWS_METADATA_TYPE_CONVERSION_H_
#include <stdint.h>
#include <memory>
#include <utility>
#include <vector>
#include "base/no_destructor.h"
#include "base/optional.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/range/range.h"
#include "ui/gfx/shadow_value.h"
#include "ui/gfx/text_constants.h"
#include "ui/views/views_export.h"
namespace views {
namespace metadata {
using ValidStrings = std::vector<base::string16>;
// Various metadata methods pass types either by value or const ref depending on
// whether the types are "small" (defined as "fundamental, enum, or pointer").
// ArgType<T> gives the appropriate type to use as an argument in such cases.
template <typename T>
using ArgType =
typename std::conditional<std::is_fundamental<T>::value ||
std::is_enum<T>::value ||
std::is_pointer<T>::value ||
(std::is_move_assignable<T>::value &&
std::is_move_constructible<T>::value &&
!std::is_copy_assignable<T>::value &&
!std::is_copy_constructible<T>::value),
T,
const T&>::type;
// General Type Conversion Template Functions ---------------------------------
template <bool serializable>
struct BaseTypeConverter {
static constexpr bool is_serializable = serializable;
static bool IsSerializable() { return is_serializable; }
};
template <typename T>
struct TypeConverter : BaseTypeConverter<std::is_enum<T>::value> {
static base::string16 ToString(ArgType<T> source_value);
static base::Optional<T> FromString(const base::string16& source_value);
static ValidStrings GetValidStrings();
};
// Types and macros for generating enum converters ----------------------------
template <typename T>
struct EnumStrings {
struct EnumString {
T enum_value;
base::string16 str_value;
};
explicit EnumStrings(std::vector<EnumString> init_val)
: pairs(std::move(init_val)) {}
ValidStrings GetStringValues() const {
ValidStrings string_values;
for (const auto& pair : pairs)
string_values.push_back(pair.str_value);
return string_values;
}
const std::vector<EnumString> pairs;
};
template <typename T>
static const EnumStrings<T>& GetEnumStringsInstance();
// Generate the code to define a enum type to and from base::string16
// conversions. The first argument is the type T, and the rest of the argument
// should have the enum value and string pairs defined in a format like
// "{enum_value0, string16_value0}, {enum_value1, string16_value1} ...".
#define DEFINE_ENUM_CONVERTERS(T, ...) \
template <> \
const views::metadata::EnumStrings<T>& \
views::metadata::GetEnumStringsInstance<T>() { \
static const base::NoDestructor<EnumStrings<T>> instance( \
std::vector<views::metadata::EnumStrings<T>::EnumString>( \
{__VA_ARGS__})); \
return *instance; \
} \
\
template <> \
base::string16 views::metadata::TypeConverter<T>::ToString( \
ArgType<T> source_value) { \
for (const auto& pair : GetEnumStringsInstance<T>().pairs) { \
if (source_value == pair.enum_value) \
return pair.str_value; \
} \
return base::string16(); \
} \
\
template <> \
base::Optional<T> views::metadata::TypeConverter<T>::FromString( \
const base::string16& source_value) { \
for (const auto& pair : GetEnumStringsInstance<T>().pairs) { \
if (source_value == pair.str_value) { \
return pair.enum_value; \
} \
} \
return base::nullopt; \
} \
\
template <> \
views::metadata::ValidStrings \
views::metadata::TypeConverter<T>::GetValidStrings() { \
return GetEnumStringsInstance<T>().GetStringValues(); \
}
// String Conversions ---------------------------------------------------------
// Converts the four elements of |pieces| beginning at |start_piece| to an
// SkColor by assuming the pieces are split from a string like "rgba(r,g,b,a)".
// Returns nullopt if conversion was unsuccessful.
VIEWS_EXPORT base::Optional<SkColor> RgbaPiecesToSkColor(
const std::vector<base::StringPiece16>& pieces,
size_t start_piece);
#define DECLARE_CONVERSIONS(T) \
template <> \
struct VIEWS_EXPORT TypeConverter<T> : BaseTypeConverter<true> { \
static base::string16 ToString(ArgType<T> source_value); \
static base::Optional<T> FromString(const base::string16& source_value); \
static ValidStrings GetValidStrings() { return {}; } \
};
DECLARE_CONVERSIONS(int8_t)
DECLARE_CONVERSIONS(int16_t)
DECLARE_CONVERSIONS(int32_t)
DECLARE_CONVERSIONS(int64_t)
DECLARE_CONVERSIONS(uint8_t)
DECLARE_CONVERSIONS(uint16_t)
DECLARE_CONVERSIONS(uint32_t)
DECLARE_CONVERSIONS(uint64_t)
DECLARE_CONVERSIONS(float)
DECLARE_CONVERSIONS(double)
DECLARE_CONVERSIONS(const char*)
DECLARE_CONVERSIONS(base::string16)
DECLARE_CONVERSIONS(base::TimeDelta)
DECLARE_CONVERSIONS(gfx::ShadowValues)
DECLARE_CONVERSIONS(gfx::Size)
DECLARE_CONVERSIONS(gfx::Range)
DECLARE_CONVERSIONS(gfx::Insets)
#undef DECLARE_CONVERSIONS
template <>
struct VIEWS_EXPORT TypeConverter<bool> : BaseTypeConverter<true> {
static base::string16 ToString(bool source_value);
static base::Optional<bool> FromString(const base::string16& source_value);
static ValidStrings GetValidStrings();
};
// Special Conversions for base::Optional<T> type ------------------------------
VIEWS_EXPORT const base::string16& GetNullOptStr();
template <typename T>
struct TypeConverter<base::Optional<T>>
: BaseTypeConverter<TypeConverter<T>::is_serializable> {
static base::string16 ToString(ArgType<base::Optional<T>> source_value) {
if (!source_value)
return GetNullOptStr();
return TypeConverter<T>::ToString(source_value.value());
}
static base::Optional<base::Optional<T>> FromString(
const base::string16& source_value) {
if (source_value == GetNullOptStr())
return base::make_optional<base::Optional<T>>(base::nullopt);
auto ret = TypeConverter<T>::FromString(source_value);
return ret ? base::make_optional(ret) : base::nullopt;
}
static ValidStrings GetValidStrings() { return {}; }
};
template <typename T>
struct TypeConverter<std::unique_ptr<T>> : BaseTypeConverter<false> {
static base::string16 ToString(const std::unique_ptr<T>& source_value);
static base::Optional<std::unique_ptr<T>> FromString(
const base::string16& source_value);
static ValidStrings GetValidStrings() { return {}; }
};
} // namespace metadata
} // namespace views
#endif // UI_VIEWS_METADATA_TYPE_CONVERSION_H_