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 5 #include "dbus/property.h" 6 7 #include <stddef.h> 8 9 #include <memory> 10 11 #include "base/bind.h" 12 #include "base/logging.h" 13 14 #include "dbus/message.h" 15 #include "dbus/object_path.h" 16 #include "dbus/object_proxy.h" 17 18 namespace dbus { 19 20 // 21 // PropertyBase implementation. 22 // 23 24 PropertyBase::PropertyBase() : property_set_(nullptr), is_valid_(false) {} 25 26 PropertyBase::~PropertyBase() = default; 27 28 void PropertyBase::Init(PropertySet* property_set, const std::string& name) { 29 DCHECK(!property_set_); 30 property_set_ = property_set; 31 is_valid_ = false; 32 name_ = name; 33 } 34 35 // 36 // PropertySet implementation. 37 // 38 39 PropertySet::PropertySet( 40 ObjectProxy* object_proxy, 41 const std::string& interface, 42 const PropertyChangedCallback& property_changed_callback) 43 : object_proxy_(object_proxy), 44 interface_(interface), 45 property_changed_callback_(property_changed_callback), 46 weak_ptr_factory_(this) {} 47 48 PropertySet::~PropertySet() = default; 49 50 void PropertySet::RegisterProperty(const std::string& name, 51 PropertyBase* property) { 52 property->Init(this, name); 53 properties_map_[name] = property; 54 } 55 56 void PropertySet::ConnectSignals() { 57 DCHECK(object_proxy_); 58 object_proxy_->ConnectToSignal( 59 kPropertiesInterface, 60 kPropertiesChanged, 61 base::Bind(&PropertySet::ChangedReceived, 62 weak_ptr_factory_.GetWeakPtr()), 63 base::Bind(&PropertySet::ChangedConnected, 64 weak_ptr_factory_.GetWeakPtr())); 65 } 66 67 68 void PropertySet::ChangedReceived(Signal* signal) { 69 DCHECK(signal); 70 MessageReader reader(signal); 71 72 std::string interface; 73 if (!reader.PopString(&interface)) { 74 LOG(WARNING) << "Property changed signal has wrong parameters: " 75 << "expected interface name: " << signal->ToString(); 76 return; 77 } 78 79 if (interface != this->interface()) 80 return; 81 82 if (!UpdatePropertiesFromReader(&reader)) { 83 LOG(WARNING) << "Property changed signal has wrong parameters: " 84 << "expected dictionary: " << signal->ToString(); 85 } 86 87 if (!InvalidatePropertiesFromReader(&reader)) { 88 LOG(WARNING) << "Property changed signal has wrong parameters: " 89 << "expected array to invalidate: " << signal->ToString(); 90 } 91 } 92 93 void PropertySet::ChangedConnected(const std::string& interface_name, 94 const std::string& signal_name, 95 bool success) { 96 LOG_IF(WARNING, !success) << "Failed to connect to " << signal_name 97 << "signal."; 98 } 99 100 101 void PropertySet::Get(PropertyBase* property, GetCallback callback) { 102 MethodCall method_call(kPropertiesInterface, kPropertiesGet); 103 MessageWriter writer(&method_call); 104 writer.AppendString(interface()); 105 writer.AppendString(property->name()); 106 107 DCHECK(object_proxy_); 108 object_proxy_->CallMethod(&method_call, 109 ObjectProxy::TIMEOUT_USE_DEFAULT, 110 base::Bind(&PropertySet::OnGet, 111 GetWeakPtr(), 112 property, 113 callback)); 114 } 115 116 void PropertySet::OnGet(PropertyBase* property, GetCallback callback, 117 Response* response) { 118 if (!response) { 119 LOG(WARNING) << property->name() << ": Get: failed."; 120 return; 121 } 122 123 MessageReader reader(response); 124 if (property->PopValueFromReader(&reader)) { 125 property->set_valid(true); 126 NotifyPropertyChanged(property->name()); 127 } else { 128 if (property->is_valid()) { 129 property->set_valid(false); 130 NotifyPropertyChanged(property->name()); 131 } 132 } 133 134 if (!callback.is_null()) 135 callback.Run(response); 136 } 137 138 bool PropertySet::GetAndBlock(PropertyBase* property) { 139 MethodCall method_call(kPropertiesInterface, kPropertiesGet); 140 MessageWriter writer(&method_call); 141 writer.AppendString(interface()); 142 writer.AppendString(property->name()); 143 144 DCHECK(object_proxy_); 145 std::unique_ptr<dbus::Response> response(object_proxy_->CallMethodAndBlock( 146 &method_call, ObjectProxy::TIMEOUT_USE_DEFAULT)); 147 148 if (!response.get()) { 149 LOG(WARNING) << property->name() << ": GetAndBlock: failed."; 150 return false; 151 } 152 153 MessageReader reader(response.get()); 154 if (property->PopValueFromReader(&reader)) { 155 property->set_valid(true); 156 NotifyPropertyChanged(property->name()); 157 } else { 158 if (property->is_valid()) { 159 property->set_valid(false); 160 NotifyPropertyChanged(property->name()); 161 } 162 } 163 return true; 164 } 165 166 void PropertySet::GetAll() { 167 MethodCall method_call(kPropertiesInterface, kPropertiesGetAll); 168 MessageWriter writer(&method_call); 169 writer.AppendString(interface()); 170 171 DCHECK(object_proxy_); 172 object_proxy_->CallMethod(&method_call, 173 ObjectProxy::TIMEOUT_USE_DEFAULT, 174 base::Bind(&PropertySet::OnGetAll, 175 weak_ptr_factory_.GetWeakPtr())); 176 } 177 178 void PropertySet::OnGetAll(Response* response) { 179 if (!response) { 180 LOG(WARNING) << "GetAll request failed for: " << interface_; 181 return; 182 } 183 184 MessageReader reader(response); 185 if (!UpdatePropertiesFromReader(&reader)) { 186 LOG(WARNING) << "GetAll response has wrong parameters: " 187 << "expected dictionary: " << response->ToString(); 188 } 189 } 190 191 void PropertySet::Set(PropertyBase* property, SetCallback callback) { 192 MethodCall method_call(kPropertiesInterface, kPropertiesSet); 193 MessageWriter writer(&method_call); 194 writer.AppendString(interface()); 195 writer.AppendString(property->name()); 196 property->AppendSetValueToWriter(&writer); 197 198 DCHECK(object_proxy_); 199 object_proxy_->CallMethod(&method_call, 200 ObjectProxy::TIMEOUT_USE_DEFAULT, 201 base::Bind(&PropertySet::OnSet, 202 GetWeakPtr(), 203 property, 204 callback)); 205 } 206 207 bool PropertySet::SetAndBlock(PropertyBase* property) { 208 MethodCall method_call(kPropertiesInterface, kPropertiesSet); 209 MessageWriter writer(&method_call); 210 writer.AppendString(interface()); 211 writer.AppendString(property->name()); 212 property->AppendSetValueToWriter(&writer); 213 214 DCHECK(object_proxy_); 215 std::unique_ptr<dbus::Response> response(object_proxy_->CallMethodAndBlock( 216 &method_call, ObjectProxy::TIMEOUT_USE_DEFAULT)); 217 if (response.get()) 218 return true; 219 return false; 220 } 221 222 void PropertySet::OnSet(PropertyBase* property, 223 SetCallback callback, 224 Response* response) { 225 LOG_IF(WARNING, !response) << property->name() << ": Set: failed."; 226 if (!callback.is_null()) 227 callback.Run(response); 228 } 229 230 bool PropertySet::UpdatePropertiesFromReader(MessageReader* reader) { 231 DCHECK(reader); 232 MessageReader array_reader(nullptr); 233 if (!reader->PopArray(&array_reader)) 234 return false; 235 236 while (array_reader.HasMoreData()) { 237 MessageReader dict_entry_reader(nullptr); 238 if (array_reader.PopDictEntry(&dict_entry_reader)) 239 UpdatePropertyFromReader(&dict_entry_reader); 240 } 241 242 return true; 243 } 244 245 bool PropertySet::UpdatePropertyFromReader(MessageReader* reader) { 246 DCHECK(reader); 247 248 std::string name; 249 if (!reader->PopString(&name)) 250 return false; 251 252 PropertiesMap::iterator it = properties_map_.find(name); 253 if (it == properties_map_.end()) 254 return false; 255 256 PropertyBase* property = it->second; 257 if (property->PopValueFromReader(reader)) { 258 property->set_valid(true); 259 NotifyPropertyChanged(name); 260 return true; 261 } else { 262 if (property->is_valid()) { 263 property->set_valid(false); 264 NotifyPropertyChanged(property->name()); 265 } 266 return false; 267 } 268 } 269 270 bool PropertySet::InvalidatePropertiesFromReader(MessageReader* reader) { 271 DCHECK(reader); 272 MessageReader array_reader(nullptr); 273 if (!reader->PopArray(&array_reader)) 274 return false; 275 276 while (array_reader.HasMoreData()) { 277 std::string name; 278 if (!array_reader.PopString(&name)) 279 return false; 280 281 PropertiesMap::iterator it = properties_map_.find(name); 282 if (it == properties_map_.end()) 283 continue; 284 285 PropertyBase* property = it->second; 286 if (property->is_valid()) { 287 property->set_valid(false); 288 NotifyPropertyChanged(property->name()); 289 } 290 } 291 292 return true; 293 } 294 295 void PropertySet::NotifyPropertyChanged(const std::string& name) { 296 if (!property_changed_callback_.is_null()) 297 property_changed_callback_.Run(name); 298 } 299 300 // 301 // Property<Byte> specialization. 302 // 303 304 template <> 305 Property<uint8_t>::Property() 306 : value_(0) {} 307 308 template <> 309 bool Property<uint8_t>::PopValueFromReader(MessageReader* reader) { 310 return reader->PopVariantOfByte(&value_); 311 } 312 313 template <> 314 void Property<uint8_t>::AppendSetValueToWriter(MessageWriter* writer) { 315 writer->AppendVariantOfByte(set_value_); 316 } 317 318 // 319 // Property<bool> specialization. 320 // 321 322 template <> 323 Property<bool>::Property() : value_(false) { 324 } 325 326 template <> 327 bool Property<bool>::PopValueFromReader(MessageReader* reader) { 328 return reader->PopVariantOfBool(&value_); 329 } 330 331 template <> 332 void Property<bool>::AppendSetValueToWriter(MessageWriter* writer) { 333 writer->AppendVariantOfBool(set_value_); 334 } 335 336 // 337 // Property<int16_t> specialization. 338 // 339 340 template <> 341 Property<int16_t>::Property() 342 : value_(0) {} 343 344 template <> 345 bool Property<int16_t>::PopValueFromReader(MessageReader* reader) { 346 return reader->PopVariantOfInt16(&value_); 347 } 348 349 template <> 350 void Property<int16_t>::AppendSetValueToWriter(MessageWriter* writer) { 351 writer->AppendVariantOfInt16(set_value_); 352 } 353 354 // 355 // Property<uint16_t> specialization. 356 // 357 358 template <> 359 Property<uint16_t>::Property() 360 : value_(0) {} 361 362 template <> 363 bool Property<uint16_t>::PopValueFromReader(MessageReader* reader) { 364 return reader->PopVariantOfUint16(&value_); 365 } 366 367 template <> 368 void Property<uint16_t>::AppendSetValueToWriter(MessageWriter* writer) { 369 writer->AppendVariantOfUint16(set_value_); 370 } 371 372 // 373 // Property<int32_t> specialization. 374 // 375 376 template <> 377 Property<int32_t>::Property() 378 : value_(0) {} 379 380 template <> 381 bool Property<int32_t>::PopValueFromReader(MessageReader* reader) { 382 return reader->PopVariantOfInt32(&value_); 383 } 384 385 template <> 386 void Property<int32_t>::AppendSetValueToWriter(MessageWriter* writer) { 387 writer->AppendVariantOfInt32(set_value_); 388 } 389 390 // 391 // Property<uint32_t> specialization. 392 // 393 394 template <> 395 Property<uint32_t>::Property() 396 : value_(0) {} 397 398 template <> 399 bool Property<uint32_t>::PopValueFromReader(MessageReader* reader) { 400 return reader->PopVariantOfUint32(&value_); 401 } 402 403 template <> 404 void Property<uint32_t>::AppendSetValueToWriter(MessageWriter* writer) { 405 writer->AppendVariantOfUint32(set_value_); 406 } 407 408 // 409 // Property<int64_t> specialization. 410 // 411 412 template <> 413 Property<int64_t>::Property() 414 : value_(0), set_value_(0) {} 415 416 template <> 417 bool Property<int64_t>::PopValueFromReader(MessageReader* reader) { 418 return reader->PopVariantOfInt64(&value_); 419 } 420 421 template <> 422 void Property<int64_t>::AppendSetValueToWriter(MessageWriter* writer) { 423 writer->AppendVariantOfInt64(set_value_); 424 } 425 426 // 427 // Property<uint64_t> specialization. 428 // 429 430 template <> 431 Property<uint64_t>::Property() 432 : value_(0) {} 433 434 template <> 435 bool Property<uint64_t>::PopValueFromReader(MessageReader* reader) { 436 return reader->PopVariantOfUint64(&value_); 437 } 438 439 template <> 440 void Property<uint64_t>::AppendSetValueToWriter(MessageWriter* writer) { 441 writer->AppendVariantOfUint64(set_value_); 442 } 443 444 // 445 // Property<double> specialization. 446 // 447 448 template <> 449 Property<double>::Property() : value_(0.0) { 450 } 451 452 template <> 453 bool Property<double>::PopValueFromReader(MessageReader* reader) { 454 return reader->PopVariantOfDouble(&value_); 455 } 456 457 template <> 458 void Property<double>::AppendSetValueToWriter(MessageWriter* writer) { 459 writer->AppendVariantOfDouble(set_value_); 460 } 461 462 // 463 // Property<std::string> specialization. 464 // 465 466 template <> 467 bool Property<std::string>::PopValueFromReader(MessageReader* reader) { 468 return reader->PopVariantOfString(&value_); 469 } 470 471 template <> 472 void Property<std::string>::AppendSetValueToWriter(MessageWriter* writer) { 473 writer->AppendVariantOfString(set_value_); 474 } 475 476 // 477 // Property<ObjectPath> specialization. 478 // 479 480 template <> 481 bool Property<ObjectPath>::PopValueFromReader(MessageReader* reader) { 482 return reader->PopVariantOfObjectPath(&value_); 483 } 484 485 template <> 486 void Property<ObjectPath>::AppendSetValueToWriter(MessageWriter* writer) { 487 writer->AppendVariantOfObjectPath(set_value_); 488 } 489 490 // 491 // Property<std::vector<std::string>> specialization. 492 // 493 494 template <> 495 bool Property<std::vector<std::string>>::PopValueFromReader( 496 MessageReader* reader) { 497 MessageReader variant_reader(nullptr); 498 if (!reader->PopVariant(&variant_reader)) 499 return false; 500 501 value_.clear(); 502 return variant_reader.PopArrayOfStrings(&value_); 503 } 504 505 template <> 506 void Property<std::vector<std::string>>::AppendSetValueToWriter( 507 MessageWriter* writer) { 508 MessageWriter variant_writer(nullptr); 509 writer->OpenVariant("as", &variant_writer); 510 variant_writer.AppendArrayOfStrings(set_value_); 511 writer->CloseContainer(&variant_writer); 512 } 513 514 // 515 // Property<std::vector<ObjectPath>> specialization. 516 // 517 518 template <> 519 bool Property<std::vector<ObjectPath>>::PopValueFromReader( 520 MessageReader* reader) { 521 MessageReader variant_reader(nullptr); 522 if (!reader->PopVariant(&variant_reader)) 523 return false; 524 525 value_.clear(); 526 return variant_reader.PopArrayOfObjectPaths(&value_); 527 } 528 529 template <> 530 void Property<std::vector<ObjectPath>>::AppendSetValueToWriter( 531 MessageWriter* writer) { 532 MessageWriter variant_writer(nullptr); 533 writer->OpenVariant("ao", &variant_writer); 534 variant_writer.AppendArrayOfObjectPaths(set_value_); 535 writer->CloseContainer(&variant_writer); 536 } 537 538 // 539 // Property<std::vector<uint8_t>> specialization. 540 // 541 542 template <> 543 bool Property<std::vector<uint8_t>>::PopValueFromReader(MessageReader* reader) { 544 MessageReader variant_reader(nullptr); 545 if (!reader->PopVariant(&variant_reader)) 546 return false; 547 548 value_.clear(); 549 const uint8_t* bytes = nullptr; 550 size_t length = 0; 551 if (!variant_reader.PopArrayOfBytes(&bytes, &length)) 552 return false; 553 value_.assign(bytes, bytes + length); 554 return true; 555 } 556 557 template <> 558 void Property<std::vector<uint8_t>>::AppendSetValueToWriter( 559 MessageWriter* writer) { 560 MessageWriter variant_writer(nullptr); 561 writer->OpenVariant("ay", &variant_writer); 562 variant_writer.AppendArrayOfBytes(set_value_.data(), set_value_.size()); 563 writer->CloseContainer(&variant_writer); 564 } 565 566 // 567 // Property<std::map<std::string, std::string>> specialization. 568 // 569 570 template <> 571 bool Property<std::map<std::string, std::string>>::PopValueFromReader( 572 MessageReader* reader) { 573 MessageReader variant_reader(nullptr); 574 MessageReader array_reader(nullptr); 575 if (!reader->PopVariant(&variant_reader) || 576 !variant_reader.PopArray(&array_reader)) 577 return false; 578 value_.clear(); 579 while (array_reader.HasMoreData()) { 580 dbus::MessageReader dict_entry_reader(nullptr); 581 if (!array_reader.PopDictEntry(&dict_entry_reader)) 582 return false; 583 std::string key; 584 std::string value; 585 if (!dict_entry_reader.PopString(&key) || 586 !dict_entry_reader.PopString(&value)) 587 return false; 588 value_[key] = value; 589 } 590 return true; 591 } 592 593 template <> 594 void Property<std::map<std::string, std::string>>::AppendSetValueToWriter( 595 MessageWriter* writer) { 596 MessageWriter variant_writer(nullptr); 597 MessageWriter dict_writer(nullptr); 598 writer->OpenVariant("a{ss}", &variant_writer); 599 variant_writer.OpenArray("{ss}", &dict_writer); 600 for (const auto& pair : set_value_) { 601 dbus::MessageWriter entry_writer(nullptr); 602 dict_writer.OpenDictEntry(&entry_writer); 603 entry_writer.AppendString(pair.first); 604 entry_writer.AppendString(pair.second); 605 dict_writer.CloseContainer(&entry_writer); 606 } 607 variant_writer.CloseContainer(&dict_writer); 608 writer->CloseContainer(&variant_writer); 609 } 610 611 // 612 // Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>> 613 // specialization. 614 // 615 616 template <> 617 bool Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>:: 618 PopValueFromReader(MessageReader* reader) { 619 MessageReader variant_reader(nullptr); 620 MessageReader array_reader(nullptr); 621 if (!reader->PopVariant(&variant_reader) || 622 !variant_reader.PopArray(&array_reader)) 623 return false; 624 625 value_.clear(); 626 while (array_reader.HasMoreData()) { 627 dbus::MessageReader struct_reader(nullptr); 628 if (!array_reader.PopStruct(&struct_reader)) 629 return false; 630 631 std::pair<std::vector<uint8_t>, uint16_t> entry; 632 const uint8_t* bytes = nullptr; 633 size_t length = 0; 634 if (!struct_reader.PopArrayOfBytes(&bytes, &length)) 635 return false; 636 entry.first.assign(bytes, bytes + length); 637 if (!struct_reader.PopUint16(&entry.second)) 638 return false; 639 value_.push_back(entry); 640 } 641 return true; 642 } 643 644 template <> 645 void Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>:: 646 AppendSetValueToWriter(MessageWriter* writer) { 647 MessageWriter variant_writer(nullptr); 648 MessageWriter array_writer(nullptr); 649 writer->OpenVariant("a(ayq)", &variant_writer); 650 variant_writer.OpenArray("(ayq)", &array_writer); 651 for (const auto& pair : set_value_) { 652 dbus::MessageWriter struct_writer(nullptr); 653 array_writer.OpenStruct(&struct_writer); 654 struct_writer.AppendArrayOfBytes(std::get<0>(pair).data(), 655 std::get<0>(pair).size()); 656 struct_writer.AppendUint16(std::get<1>(pair)); 657 array_writer.CloseContainer(&struct_writer); 658 } 659 variant_writer.CloseContainer(&array_writer); 660 writer->CloseContainer(&variant_writer); 661 } 662 663 // 664 // Property<std::map<std::string, std::vector<uint8_t>>> 665 // specialization. 666 // 667 668 template <> 669 bool Property<std::map<std::string, std::vector<uint8_t>>>::PopValueFromReader( 670 MessageReader* reader) { 671 MessageReader variant_reader(nullptr); 672 MessageReader dict_reader(nullptr); 673 if (!reader->PopVariant(&variant_reader) || 674 !variant_reader.PopArray(&dict_reader)) 675 return false; 676 677 value_.clear(); 678 while (dict_reader.HasMoreData()) { 679 MessageReader entry_reader(nullptr); 680 if (!dict_reader.PopDictEntry(&entry_reader)) 681 return false; 682 683 std::string key; 684 MessageReader value_varient_reader(nullptr); 685 if (!entry_reader.PopString(&key) || 686 !entry_reader.PopVariant(&value_varient_reader)) 687 return false; 688 689 const uint8_t* bytes = nullptr; 690 size_t length = 0; 691 if (!value_varient_reader.PopArrayOfBytes(&bytes, &length)) 692 return false; 693 694 value_[key].assign(bytes, bytes + length); 695 } 696 return true; 697 } 698 699 template <> 700 void Property<std::map<std::string, std::vector<uint8_t>>>:: 701 AppendSetValueToWriter(MessageWriter* writer) { 702 MessageWriter variant_writer(nullptr); 703 MessageWriter dict_writer(nullptr); 704 705 writer->OpenVariant("a{sv}", &variant_writer); 706 variant_writer.OpenArray("{sv}", &dict_writer); 707 708 for (const auto& pair : set_value_) { 709 MessageWriter entry_writer(nullptr); 710 dict_writer.OpenDictEntry(&entry_writer); 711 712 entry_writer.AppendString(pair.first); 713 714 MessageWriter value_varient_writer(nullptr); 715 entry_writer.OpenVariant("ay", &value_varient_writer); 716 value_varient_writer.AppendArrayOfBytes(pair.second.data(), 717 pair.second.size()); 718 entry_writer.CloseContainer(&value_varient_writer); 719 720 dict_writer.CloseContainer(&entry_writer); 721 } 722 723 variant_writer.CloseContainer(&dict_writer); 724 writer->CloseContainer(&variant_writer); 725 } 726 727 // 728 // Property<std::map<uint16_t, std::vector<uint8_t>>> 729 // specialization. 730 // 731 732 template <> 733 bool Property<std::map<uint16_t, std::vector<uint8_t>>>::PopValueFromReader( 734 MessageReader* reader) { 735 MessageReader variant_reader(nullptr); 736 MessageReader dict_reader(nullptr); 737 if (!reader->PopVariant(&variant_reader) || 738 !variant_reader.PopArray(&dict_reader)) 739 return false; 740 741 value_.clear(); 742 while (dict_reader.HasMoreData()) { 743 MessageReader entry_reader(nullptr); 744 if (!dict_reader.PopDictEntry(&entry_reader)) 745 return false; 746 747 uint16_t key; 748 MessageReader value_varient_reader(nullptr); 749 if (!entry_reader.PopUint16(&key) || 750 !entry_reader.PopVariant(&value_varient_reader)) 751 return false; 752 753 const uint8_t* bytes = nullptr; 754 size_t length = 0; 755 if (!value_varient_reader.PopArrayOfBytes(&bytes, &length)) 756 return false; 757 758 value_[key].assign(bytes, bytes + length); 759 } 760 return true; 761 } 762 763 template <> 764 void Property<std::map<uint16_t, std::vector<uint8_t>>>::AppendSetValueToWriter( 765 MessageWriter* writer) { 766 MessageWriter variant_writer(nullptr); 767 MessageWriter dict_writer(nullptr); 768 769 writer->OpenVariant("a{qv}", &variant_writer); 770 variant_writer.OpenArray("{qv}", &dict_writer); 771 772 for (const auto& pair : set_value_) { 773 MessageWriter entry_writer(nullptr); 774 dict_writer.OpenDictEntry(&entry_writer); 775 776 entry_writer.AppendUint16(pair.first); 777 778 MessageWriter value_varient_writer(nullptr); 779 entry_writer.OpenVariant("ay", &value_varient_writer); 780 value_varient_writer.AppendArrayOfBytes(pair.second.data(), 781 pair.second.size()); 782 entry_writer.CloseContainer(&value_varient_writer); 783 784 dict_writer.CloseContainer(&entry_writer); 785 } 786 787 variant_writer.CloseContainer(&dict_writer); 788 writer->CloseContainer(&variant_writer); 789 } 790 791 template class Property<uint8_t>; 792 template class Property<bool>; 793 template class Property<int16_t>; 794 template class Property<uint16_t>; 795 template class Property<int32_t>; 796 template class Property<uint32_t>; 797 template class Property<int64_t>; 798 template class Property<uint64_t>; 799 template class Property<double>; 800 template class Property<std::string>; 801 template class Property<ObjectPath>; 802 template class Property<std::vector<std::string>>; 803 template class Property<std::vector<ObjectPath>>; 804 template class Property<std::vector<uint8_t>>; 805 template class Property<std::map<std::string, std::string>>; 806 template class Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>; 807 template class Property<std::map<std::string, std::vector<uint8_t>>>; 808 template class Property<std::map<uint16_t, std::vector<uint8_t>>>; 809 810 } // namespace dbus 811