Skip to content

Commit 2f1b3d8

Browse files
committed
Refactor serialize/deserialize
1 parent 100db87 commit 2f1b3d8

9 files changed

Lines changed: 502 additions & 358 deletions

File tree

src/include/sndx/audio/wav.hpp

Lines changed: 141 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,30 @@ namespace sndx::audio {
2121
static constexpr std::array<char, 4> ID = { 'f', 'm', 't', ' ' };
2222

2323
struct ExtendedNone {
24-
static void deserialize(const serialize::Deserializer&) {};
25-
static void serialize(const serialize::Serializer&) {};
24+
template <class DeserializeIt>
25+
static constexpr void deserialize(DeserializeIt&, DeserializeIt) {};
26+
27+
template <class SerializeIt>
28+
static constexpr void serialize(SerializeIt&) {};
2629

2730
static constexpr uint32_t size() noexcept {
2831
return 0 + 16;
2932
}
3033
};
3134

3235
struct Extended0 {
33-
static void deserialize(serialize::Deserializer& deserializer) {
36+
template <class DeserializeIt>
37+
static constexpr void deserialize(DeserializeIt& in, DeserializeIt end) {
3438
uint16_t size;
35-
deserializer.deserialize<std::endian::little>(size);
39+
deserializeFromAdjust(size, in, end);
3640

3741
if (size != 0)
3842
throw deserialize_error("Extended0 didn't have size 0");
3943
};
4044

41-
static void serialize(serialize::Serializer& serializer) noexcept {
42-
serializer.serialize<std::endian::little>(static_cast<uint16_t>(0));
45+
template <class SerializeIt>
46+
static constexpr void serialize(SerializeIt& out) noexcept {
47+
serializeToAdjust(out, static_cast<uint16_t>(0));
4348
};
4449

4550
static constexpr uint32_t size() noexcept {
@@ -50,28 +55,30 @@ namespace sndx::audio {
5055
struct Extended {
5156
uint16_t validBitsPerSample = 0;
5257
uint32_t channelMask = 0;
53-
char guid[16] = { 0 };
58+
std::array<char, 16> guid{ 0 };
5459

5560
static constexpr uint16_t dataSize = sizeof(validBitsPerSample) + sizeof(channelMask) + sizeof(guid);
5661

57-
void deserialize(serialize::Deserializer& deserializer) {
62+
template <class DeserializeIt>
63+
constexpr void deserialize(DeserializeIt& in, DeserializeIt end) {
5864
uint16_t size;
59-
deserializer.deserialize<std::endian::little>(size);
65+
deserializeFromAdjust(size, in, end);
6066

6167
if (size != dataSize)
6268
throw deserialize_error("Extended format didn't have size 22");
6369

64-
deserializer.deserialize<std::endian::little>(validBitsPerSample);
65-
deserializer.deserialize<std::endian::little>(channelMask);
66-
deserializer.deserialize(guid, sizeof(guid));
70+
deserializeFromAdjust(validBitsPerSample, in, end);
71+
deserializeFromAdjust(channelMask, in, end);
72+
deserializeFromAdjust(guid, in, end);
6773
};
6874

69-
void serialize(serialize::Serializer& serializer) const {
70-
serializer.serialize<std::endian::little>(dataSize);
75+
template <class SerializeIt>
76+
void serialize(SerializeIt& out) const {
77+
serializeToAdjust(out, dataSize);
7178

72-
serializer.serialize<std::endian::little>(validBitsPerSample);
73-
serializer.serialize<std::endian::little>(channelMask);
74-
serializer.serialize(guid, sizeof(guid));
79+
serializeToAdjust(out, validBitsPerSample);
80+
serializeToAdjust(out, channelMask);
81+
serializeToAdjust(out, guid);
7582
};
7683

7784
static constexpr uint32_t size() noexcept {
@@ -102,7 +109,7 @@ namespace sndx::audio {
102109
ext = Extended();
103110
break;
104111
default:
105-
throw deserialize_error("Invalid fmt size");
112+
throw bad_field_error("Invalid fmt size");
106113
}
107114
}
108115

@@ -111,36 +118,42 @@ namespace sndx::audio {
111118
return blockAlign / channels;
112119
}
113120

114-
void deserialize(serialize::Deserializer& deserializer) override {
115-
deserializer.deserialize<std::endian::little>(format);
116-
deserializer.deserialize<std::endian::little>(channels);
117-
deserializer.deserialize<std::endian::little>(sampleRate);
118-
deserializer.deserialize<std::endian::little>(byteRate);
119-
deserializer.deserialize<std::endian::little>(blockAlign);
120-
deserializer.deserialize<std::endian::little>(bitDepth);
121+
void deserialize(const std::vector<uint8_t>& in) override {
122+
auto it = in.begin();
123+
deserializeFromAdjust(format, it, in.end());
124+
deserializeFromAdjust(channels, it, in.end());
125+
deserializeFromAdjust(sampleRate, it, in.end());
126+
deserializeFromAdjust(byteRate, it, in.end());
127+
deserializeFromAdjust(blockAlign, it, in.end());
128+
deserializeFromAdjust(bitDepth, it, in.end());
121129

122-
std::visit([&deserializer]<typename T>(T&& arg) {
123-
deserializer.deserialize(std::forward<T>(arg));
130+
std::visit([&it, end = in.end()]<typename T>(T&& arg) {
131+
deserializeFromAdjust(std::forward<T>(arg), it, end);
124132
}, ext);
125133
};
126134

127-
void serialize(serialize::Serializer& serializer) const override {
128-
serializer.serialize("fmt ", 4);
135+
std::vector<uint8_t> serialize() const override {
136+
std::vector<uint8_t> out{};
137+
auto it = std::back_inserter(out);
138+
139+
serializeToAdjust(it, std::array{ 'f', 'm', 't', ' ' });
129140

130-
std::visit([&serializer]<typename T>(const T&) {
131-
serializer.serialize<std::endian::little>(static_cast<uint32_t>(T::size()));
141+
std::visit([&it]<typename T>(const T&) {
142+
serializeToAdjust(it, static_cast<uint32_t>(T::size()));
132143
}, ext);
133144

134-
serializer.serialize<std::endian::little>(format);
135-
serializer.serialize<std::endian::little>(channels);
136-
serializer.serialize<std::endian::little>(sampleRate);
137-
serializer.serialize<std::endian::little>(byteRate);
138-
serializer.serialize<std::endian::little>(blockAlign);
139-
serializer.serialize<std::endian::little>(bitDepth);
140-
141-
std::visit([&serializer]<typename T>(T&& arg) {
142-
serializer.serialize(std::forward<T>(arg));
145+
serializeToAdjust(it, format);
146+
serializeToAdjust(it, channels);
147+
serializeToAdjust(it, sampleRate);
148+
serializeToAdjust(it, byteRate);
149+
serializeToAdjust(it, blockAlign);
150+
serializeToAdjust(it, bitDepth);
151+
152+
std::visit([&it]<typename T>(T&& arg) {
153+
serializeToAdjust(it, arg);
143154
}, ext);
155+
156+
return out;
144157
};
145158

146159
[[nodiscard]]
@@ -180,15 +193,19 @@ namespace sndx::audio {
180193

181194
explicit constexpr FACTchunk(const RIFF::ChunkHeader&) noexcept {};
182195

183-
void deserialize(serialize::Deserializer& deserializer) override {
184-
deserializer.deserialize<std::endian::little>(sampleLength);
196+
void deserialize(const std::vector<uint8_t>& data) override {
197+
sndx::deserialize(sampleLength, data);
185198
}
186199

187-
void serialize(serialize::Serializer& serializer) const override {
188-
serializer.serialize("fact", 4);
189-
serializer.serialize<std::endian::little>(static_cast<uint32_t>(sizeof(sampleLength)));
200+
std::vector<uint8_t> serialize() const override {
201+
std::vector<uint8_t> out{};
202+
auto it = std::back_inserter(out);
203+
204+
serializeToAdjust(it, std::array{ 'f', 'a', 'c', 't' });
205+
serializeToAdjust(it, static_cast<uint32_t>(sizeof(sampleLength)));
206+
serializeToAdjust(it, sampleLength);
190207

191-
serializer.serialize<std::endian::little>(sampleLength);
208+
return out;
192209
}
193210

194211
[[nodiscard]]
@@ -208,25 +225,29 @@ namespace sndx::audio {
208225
data.resize(header.size);
209226
}
210227

211-
void deserialize(serialize::Deserializer& deserializer) override {
212-
deserializer.deserialize(data.data(), data.size());
213-
214-
uint8_t padding = 0;
215-
if (data.size() % 2 == 1)
216-
deserializer.deserialize(padding);
228+
void deserialize(const std::vector<uint8_t>& data) override {
229+
auto it = data.begin();
230+
for (auto& b : this->data) {
231+
deserializeFromAdjust(b, it, data.end());
232+
}
217233
}
218234

219-
void serialize(serialize::Serializer& serializer) const override {
220-
serializer.serialize("data", 4);
221-
serializer.serialize<std::endian::little>(static_cast<uint32_t>(data.size()));
235+
std::vector<uint8_t> serialize() const override {
236+
std::vector<uint8_t> out{};
237+
auto it = std::back_inserter(out);
238+
239+
serializeToAdjust(it, std::array{ 'd', 'a', 't', 'a' });
240+
serializeToAdjust(it, static_cast<uint32_t>(data.size()));
222241

223242
for (const auto& b : data) {
224-
serializer.serialize(b);
243+
serializeToAdjust(it, b);
225244
}
226245

227246
if (data.size() % 2 == 1) {
228-
serializer.serialize(static_cast<uint8_t>(0));
247+
serializeToAdjust(it, static_cast<uint8_t>(0));
229248
}
249+
250+
return out;
230251
}
231252

232253
[[nodiscard]]
@@ -307,20 +328,25 @@ namespace sndx::audio {
307328
return *m_fmt;
308329
}
309330

310-
void deserialize(serialize::Deserializer& deserializer) {
311-
m_file.deserialize(deserializer, ID);
331+
template <class InputIt>
332+
void deserialize(InputIt& in, InputIt end) {
333+
deserializeFromAdjust(m_file, in, end);
334+
335+
if (m_file.getHeader().type != ID)
336+
throw bad_field_error("WAVE file missing WAVE");
312337

313338
m_fmt = m_file.getChunk<FMTchunk>();
314339
m_data = m_file.getChunk<DATAchunk>();
315340

316341
if (!m_fmt || !m_data)
317-
throw deserialize_error("WAVE file missing fmt or data");
342+
throw bad_field_error("WAVE file missing fmt or data");
318343
}
319344

320-
void serialize(serialize::Serializer& serializer) const {
345+
template <class SerializeIt>
346+
void serialize(SerializeIt& it) const {
321347

322348
if (!m_fmt || !m_data)
323-
throw serialize_error("WAVE file missing fmt or data");
349+
throw std::logic_error("WAVE file missing fmt or data");
324350

325351
auto tmp = m_file.getHeader();
326352
const auto& chunks = m_file.getChunks();
@@ -330,8 +356,12 @@ namespace sndx::audio {
330356
tmp.size += chunk->getLength();
331357
}
332358

333-
serializer.serialize(tmp);
334-
serializer.serialize(*m_fmt);
359+
serializeToAdjust(it, tmp);
360+
361+
auto buf = m_fmt->serialize();
362+
for (auto b : buf) {
363+
serializeToAdjust(it, b);
364+
}
335365

336366
for (const auto& [id, chunk] : chunks) {
337367
if (id == RIFF::idToRawID(FMTchunk::ID) ||
@@ -340,10 +370,16 @@ namespace sndx::audio {
340370
continue;
341371
}
342372

343-
serializer.serialize(*chunk);
373+
buf = chunk->serialize();
374+
for (auto b : buf) {
375+
serializeToAdjust(it, b);
376+
}
344377
}
345378

346-
serializer.serialize(*m_data);
379+
buf = m_fmt->serialize();
380+
for (auto b : buf) {
381+
serializeToAdjust(it, b);
382+
}
347383
}
348384
};
349385

@@ -362,36 +398,39 @@ namespace sndx::audio {
362398
explicit WAVdecoder(std::istream& stream) :
363399
m_stream(stream.rdbuf()) {
364400

365-
serialize::Deserializer deserializer{ stream };
366-
bool seekable = true;
401+
auto it = std::istream_iterator<uint8_t>(stream);
402+
auto end = std::istream_iterator<uint8_t>();
367403

368404
RIFF::RIFFheader head;
369-
deserializer.deserialize(head);
405+
deserializeFromAdjust(head, it, end);
370406

371407
if (head.type != std::array<char, 4>{'W', 'A', 'V', 'E'})
372-
throw identifier_error("RIFF file is not WAVE");
408+
throw bad_field_error("RIFF file is not WAVE");
373409

374410
RIFF::ChunkHeader header;
375-
deserializer.deserialize(header);
411+
deserializeFromAdjust(header, it, end);
376412

377413

378414
if (header.id != std::array<char, 4>{'f', 'm', 't', ' '})
379-
throw identifier_error("fmt not first subchunk in RIFF");
415+
throw bad_field_error("fmt not first subchunk in RIFF");
380416

381417
m_meta = FMTchunk(header);
382-
deserializer.deserialize(m_meta);
418+
std::vector<uint8_t> buf{};
419+
buf.resize(m_meta.getLength() - 4 - sizeof(uint32_t));
420+
for (auto& b : buf) {
421+
deserializeFromAdjust(b, it, end);
422+
}
423+
m_meta.deserialize(buf);
383424

384425
do {
385-
deserializer.deserialize(header);
426+
deserializeFromAdjust(header, it, end);
386427

387428
m_size = header.size;
388429

389430
if (header.id == std::array<char, 4>{'d', 'a', 't', 'a'}) {
390431
m_offset = size_t(m_stream.tellg());
391432
return;
392433
}
393-
394-
seekable = deserializer.discard(header.size, seekable);
395434
} while (m_stream.good());
396435

397436
throw deserialize_error("Invalid .wav file");
@@ -553,4 +592,30 @@ namespace sndx::audio {
553592
registerDecoder<WAVdecoder>(".wav") &&
554593
registerDecoder<WAVdecoder>(".wave");
555594
}();
595+
}
596+
597+
namespace sndx {
598+
template<class T>
599+
requires
600+
std::is_same_v<T, audio::FMTchunk::ExtendedNone> ||
601+
std::is_same_v<T, audio::FMTchunk::Extended0> ||
602+
std::is_same_v<T, audio::FMTchunk::Extended>
603+
struct Serializer<T> {
604+
template <class SerializeIt>
605+
constexpr void serialize(const T& v, SerializeIt& it) const {
606+
v.serialize(it);
607+
}
608+
};
609+
610+
template<class T>
611+
requires
612+
std::is_same_v<T, audio::FMTchunk::ExtendedNone> ||
613+
std::is_same_v<T, audio::FMTchunk::Extended0> ||
614+
std::is_same_v<T, audio::FMTchunk::Extended>
615+
struct Deserializer<T> {
616+
template <class DeserializeIt>
617+
constexpr void deserialize(T& to, DeserializeIt& in, DeserializeIt end) const {
618+
to.deserialize(in, end);
619+
}
620+
};
556621
}

0 commit comments

Comments
 (0)