Skyward boardcore
Loading...
Searching...
No Matches
RegistrySerializer.cpp
Go to the documentation of this file.
1/* Copyright (c) 2023 Skyward Experimental Rocketry
2 * Author: Nicolò Caruso
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#include "RegistrySerializer.h"
24
25#include <functional>
26#include <numeric>
27
28namespace Boardcore
29{
30RegistrySerializer::RegistrySerializer(std::vector<uint8_t>& vector)
31 : serializationVector(vector), vectorWritePosition(0)
32{
33}
34
36 RegistryConfiguration& configuration)
37{
39 bool success = true;
40
41 // Resizes the serialization vector
42 serializationVector.resize(size(configuration));
43
44 // Write the header
45 RegistryHeader header;
46 header.startBytes = 1;
47 header.totalSize = serializationVector.size();
48 header.nrEntries = configuration.size();
49 error = serialize(header);
50 if (error != RegistryError::OK)
52
53 // Add the configuration entries one after the other
54 for (auto& entry : configuration)
55 {
56 TypesEnum type;
57 // Appends the entry ID
58 success &= (serialize(entry.first) == RegistryError::OK);
59 // Appends the configuration entry
60 type = entry.second.getType();
61 success &= (serialize(type) == RegistryError::OK);
62 if (!success)
64
65 switch (entry.second.getType())
66 {
68 {
69 Coordinates coordinate{0, 0};
70 entry.second.get(coordinate);
71 success &= (serialize(coordinate) == RegistryError::OK);
72 break;
73 }
74
76 {
77 uint32_t uint32Value = 0;
78 entry.second.get(uint32Value);
79 success &= (serialize(uint32Value) == RegistryError::OK);
80 break;
81 }
82
84 {
85 float floatValue = 0;
86 entry.second.get(floatValue);
87 success &= (serialize(floatValue) == RegistryError::OK);
88 break;
89 }
90
91 default:
93 break;
94 }
95 if (!success)
97 }
98
99 // Compute the Footer and write it
100 RegistryFooter footer;
101 footer.checksum = computeChecksum();
102
103 // Add the footer to the serialized data
104 return serialize(footer);
105}
106
108 RegistryConfiguration& configuration)
109{
110 bool success = true;
111
112 // Case the vector is empty/not have even the vector size
113 if (serializationVector.size() <
114 sizeof(RegistryHeader) + sizeof(RegistryFooter))
115 {
117 }
118
119 RegistryHeader header;
120 success &= (deserialize(header) == RegistryError::OK);
121 if (!success)
123
124 if (header.startBytes != 1)
126
127 // Save the current vector position before jumping to the footer
128 uint32_t previousPos = vectorWritePosition;
129 vectorWritePosition = header.totalSize - sizeof(RegistryFooter);
130 RegistryFooter footer;
131 success &= (deserialize(footer) == RegistryError::OK);
132 if (!success)
134 // Restore vector position
135 vectorWritePosition = previousPos;
136
137 uint32_t savedChecksum = computeChecksum();
138 if (footer.checksum != savedChecksum)
140
141 // Set the configuration from the saved configuration
142 uint32_t counter = 0;
143
144 while (vectorWritePosition < serializationVector.size() - sizeof(footer) &&
145 counter < header.nrEntries)
146 {
147 ConfigurationId id = 0;
148 TypesEnum typeId;
149 // Gets the ID of the entry, the ID of the data type, the value
150 success &= (deserialize(id) == RegistryError::OK);
151 success &= (deserialize(typeId) == RegistryError::OK);
152 if (!success)
154
155 switch (typeId)
156 {
158 {
159 Coordinates coordinate{0, 0};
160 success &= (deserialize(coordinate) == RegistryError::OK);
161 if (!success)
163 EntryStructsUnion entry = EntryStructsUnion::make(coordinate);
164 auto insert = configuration.insert({id, entry});
165 if (!insert.second)
166 insert.first->second = entry;
167 break;
168 }
169 case TypesEnum::FLOAT:
170 {
171 float floatValue = 0;
172 success &= (deserialize(floatValue) == RegistryError::OK);
173 if (!success)
175 EntryStructsUnion entry = EntryStructsUnion::make(floatValue);
176 auto insert = configuration.insert({id, entry});
177 if (!insert.second)
178 insert.first->second = entry;
179 break;
180 }
182 {
183 uint32_t uint32Value = 0;
184 success &= (deserialize(uint32Value) == RegistryError::OK);
185 if (!success)
187 EntryStructsUnion entry = EntryStructsUnion::make(uint32Value);
188 auto insert = configuration.insert({id, entry});
189 if (!insert.second)
190 insert.first->second = entry;
191 break;
192 }
193 default:
194 {
196 }
197 }
198
199 counter++;
200 }
201
202 return RegistryError::OK;
203}
204
205uint32_t RegistrySerializer::computeChecksum()
206{
207 uint32_t counter = 0;
208 return std::accumulate(
209 serializationVector.begin() + sizeof(RegistryHeader),
210 serializationVector.end() - sizeof(RegistryFooter), 0,
211 [&counter](uint32_t acc, uint8_t element)
212 {
213 acc ^= static_cast<uint32_t>(element >> (3 - (counter % 4)) * 8);
214 counter++;
215 return acc;
216 });
217}
218
219size_t RegistrySerializer::size(RegistryConfiguration& configuration)
220{
221 size_t totalSize = sizeof(RegistryHeader) + sizeof(RegistryFooter);
222
223 // Compute the overall space required for the configurations
224 for (auto& entry : configuration)
225 {
226 totalSize += sizeof(entry.first);
227 totalSize += entry.second.sizeBytes();
228 }
229 return totalSize;
230}
231
232} // namespace Boardcore
RegistryError deserializeConfiguration(RegistryConfiguration &configuration)
De-serializes the data from a serialized vector into the configuration map. In case of malformed seri...
RegistrySerializer(std::vector< uint8_t > &vector)
Construct a new Registry Serializer object.
RegistryError serializeConfiguration(RegistryConfiguration &configuration)
Serializes the configuration map into the uint8_t vector for serialized data.
This file includes all the types the logdecoder script will decode.
uint32_t ConfigurationId
std::unordered_map< ConfigurationId, EntryStructsUnion > RegistryConfiguration
RegistryError
RegistryError enumeration as return type.
@ CHECKSUM_FAIL
The custom checksum check fails.
@ NO_SPACE_FOR_HEADER
There is not enough space to write the header.
@ NO_SUCH_TYPE
There is no such type in TypeEnum.
@ MALFORMED_SERIALIZED_DATA
Malformed data while deserializing.
@ WRONG_ENDIANESS
The endianess not corresponds.
@ OK
Correct condition.
@ WRONG_WRITES_SIZE
Cannot write due to wrong data size.
Coordinates struct with latitude [degree], longitude [degree].
Union data struct to be stored in the map. It does contain the enumeration index and the value of suc...
static EntryStructsUnion make(float value)
Set the Union object with its float value.
Serialization header, with useful information about the serialized data. Header to the actually seria...
uint32_t totalSize
Total size of serialized data in bytes.
uint64_t startBytes
Bytes at start, initialized as 1.
uint32_t nrEntries
Nr of configuration entries.