1 | // Copyright 2013 The Flutter 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 | #ifndef FLUTTER_FML_MESSAGE_H_ |
6 | #define FLUTTER_FML_MESSAGE_H_ |
7 | |
8 | #include <algorithm> |
9 | #include <cstdint> |
10 | #include <cstring> |
11 | #include <memory> |
12 | #include <type_traits> |
13 | #include <utility> |
14 | |
15 | #include "flutter/fml/compiler_specific.h" |
16 | #include "flutter/fml/macros.h" |
17 | |
18 | namespace fml { |
19 | |
20 | #define FML_SERIALIZE(message, value) \ |
21 | if (!message.Encode(value)) { \ |
22 | return false; \ |
23 | } |
24 | |
25 | #define FML_SERIALIZE_TRAITS(message, value, traits) \ |
26 | if (!message.Encode<traits>(value)) { \ |
27 | return false; \ |
28 | } |
29 | |
30 | #define FML_DESERIALIZE(message, value) \ |
31 | if (!message.Decode(value)) { \ |
32 | return false; \ |
33 | } |
34 | |
35 | #define FML_DESERIALIZE_TRAITS(message, value, traits) \ |
36 | if (!message.Decode<traits>(value)) { \ |
37 | return false; \ |
38 | } |
39 | |
40 | class Message; |
41 | |
42 | class MessageSerializable { |
43 | public: |
44 | virtual ~MessageSerializable() = default; |
45 | |
46 | virtual bool Serialize(Message& message) const = 0; |
47 | |
48 | virtual bool Deserialize(Message& message) = 0; |
49 | |
50 | virtual size_t GetSerializableTag() const; |
51 | }; |
52 | |
53 | // The traits passed to the encode/decode calls that accept traits should be |
54 | // something like the following. |
55 | // |
56 | // class MessageSerializableTraits { |
57 | // static size_t GetSerializableTag(const T&); |
58 | // static std::unique_ptr<T> CreateForSerializableTag(size_t tag); |
59 | // }; |
60 | |
61 | template <class T> |
62 | struct Serializable : public std::integral_constant< |
63 | bool, |
64 | std::is_trivially_copyable<T>::value || |
65 | std::is_base_of<MessageSerializable, T>::value> { |
66 | }; |
67 | |
68 | // Utility class to encode and decode |Serializable| types to and from a buffer. |
69 | // Elements have to be read back into the same order they were written. |
70 | class Message { |
71 | public: |
72 | Message(); |
73 | |
74 | ~Message(); |
75 | |
76 | const uint8_t* GetBuffer() const; |
77 | |
78 | size_t GetBufferSize() const; |
79 | |
80 | size_t GetDataLength() const; |
81 | |
82 | size_t GetSizeRead() const; |
83 | |
84 | void ResetRead(); |
85 | |
86 | // Encoders. |
87 | |
88 | template <typename T, |
89 | typename = std::enable_if_t<std::is_trivially_copyable<T>::value>> |
90 | [[nodiscard]] bool Encode(const T& value) { |
91 | if (auto* buffer = PrepareEncode(sizeof(T))) { |
92 | ::memcpy(buffer, &value, sizeof(T)); |
93 | return true; |
94 | } |
95 | return false; |
96 | } |
97 | |
98 | [[nodiscard]] bool Encode(const MessageSerializable& value) { |
99 | return value.Serialize(*this); |
100 | } |
101 | |
102 | template <typename Traits, |
103 | typename T, |
104 | typename = std::enable_if_t< |
105 | std::is_base_of<MessageSerializable, T>::value>> |
106 | [[nodiscard]] bool Encode(const std::unique_ptr<T>& value) { |
107 | // Encode if null. |
108 | if (!Encode(static_cast<bool>(value))) { |
109 | return false; |
110 | } |
111 | |
112 | if (!value) { |
113 | return true; |
114 | } |
115 | |
116 | // Encode the type. |
117 | if (!Encode(Traits::GetSerializableTag(*value.get()))) { |
118 | return false; |
119 | } |
120 | |
121 | // Encode the value. |
122 | if (!Encode(*value.get())) { |
123 | return false; |
124 | } |
125 | |
126 | return true; |
127 | } |
128 | |
129 | // Decoders. |
130 | |
131 | template <typename T, |
132 | typename = std::enable_if_t<std::is_trivially_copyable<T>::value>> |
133 | [[nodiscard]] bool Decode(T& value) { |
134 | if (auto* buffer = PrepareDecode(sizeof(T))) { |
135 | ::memcpy(&value, buffer, sizeof(T)); |
136 | return true; |
137 | } |
138 | return false; |
139 | } |
140 | |
141 | [[nodiscard]] bool Decode(MessageSerializable& value) { |
142 | return value.Deserialize(*this); |
143 | } |
144 | |
145 | template <typename Traits, |
146 | typename T, |
147 | typename = std::enable_if_t< |
148 | std::is_base_of<MessageSerializable, T>::value>> |
149 | [[nodiscard]] bool Decode(std::unique_ptr<T>& value) { |
150 | // Decode if null. |
151 | bool is_null = false; |
152 | if (!Decode(is_null)) { |
153 | return false; |
154 | } |
155 | |
156 | if (is_null) { |
157 | return true; |
158 | } |
159 | |
160 | // Decode type. |
161 | size_t tag = 0; |
162 | if (!Decode(tag)) { |
163 | return false; |
164 | } |
165 | |
166 | std::unique_ptr<T> new_value = Traits::CreateForSerializableTag(tag); |
167 | if (!new_value) { |
168 | return false; |
169 | } |
170 | |
171 | // Decode value. |
172 | if (!Decode(*new_value.get())) { |
173 | return false; |
174 | } |
175 | |
176 | std::swap(value, new_value); |
177 | |
178 | return true; |
179 | } |
180 | |
181 | private: |
182 | uint8_t* buffer_ = nullptr; |
183 | size_t buffer_length_ = 0; |
184 | size_t data_length_ = 0; |
185 | size_t size_read_ = 0; |
186 | |
187 | [[nodiscard]] bool Reserve(size_t size); |
188 | |
189 | [[nodiscard]] bool Resize(size_t size); |
190 | |
191 | [[nodiscard]] uint8_t* PrepareEncode(size_t size); |
192 | |
193 | [[nodiscard]] uint8_t* PrepareDecode(size_t size); |
194 | |
195 | FML_DISALLOW_COPY_AND_ASSIGN(Message); |
196 | }; |
197 | |
198 | } // namespace fml |
199 | |
200 | #endif // FLUTTER_FML_MESSAGE_H_ |
201 | |