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