values_util.cc 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. // Copyright (c) 2012 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. #include "dbus/values_util.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "base/json/json_writer.h"
  8. #include "base/logging.h"
  9. #include "base/notreached.h"
  10. #include "base/values.h"
  11. #include "dbus/message.h"
  12. namespace dbus {
  13. namespace {
  14. // Returns whether |value| is exactly representable by double or not.
  15. template <typename T>
  16. bool IsExactlyRepresentableByDouble(T value) {
  17. return value == static_cast<T>(static_cast<double>(value));
  18. }
  19. // Pops values from |reader| and appends them to |list_value|.
  20. bool PopListElements(MessageReader* reader, base::Value* list_value) {
  21. DCHECK(list_value->is_list());
  22. while (reader->HasMoreData()) {
  23. base::Value element_value = PopDataAsValue(reader);
  24. if (element_value.is_none())
  25. return false;
  26. list_value->Append(std::move(element_value));
  27. }
  28. return true;
  29. }
  30. // Pops dict-entries from |reader| and sets them to |dictionary_value|
  31. bool PopDictionaryEntries(MessageReader* reader,
  32. base::Value* dictionary_value) {
  33. DCHECK(dictionary_value->is_dict());
  34. while (reader->HasMoreData()) {
  35. DCHECK_EQ(Message::DICT_ENTRY, reader->GetDataType());
  36. MessageReader entry_reader(nullptr);
  37. if (!reader->PopDictEntry(&entry_reader))
  38. return false;
  39. // Get key as a string.
  40. std::string key_string;
  41. if (entry_reader.GetDataType() == Message::STRING) {
  42. // If the type of keys is STRING, pop it directly.
  43. if (!entry_reader.PopString(&key_string))
  44. return false;
  45. } else {
  46. // If the type of keys is not STRING, convert it to string.
  47. base::Value key = PopDataAsValue(&entry_reader);
  48. if (key.is_none())
  49. return false;
  50. // Use JSONWriter to convert an arbitrary value to a string.
  51. base::JSONWriter::Write(key, &key_string);
  52. }
  53. // Get the value and set the key-value pair.
  54. base::Value value = PopDataAsValue(&entry_reader);
  55. if (value.is_none())
  56. return false;
  57. dictionary_value->SetKey(key_string, std::move(value));
  58. }
  59. return true;
  60. }
  61. // Gets the D-Bus type signature for the value.
  62. std::string GetTypeSignature(base::ValueView value) {
  63. struct Visitor {
  64. std::string operator()(absl::monostate) {
  65. DLOG(ERROR) << "Unexpected type " << base::Value::Type::NONE;
  66. return std::string();
  67. }
  68. std::string operator()(bool) { return "b"; }
  69. std::string operator()(int) { return "i"; }
  70. std::string operator()(double) { return "d"; }
  71. std::string operator()(base::StringPiece) { return "s"; }
  72. std::string operator()(const base::Value::BlobStorage&) { return "ay"; }
  73. std::string operator()(const base::Value::Dict&) { return "a{sv}"; }
  74. std::string operator()(const base::Value::List&) { return "av"; }
  75. };
  76. return value.Visit(Visitor());
  77. }
  78. } // namespace
  79. base::Value PopDataAsValue(MessageReader* reader) {
  80. base::Value result;
  81. switch (reader->GetDataType()) {
  82. case Message::INVALID_DATA:
  83. // Do nothing.
  84. break;
  85. case Message::BYTE: {
  86. uint8_t value = 0;
  87. if (reader->PopByte(&value))
  88. result = base::Value(value);
  89. break;
  90. }
  91. case Message::BOOL: {
  92. bool value = false;
  93. if (reader->PopBool(&value))
  94. result = base::Value(value);
  95. break;
  96. }
  97. case Message::INT16: {
  98. int16_t value = 0;
  99. if (reader->PopInt16(&value))
  100. result = base::Value(value);
  101. break;
  102. }
  103. case Message::UINT16: {
  104. uint16_t value = 0;
  105. if (reader->PopUint16(&value))
  106. result = base::Value(value);
  107. break;
  108. }
  109. case Message::INT32: {
  110. int32_t value = 0;
  111. if (reader->PopInt32(&value))
  112. result = base::Value(value);
  113. break;
  114. }
  115. case Message::UINT32: {
  116. uint32_t value = 0;
  117. if (reader->PopUint32(&value)) {
  118. result = base::Value(static_cast<double>(value));
  119. }
  120. break;
  121. }
  122. case Message::INT64: {
  123. int64_t value = 0;
  124. if (reader->PopInt64(&value)) {
  125. DLOG_IF(WARNING, !IsExactlyRepresentableByDouble(value))
  126. << value << " is not exactly representable by double";
  127. result = base::Value(static_cast<double>(value));
  128. }
  129. break;
  130. }
  131. case Message::UINT64: {
  132. uint64_t value = 0;
  133. if (reader->PopUint64(&value)) {
  134. DLOG_IF(WARNING, !IsExactlyRepresentableByDouble(value))
  135. << value << " is not exactly representable by double";
  136. result = base::Value(static_cast<double>(value));
  137. }
  138. break;
  139. }
  140. case Message::DOUBLE: {
  141. double value = 0;
  142. if (reader->PopDouble(&value))
  143. result = base::Value(value);
  144. break;
  145. }
  146. case Message::STRING: {
  147. std::string value;
  148. if (reader->PopString(&value))
  149. result = base::Value(value);
  150. break;
  151. }
  152. case Message::OBJECT_PATH: {
  153. ObjectPath value;
  154. if (reader->PopObjectPath(&value))
  155. result = base::Value(value.value());
  156. break;
  157. }
  158. case Message::UNIX_FD: {
  159. // Cannot distinguish a file descriptor from an int
  160. NOTREACHED();
  161. break;
  162. }
  163. case Message::ARRAY: {
  164. MessageReader sub_reader(nullptr);
  165. if (reader->PopArray(&sub_reader)) {
  166. // If the type of the array's element is DICT_ENTRY, create a
  167. // Value with type base::Value::Type::DICTIONARY, otherwise create a
  168. // Value with type base::Value::Type::LIST.
  169. if (sub_reader.GetDataType() == Message::DICT_ENTRY) {
  170. auto dictionary_value = base::Value(base::Value::Type::DICTIONARY);
  171. if (PopDictionaryEntries(&sub_reader, &dictionary_value))
  172. result = std::move(dictionary_value);
  173. } else {
  174. auto list_value = base::Value(base::Value::Type::LIST);
  175. if (PopListElements(&sub_reader, &list_value))
  176. result = std::move(list_value);
  177. }
  178. }
  179. break;
  180. }
  181. case Message::STRUCT: {
  182. MessageReader sub_reader(nullptr);
  183. if (reader->PopStruct(&sub_reader)) {
  184. auto list_value = base::Value(base::Value::Type::LIST);
  185. if (PopListElements(&sub_reader, &list_value))
  186. result = std::move(list_value);
  187. }
  188. break;
  189. }
  190. case Message::DICT_ENTRY:
  191. // DICT_ENTRY must be popped as an element of an array.
  192. NOTREACHED();
  193. break;
  194. case Message::VARIANT: {
  195. MessageReader sub_reader(nullptr);
  196. if (reader->PopVariant(&sub_reader))
  197. result = PopDataAsValue(&sub_reader);
  198. break;
  199. }
  200. }
  201. return result;
  202. }
  203. void AppendBasicTypeValueData(MessageWriter* writer, base::ValueView value) {
  204. struct Visitor {
  205. MessageWriter* writer;
  206. void operator()(absl::monostate) {
  207. DLOG(ERROR) << "Unexpected type: " << base::Value::Type::NONE;
  208. }
  209. void operator()(bool value) { writer->AppendBool(value); }
  210. void operator()(int value) { writer->AppendInt32(value); }
  211. void operator()(double value) { writer->AppendDouble(value); }
  212. void operator()(base::StringPiece value) { writer->AppendString(value); }
  213. void operator()(const base::Value::BlobStorage&) {
  214. DLOG(ERROR) << "Unexpected type: " << base::Value::Type::BINARY;
  215. }
  216. void operator()(const base::Value::Dict&) {
  217. DLOG(ERROR) << "Unexpected type: " << base::Value::Type::DICT;
  218. }
  219. void operator()(const base::Value::List&) {
  220. DLOG(ERROR) << "Unexpected type: " << base::Value::Type::LIST;
  221. }
  222. };
  223. value.Visit(Visitor{.writer = writer});
  224. }
  225. void AppendBasicTypeValueDataAsVariant(MessageWriter* writer,
  226. base::ValueView value) {
  227. MessageWriter sub_writer(nullptr);
  228. writer->OpenVariant(GetTypeSignature(value), &sub_writer);
  229. AppendBasicTypeValueData(&sub_writer, value);
  230. writer->CloseContainer(&sub_writer);
  231. }
  232. void AppendValueData(MessageWriter* writer, base::ValueView value) {
  233. struct Visitor {
  234. MessageWriter* writer;
  235. void operator()(absl::monostate) {
  236. DLOG(ERROR) << "Unexpected type: " << base::Value::Type::NONE;
  237. }
  238. void operator()(bool value) {
  239. return AppendBasicTypeValueData(writer, value);
  240. }
  241. void operator()(int value) {
  242. return AppendBasicTypeValueData(writer, value);
  243. }
  244. void operator()(double value) {
  245. return AppendBasicTypeValueData(writer, value);
  246. }
  247. void operator()(base::StringPiece value) {
  248. return AppendBasicTypeValueData(writer, value);
  249. }
  250. void operator()(const base::Value::BlobStorage& value) {
  251. DLOG(ERROR) << "Unexpected type: " << base::Value::Type::BINARY;
  252. }
  253. void operator()(const base::Value::Dict& value) {
  254. dbus::MessageWriter array_writer(nullptr);
  255. writer->OpenArray("{sv}", &array_writer);
  256. for (auto item : value) {
  257. dbus::MessageWriter dict_entry_writer(nullptr);
  258. array_writer.OpenDictEntry(&dict_entry_writer);
  259. dict_entry_writer.AppendString(item.first);
  260. AppendValueDataAsVariant(&dict_entry_writer, item.second);
  261. array_writer.CloseContainer(&dict_entry_writer);
  262. }
  263. writer->CloseContainer(&array_writer);
  264. }
  265. void operator()(const base::Value::List& value) {
  266. dbus::MessageWriter array_writer(nullptr);
  267. writer->OpenArray("v", &array_writer);
  268. for (const auto& value_in_list : value) {
  269. AppendValueDataAsVariant(&array_writer, value_in_list);
  270. }
  271. writer->CloseContainer(&array_writer);
  272. }
  273. };
  274. value.Visit(Visitor{.writer = writer});
  275. }
  276. void AppendValueDataAsVariant(MessageWriter* writer, base::ValueView value) {
  277. MessageWriter variant_writer(nullptr);
  278. writer->OpenVariant(GetTypeSignature(value), &variant_writer);
  279. AppendValueData(&variant_writer, value);
  280. writer->CloseContainer(&variant_writer);
  281. }
  282. } // namespace dbus