Serialization.h
1 #pragma once 2 #include <HardwareSerial.h> 3 #include <SdFat.h> 4 5 #include <iostream> 6 7 namespace serialization { 8 template <typename T> 9 static void writePod(std::ostream& os, const T& value) { 10 os.write(reinterpret_cast<const char*>(&value), sizeof(T)); 11 } 12 13 template <typename T> 14 static void writePod(FsFile& file, const T& value) { 15 file.write(reinterpret_cast<const uint8_t*>(&value), sizeof(T)); 16 } 17 18 template <typename T> 19 static void readPod(std::istream& is, T& value) { 20 is.read(reinterpret_cast<char*>(&value), sizeof(T)); 21 } 22 23 template <typename T> 24 static void readPod(FsFile& file, T& value) { 25 file.read(reinterpret_cast<uint8_t*>(&value), sizeof(T)); 26 } 27 28 template <typename T> 29 [[nodiscard]] static bool readPodChecked(FsFile& file, T& value) { 30 return file.read(reinterpret_cast<uint8_t*>(&value), sizeof(T)) == sizeof(T); 31 } 32 33 static void writeString(std::ostream& os, const std::string& s) { 34 const uint32_t len = s.size(); 35 writePod(os, len); 36 os.write(s.data(), len); 37 } 38 39 static void writeString(FsFile& file, const std::string& s) { 40 const uint32_t len = s.size(); 41 writePod(file, len); 42 file.write(reinterpret_cast<const uint8_t*>(s.data()), len); 43 } 44 45 [[nodiscard]] static bool readString(std::istream& is, std::string& s) { 46 uint32_t len; 47 readPod(is, len); 48 if (!is.good()) { 49 s.clear(); 50 return false; 51 } 52 if (len > 65536) { // Sanity check: no string should be > 64KB 53 s.clear(); 54 is.setstate(std::ios::failbit); 55 return false; 56 } 57 s.resize(len); 58 is.read(&s[0], len); 59 return is.good(); 60 } 61 62 [[nodiscard]] static bool readString(FsFile& file, std::string& s) { 63 uint32_t len; 64 if (file.read(reinterpret_cast<uint8_t*>(&len), sizeof(len)) != sizeof(len)) { 65 s.clear(); 66 return false; 67 } 68 if (len > 65536) { // Sanity check: no string should be > 64KB 69 Serial.printf("[SER] String length %u exceeds max, file corrupt\n", len); 70 s.clear(); 71 return false; 72 } 73 s.resize(len); 74 if (len > 0 && file.read(reinterpret_cast<uint8_t*>(&s[0]), len) != static_cast<int>(len)) { 75 s.clear(); 76 return false; 77 } 78 return true; 79 } 80 81 template <typename T> 82 static void readPodValidated(FsFile& file, T& value, T maxValue) { 83 T temp; 84 file.read(reinterpret_cast<uint8_t*>(&temp), sizeof(T)); 85 if (temp < maxValue) { 86 value = temp; 87 } 88 } 89 } // namespace serialization