base_type_conversion.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. // Copyright 2021 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef UI_BASE_METADATA_BASE_TYPE_CONVERSION_H_
  5. #define UI_BASE_METADATA_BASE_TYPE_CONVERSION_H_
  6. #include <stdint.h>
  7. #include <algorithm> // Silence broken lint check
  8. #include <memory>
  9. #include <string>
  10. #include <utility>
  11. #include <vector>
  12. #include "base/component_export.h"
  13. #include "base/containers/fixed_flat_map.h"
  14. #include "base/files/file_path.h"
  15. #include "base/ranges/algorithm.h"
  16. #include "base/ranges/ranges.h"
  17. #include "base/strings/string_number_conversions.h"
  18. #include "base/strings/string_piece.h"
  19. #include "base/strings/string_split.h"
  20. #include "base/strings/string_util.h"
  21. #include "base/strings/stringprintf.h"
  22. #include "base/strings/sys_string_conversions.h"
  23. #include "base/strings/utf_string_conversions.h"
  24. #include "base/time/time.h"
  25. #include "third_party/abseil-cpp/absl/types/optional.h"
  26. #include "third_party/skia/include/core/SkColor.h"
  27. #include "ui/base/models/menu_separator_types.h"
  28. #include "ui/gfx/geometry/insets.h"
  29. #include "ui/gfx/geometry/point.h"
  30. #include "ui/gfx/geometry/point_f.h"
  31. #include "ui/gfx/geometry/rect.h"
  32. #include "ui/gfx/geometry/rect_f.h"
  33. #include "ui/gfx/geometry/size.h"
  34. #include "ui/gfx/geometry/size_f.h"
  35. #include "ui/gfx/range/range.h"
  36. #include "ui/gfx/shadow_value.h"
  37. #include "ui/gfx/text_constants.h"
  38. #include "url/gurl.h"
  39. #include "url/third_party/mozilla/url_parse.h"
  40. namespace ui {
  41. namespace metadata {
  42. using ValidStrings = std::vector<std::u16string>;
  43. // Various metadata methods pass types either by value or const ref depending on
  44. // whether the types are "small" (defined as "fundamental, enum, or pointer").
  45. // ArgType<T> gives the appropriate type to use as an argument in such cases.
  46. template <typename T>
  47. using ArgType =
  48. typename std::conditional<std::is_fundamental<T>::value ||
  49. std::is_enum<T>::value ||
  50. std::is_pointer<T>::value ||
  51. (std::is_move_assignable<T>::value &&
  52. std::is_move_constructible<T>::value &&
  53. !std::is_copy_assignable<T>::value &&
  54. !std::is_copy_constructible<T>::value),
  55. T,
  56. const T&>::type;
  57. COMPONENT_EXPORT(UI_BASE_METADATA) extern const char kNoPrefix[];
  58. COMPONENT_EXPORT(UI_BASE_METADATA) extern const char kSkColorPrefix[];
  59. // General Type Conversion Template Functions ---------------------------------
  60. template <bool serializable,
  61. bool read_only = false,
  62. const char* name_prefix = kNoPrefix>
  63. struct BaseTypeConverter {
  64. static constexpr bool is_serializable = serializable;
  65. static constexpr bool is_read_only = read_only;
  66. static bool IsSerializable() { return is_serializable; }
  67. static bool IsReadOnly() { return is_read_only; }
  68. static const char* PropertyNamePrefix() { return name_prefix; }
  69. };
  70. template <typename T>
  71. struct TypeConverter : BaseTypeConverter<std::is_enum<T>::value> {
  72. static std::u16string ToString(ArgType<T> source_value);
  73. static absl::optional<T> FromString(const std::u16string& source_value);
  74. static ValidStrings GetValidStrings();
  75. };
  76. // The following definitions and macros are needed only in cases where a type
  77. // is a mere alias to a POD type AND a specialized type converter is also needed
  78. // to handle different the string conversions different from the existing POD
  79. // type converter. See SkColor below as an example of their use.
  80. // NOTE: This should be a rare occurrence and if possible use a unique type and
  81. // a TypeConverter specialization based on that unique type.
  82. template <typename T, typename K>
  83. struct Uniquifier {
  84. using type = T;
  85. using tag = K;
  86. };
  87. #define MAKE_TYPE_UNIQUE(type_name) \
  88. struct type_name##Tag {}; \
  89. using type_name##Unique = \
  90. ::ui::metadata::Uniquifier<type_name, type_name##Tag>
  91. #define _UNIQUE_TYPE_NAME1(type_name) type_name##Unique
  92. #define _UNIQUE_TYPE_NAME2(qualifier, type_name) qualifier::type_name##Unique
  93. #define _GET_TYPE_MACRO(_1, _2, NAME, ...) NAME
  94. #define UNIQUE_TYPE_NAME(name, ...) \
  95. _GET_TYPE_MACRO(name, ##__VA_ARGS__, _UNIQUE_TYPE_NAME2, _UNIQUE_TYPE_NAME1) \
  96. (name, ##__VA_ARGS__)
  97. // Types and macros for generating enum converters ----------------------------
  98. template <typename T>
  99. struct EnumStringsMap;
  100. // *****************************************************************
  101. // * NOTE: The ENUM macros *must* be placed outside any namespace. *
  102. // *****************************************************************
  103. //
  104. // Use this macro only if your enum converters need to be accessible across
  105. // modules. Place this in the header file for the module and use the other macro
  106. // below as described.
  107. //
  108. #define EXPORT_ENUM_CONVERTERS(T, EXPORT) \
  109. template <> \
  110. EXPORT std::u16string ui::metadata::TypeConverter<T>::ToString( \
  111. ui::metadata::ArgType<T> source_value); \
  112. \
  113. template <> \
  114. EXPORT absl::optional<T> ui::metadata::TypeConverter<T>::FromString( \
  115. const std::u16string& str); \
  116. \
  117. template <> \
  118. EXPORT ui::metadata::ValidStrings \
  119. ui::metadata::TypeConverter<T>::GetValidStrings();
  120. // Generate the code to define a enum type to and from std::u16string
  121. // conversions. The first argument is the type T, and the rest of the argument
  122. // should have the enum value and string pairs defined in a format like
  123. // "{enum_value0, string16_value0}, {enum_value1, string16_value1} ...".
  124. // Both enum_values and string16_values need to be compile time constants.
  125. //
  126. #define DEFINE_ENUM_CONVERTERS(T, ...) \
  127. template <> \
  128. struct ui::metadata::EnumStringsMap<T> { \
  129. static_assert(std::is_enum<T>::value, "Error: " #T " is not an enum."); \
  130. \
  131. static const auto& Get() { \
  132. static constexpr auto kMap = \
  133. base::MakeFixedFlatMap<T, base::StringPiece16>({__VA_ARGS__}); \
  134. return kMap; \
  135. } \
  136. }; \
  137. \
  138. template <> \
  139. std::u16string ui::metadata::TypeConverter<T>::ToString( \
  140. ui::metadata::ArgType<T> source_value) { \
  141. const auto& map = EnumStringsMap<T>::Get(); \
  142. auto* it = map.find(source_value); \
  143. return it != map.end() ? std::u16string(it->second) : std::u16string(); \
  144. } \
  145. \
  146. template <> \
  147. absl::optional<T> ui::metadata::TypeConverter<T>::FromString( \
  148. const std::u16string& str) { \
  149. const auto& map = EnumStringsMap<T>::Get(); \
  150. using Pair = base::ranges::range_value_t<decltype(map)>; \
  151. auto* it = base::ranges::find(map, str, &Pair::second); \
  152. return it != map.end() ? absl::make_optional(it->first) : absl::nullopt; \
  153. } \
  154. \
  155. template <> \
  156. ui::metadata::ValidStrings \
  157. ui::metadata::TypeConverter<T>::GetValidStrings() { \
  158. ValidStrings string_values; \
  159. base::ranges::transform( \
  160. EnumStringsMap<T>::Get(), std::back_inserter(string_values), \
  161. [](const auto& pair) { return std::u16string(pair.second); }); \
  162. return string_values; \
  163. }
  164. // String Conversions ---------------------------------------------------------
  165. COMPONENT_EXPORT(UI_BASE_METADATA)
  166. std::u16string PointerToString(const void* pointer_val);
  167. #define DECLARE_CONVERSIONS(T) \
  168. template <> \
  169. struct COMPONENT_EXPORT(UI_BASE_METADATA) \
  170. TypeConverter<T> : BaseTypeConverter<true> { \
  171. static std::u16string ToString(ArgType<T> source_value); \
  172. static absl::optional<T> FromString(const std::u16string& source_value); \
  173. static ValidStrings GetValidStrings() { return {}; } \
  174. };
  175. DECLARE_CONVERSIONS(int8_t)
  176. DECLARE_CONVERSIONS(int16_t)
  177. DECLARE_CONVERSIONS(int32_t)
  178. DECLARE_CONVERSIONS(int64_t)
  179. DECLARE_CONVERSIONS(uint8_t)
  180. DECLARE_CONVERSIONS(uint16_t)
  181. DECLARE_CONVERSIONS(uint32_t)
  182. DECLARE_CONVERSIONS(uint64_t)
  183. DECLARE_CONVERSIONS(float)
  184. DECLARE_CONVERSIONS(double)
  185. DECLARE_CONVERSIONS(const char*)
  186. DECLARE_CONVERSIONS(base::FilePath)
  187. DECLARE_CONVERSIONS(std::u16string)
  188. DECLARE_CONVERSIONS(base::TimeDelta)
  189. DECLARE_CONVERSIONS(gfx::Insets)
  190. DECLARE_CONVERSIONS(gfx::Point)
  191. DECLARE_CONVERSIONS(gfx::PointF)
  192. DECLARE_CONVERSIONS(gfx::Range)
  193. DECLARE_CONVERSIONS(gfx::Rect)
  194. DECLARE_CONVERSIONS(gfx::RectF)
  195. DECLARE_CONVERSIONS(gfx::ShadowValues)
  196. DECLARE_CONVERSIONS(gfx::Size)
  197. DECLARE_CONVERSIONS(gfx::SizeF)
  198. DECLARE_CONVERSIONS(std::string)
  199. DECLARE_CONVERSIONS(url::Component)
  200. #undef DECLARE_CONVERSIONS
  201. template <>
  202. struct COMPONENT_EXPORT(UI_BASE_METADATA) TypeConverter<bool>
  203. : BaseTypeConverter<true> {
  204. static std::u16string ToString(bool source_value);
  205. static absl::optional<bool> FromString(const std::u16string& source_value);
  206. static ValidStrings GetValidStrings();
  207. };
  208. // Special conversions for wrapper types --------------------------------------
  209. COMPONENT_EXPORT(UI_BASE_METADATA) const std::u16string& GetNullOptStr();
  210. template <typename T>
  211. struct TypeConverter<absl::optional<T>>
  212. : BaseTypeConverter<TypeConverter<T>::is_serializable> {
  213. static std::u16string ToString(ArgType<absl::optional<T>> source_value) {
  214. if (!source_value)
  215. return GetNullOptStr();
  216. return TypeConverter<T>::ToString(source_value.value());
  217. }
  218. static absl::optional<absl::optional<T>> FromString(
  219. const std::u16string& source_value) {
  220. if (source_value == GetNullOptStr())
  221. return absl::make_optional<absl::optional<T>>(absl::nullopt);
  222. auto ret = TypeConverter<T>::FromString(source_value);
  223. return ret ? absl::make_optional(ret) : absl::nullopt;
  224. }
  225. static ValidStrings GetValidStrings() { return {}; }
  226. };
  227. // Special Conversions for std:unique_ptr<T> and T* types ----------------------
  228. template <typename T>
  229. struct TypeConverter<std::unique_ptr<T>> : BaseTypeConverter<false, true> {
  230. static std::u16string ToString(const std::unique_ptr<T>& source_value) {
  231. return PointerToString(source_value.get());
  232. }
  233. static std::u16string ToString(const T* source_value) {
  234. return PointerToString(source_value);
  235. }
  236. static absl::optional<std::unique_ptr<T>> FromString(
  237. const std::u16string& source_value) {
  238. DCHECK(false) << "Type converter cannot convert from string.";
  239. return absl::nullopt;
  240. }
  241. static ValidStrings GetValidStrings() { return {}; }
  242. };
  243. template <typename T>
  244. struct TypeConverter<T*> : BaseTypeConverter<false, true> {
  245. static std::u16string ToString(ArgType<T*> source_value) {
  246. return PointerToString(source_value);
  247. }
  248. static absl::optional<T*> FromString(const std::u16string& source_value) {
  249. DCHECK(false) << "Type converter cannot convert from string.";
  250. return absl::nullopt;
  251. }
  252. static ValidStrings GetValidStrings() { return {}; }
  253. };
  254. template <typename T>
  255. struct TypeConverter<std::vector<T>>
  256. : BaseTypeConverter<TypeConverter<T>::is_serializable> {
  257. static std::u16string ToString(ArgType<std::vector<T>> source_value) {
  258. std::vector<std::u16string> serialized;
  259. base::ranges::transform(source_value, std::back_inserter(serialized),
  260. &TypeConverter<T>::ToString);
  261. return u"{" + base::JoinString(serialized, u",") + u"}";
  262. }
  263. static absl::optional<std::vector<T>> FromString(
  264. const std::u16string& source_value) {
  265. if (source_value.empty() || source_value.front() != u'{' ||
  266. source_value.back() != u'}')
  267. return absl::nullopt;
  268. const auto values =
  269. base::SplitString(source_value.substr(1, source_value.length() - 2),
  270. u",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
  271. std::vector<T> output;
  272. for (const auto& value : values) {
  273. auto ret = TypeConverter<T>::FromString(value);
  274. if (!ret)
  275. return absl::nullopt;
  276. output.push_back(*ret);
  277. }
  278. return absl::make_optional(output);
  279. }
  280. static ValidStrings GetValidStrings() { return {}; }
  281. };
  282. MAKE_TYPE_UNIQUE(SkColor);
  283. template <>
  284. struct COMPONENT_EXPORT(UI_BASE_METADATA)
  285. TypeConverter<UNIQUE_TYPE_NAME(SkColor)>
  286. : BaseTypeConverter<true, false, kSkColorPrefix> {
  287. static std::u16string ToString(SkColor source_value);
  288. static absl::optional<SkColor> FromString(const std::u16string& source_value);
  289. static ValidStrings GetValidStrings();
  290. // Parses a string within |start| and |end| for a color string in the forms
  291. // rgb(r, g, b), rgba(r, g, b, a), hsl(h, s%, l%), hsla(h, s%, l%, a),
  292. // 0xXXXXXX, 0xXXXXXXXX, <decimal number>
  293. // Returns the full string in |color| and the position immediately following
  294. // the last token in |next_token|.
  295. // Returns false if the input string cannot be properly parsed. |color| and
  296. // |next_token| will be undefined.
  297. static bool GetNextColor(std::u16string::const_iterator start,
  298. std::u16string::const_iterator end,
  299. std::u16string& color,
  300. std::u16string::const_iterator& next_token);
  301. static bool GetNextColor(std::u16string::const_iterator start,
  302. std::u16string::const_iterator end,
  303. std::u16string& color);
  304. // Same as above, except returns the color string converted into an |SkColor|.
  305. // Returns absl::nullopt if the color string cannot be properly parsed or the
  306. // string cannot be converted into a valid SkColor and |next_token| may be
  307. // undefined.
  308. static absl::optional<SkColor> GetNextColor(
  309. std::u16string::const_iterator start,
  310. std::u16string::const_iterator end,
  311. std::u16string::const_iterator& next_token);
  312. static absl::optional<SkColor> GetNextColor(
  313. std::u16string::const_iterator start,
  314. std::u16string::const_iterator end);
  315. // Converts the four elements of |pieces| beginning at |start_piece| to an
  316. // SkColor by assuming the pieces are split from a string like
  317. // "rgba(r,g,b,a)". Returns nullopt if conversion was unsuccessful.
  318. static absl::optional<SkColor> RgbaPiecesToSkColor(
  319. const std::vector<base::StringPiece16>& pieces,
  320. size_t start_piece);
  321. private:
  322. static absl::optional<SkColor> ParseHexString(
  323. const std::u16string& hex_string);
  324. static absl::optional<SkColor> ParseHslString(
  325. const std::u16string& hsl_string);
  326. static absl::optional<SkColor> ParseRgbString(
  327. const std::u16string& rgb_string);
  328. };
  329. using SkColorConverter = TypeConverter<UNIQUE_TYPE_NAME(SkColor)>;
  330. } // namespace metadata
  331. } // namespace ui
  332. EXPORT_ENUM_CONVERTERS(gfx::HorizontalAlignment,
  333. COMPONENT_EXPORT(UI_BASE_METADATA))
  334. EXPORT_ENUM_CONVERTERS(gfx::VerticalAlignment,
  335. COMPONENT_EXPORT(UI_BASE_METADATA))
  336. EXPORT_ENUM_CONVERTERS(gfx::ElideBehavior, COMPONENT_EXPORT(UI_BASE_METADATA))
  337. EXPORT_ENUM_CONVERTERS(ui::MenuSeparatorType,
  338. COMPONENT_EXPORT(UI_BASE_METADATA))
  339. #endif // UI_BASE_METADATA_BASE_TYPE_CONVERSION_H_