Bond
 
Loading...
Searching...
No Matches
merge.h
1// Copyright (c) Microsoft. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
4#pragma once
5
6#include <bond/core/config.h>
7
8#include "detail/omit_default.h"
9#include "detail/tags.h"
10#include "exception.h"
11#include "reflection.h"
12#include "transforms.h"
13
14
15namespace bond
16{
17
18
19template <typename T, typename Writer, typename Protocols = BuiltInProtocols>
20class Merger
21 : public Serializer<Writer, Protocols>
22{
23public:
24 typedef T FastPathType;
25
26 using Serializer<Writer, Protocols>::Base;
27 using Serializer<Writer, Protocols>::Field;
28 using Serializer<Writer, Protocols>::Write;
29 using Serializer<Writer, Protocols>::OmittedField;
30 using Serializer<Writer, Protocols>::Container;
31
32 Merger(const T& var, Writer& output, bool base = false)
33 : Serializer<Writer, Protocols>(output, base),
34 _var(var)
35 {}
36
37 template <typename Pass0>
38 Merger<T, Pass0, Protocols> Rebind(Pass0& pass0) const
39 {
40 return Merger<T, Pass0, Protocols>(_var, pass0);
41 }
42
43 template <typename X, typename Reader>
44 typename boost::enable_if<has_schema<X>, bool>::type
45 Base(const bonded<X, Reader>& value) const
46 {
47 return Apply<Protocols>(Merger<typename schema<T>::type::base, Writer, Protocols>(_var, _output, true), value);
48 }
49
50
51 template <typename FieldT, typename X>
52 typename boost::enable_if_c<is_struct_field<FieldT>::value
53 || is_struct_container_field<FieldT>::value, bool>::type
54 Field(const FieldT&, const X& value) const
55 {
56 _output.WriteFieldBegin(GetTypeId(value), FieldT::id, FieldT::metadata);
57 Merge(FieldT::GetVariable(_var), value);
58 _output.WriteFieldEnd();
59 return false;
60 }
61
62
63 template <typename FieldT, typename X>
64 typename boost::disable_if_c<is_struct_field<FieldT>::value
65 || is_struct_container_field<FieldT>::value, bool>::type
66 Field(const FieldT&, const X&) const
67 {
68 return this->Field(FieldT::id, FieldT::metadata, FieldT::GetVariable(_var));
69 }
70
71
72 template <typename FieldT>
73 bool OmittedField(const FieldT&) const
74 {
75 return this->Field(FieldT::id, FieldT::metadata, FieldT::GetVariable(_var));
76 }
77
78
79 template <typename X, typename Reader>
80 typename boost::enable_if<is_element_matching<value<X, Reader>, T> >::type
81 Container(const value<X, Reader>& element, uint32_t size) const
82 {
83 Merge(_var, element, size);
84 }
85
86
87 template <typename X, typename Reader>
88 typename boost::enable_if<is_element_matching<bonded<X, Reader>, T> >::type
89 Container(const bonded<X, Reader>& element, uint32_t size) const
90 {
91 Merge(_var, element, size);
92 }
93
94
95 template <typename Key, typename X, typename Reader>
96 typename boost::enable_if_c<is_map_element_matching<X, T>::value
97 && is_map_key_matching<Key, T>::value>::type
98 Container(const value<Key, Reader>& key, const X& value, uint32_t size) const
99 {
100 Merge(_var, key, value, size);
101 }
102
103
104protected:
105 using Serializer<Writer, Protocols>::_output;
106
107
108private:
109 template <typename U, typename X>
110 void Merge(const U& var, const X& value) const
111 {
112 Apply<Protocols>(Merger<U, Writer, Protocols>(var, _output), value);
113 }
114
115
116 template <typename U, typename X>
117 void Merge(const U& var, const X& element, uint32_t size) const
118 {
119 if (size != container_size(var))
120 MergerContainerException(size, container_size(var));
121
122 _output.WriteContainerBegin(size, get_type_id<typename element_type<U>::type>::value);
123
124 for (const_enumerator<U> items(var); items.more();)
125 Merge(items.next(), element);
126
127 _output.WriteContainerEnd();
128 }
129
130
131 template <typename U, typename Key, typename X>
132 void Merge(const U& var, const Key& key, const X& value, uint32_t size) const
133 {
134 if (size != container_size(var))
135 MergerContainerException(size, container_size(var));
136
137 _output.WriteContainerBegin(size, get_type_id<typename element_type<U>::type>::value);
138
139 typename element_type<U>::type::first_type k;
140
141 while (size--)
142 {
143 key.template Deserialize<Protocols>(k);
144
145 Write(k);
146
147 // Elements of a map migth be serialized out of order, so we must
148 // look up the element to merge by key.
149 Merge(mapped_at(var, k), value);
150 }
151
152 _output.WriteContainerEnd();
153 }
154
155 const T& _var;
156};
157
158
159} // namespace bond
namespace bond
Definition: apply.h:17
void Merge(const T &obj, Reader input, Writer &output)
Merge an object with serialize data and write the result using a protocol writer.
Definition: bond.h:125