Repository files navigation

🌐 English | Deutsch

ByteSequence

ByteSequence is a single-header library for binary object serialization. ByteSequence implements byte streams into which objects can be pushed and from which objects can be popped. The focus is on generic serialization (using boost::pfr), the recursive decomposition of dynamic containers (std::vector, std::map, ...), and a minimalist syntax.

🧬 Requirements

  • Language standard: C++20
  • Compiler: gcc/g++
  • Platform: Windows

Lib has not been tested in any other way so far

🚀 Setup

  • Clone ByteSequence into the project
  • Obtain the Boost.PFR dependency or have CMake automatically set it up using add_subdirectory and linking it
git clone https://github.com/tr3dh/ByteSequence.git src
# In own CMakeLists.txt
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/src/ByteSequence")
target_link_libraries(... ... ByteSequence)
  • include Header
#include"path/to/ByteSequence.hpp"

🔧 Features

  • Bytestream interactions insert, extract, insertMultiple, extractMultiple, extractMultipleReversed, get<T>()
  • Lazy Syntax operator += / operator -=
  • file-I/O: toFile, fromFile
  • string-I/O: toString, fromString
  • XOR-Encoder : encode(std::string), decode(std::string)

🏗️ Support

  • Trivial copyable objects (non-dynamic)
  • Struct members
  • Members of fully public classes
  • std::vector<T>
  • std::map<Key, Val>
  • std::unordered_map<Key, Val>
  • std::multimap<Key, Val>
  • std::pair<First, Second>
  • std::string
  • const char*, char*, char[N]

🛠️ Usage

The insertMultiple and extractMultipleReversed methods can be used to insert objects into or extract them from the byte stream. This applies to supported (defined serialization) and trivially copyable elements.

ByteSequence bs;
int b, a = 42; double d, c = 3.14;
bs.insertMultiple(a, c);
bs.extractMultipleReversed(b, d);

In addition, struct members and class members of fully public classes can be copied. The attributes are parsed by boost::pfr and inserted recursively.

structWhatever{ std::vector<std::vector<std::vector<int>>> m_intVecs; }
ByteSequence bs;
Whatever b, a; a.m_intVecs = = {{{1,2,3}, {4,5,6}}};
bs += a;
bs -= b;

With the XOR encoder ByteSequences can be encoded and decoded.

ByteSequence bs;
bs.insert(data);
std::string key = "...";
bs.encode(key);
bs.decode(key);

If a data type cannot be serialized using the recursive chaining of trivially copyable or supported dynamic containers, a type-specific serialization can be written. This works with both external and member functions. Serialization of unsupported dynamic containers is also possible. Template-based serializations can be used for this purpose.

// Serialization via member functionsstructA {
voidtoByteSequence(ByteSequence& seq) const {
seq.insertMultiple(...);
}
voidfromByteSequence(ByteSequence& seq) {
seq.extractMultipleReversed(...);
}
};
// Serialization via functionsinlinevoidtoByteSequence(const A& a, ByteSequence& seq) {
seq.insertMultiple(...);
}
inlinevoidfromByteSequence(A& a, ByteSequence& seq) {
seq.extractMultipleReversed(...);
}
// Serialization of a dynamic container, example std::vectortemplate<typename T>
inlinevoidtoByteSequence(const std::vector<T>& member, ByteSequence& seq) {
for (auto it = member.rbegin(); it != member.rend(); ++it) {
seq.insert(*it);
}
seq.insert(member.size());
}
template<typename T>
inlinevoidfromByteSequence(std::vector<T>& member, ByteSequence& seq) {
size_t size = seq.get<size_t>();
member.resize(size);
for (size_t i = 0; i < size; i++) {
member[i] = seq.get<T>();
}
}

Using the file and string I/O functions, byte caches can be written to and read from strings or files.

ByteSequence bs;
bs.insert(data);
bs.toFile("path/to/cache.bin");
ByteSequence cachedBS;
cachedBS.fromFile("path/to/cache.bin");
auto restoredData = cachedBS.get<...>();

📊 Limitations / Notes

  • Raw memcpy is platform-dependent; for cross-platform formats, custom wrappers may need to be implemented
  • boost::pfr only works with public members and may be affected by specific constructors or class declarations
  • Complex types with internal allocation (e.g., sparse matrices) should be explicitly serialized

🤝 Many thanks

I would like to express my special thanks to my supervisor Dr. Hendrik Geisler, who was a great help during the development.

Hendrik Geisler was funded by the European Union (ERC, Gen-TSM, project number 101124463) during the supervision period. However, the views and opinions expressed are solely those of the author(s) and do not necessarily reflect those of the European Union or the European Research Council Executive Agency. Neither the European Union nor the funding authority can be held responsible for them.

📚 Libraries used

I would also like to thank the respective developers and maintainers of the open-source libraries used in the project. These are listed below. The corresponding license texts are stored in the thirdPartyLicenses folder.

LibraryLicense
Boost.PFRBoost Software License 1.0

About

Single‑header library for automatic object serialization into byte streams

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

🌐 English | Deutsch

ByteSequence

ByteSequence is a single-header library for binary object serialization. ByteSequence implements byte streams into which objects can be pushed and from which objects can be popped. The focus is on generic serialization (using boost::pfr), the recursive decomposition of dynamic containers (std::vector, std::map, ...), and a minimalist syntax.

🧬 Requirements

  • Language standard: C++20
  • Compiler: gcc/g++
  • Platform: Windows

Lib has not been tested in any other way so far

🚀 Setup

  • Clone ByteSequence into the project
  • Obtain the Boost.PFR dependency or have CMake automatically set it up using add_subdirectory and linking it
git clone https://github.com/tr3dh/ByteSequence.git src
# In own CMakeLists.txt
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/src/ByteSequence")
target_link_libraries(... ... ByteSequence)
  • include Header
#include"path/to/ByteSequence.hpp"

🔧 Features

  • Bytestream interactions insert, extract, insertMultiple, extractMultiple, extractMultipleReversed, get<T>()
  • Lazy Syntax operator += / operator -=
  • file-I/O: toFile, fromFile
  • string-I/O: toString, fromString
  • XOR-Encoder : encode(std::string), decode(std::string)

🏗️ Support

  • Trivial copyable objects (non-dynamic)
  • Struct members
  • Members of fully public classes
  • std::vector<T>
  • std::map<Key, Val>
  • std::unordered_map<Key, Val>
  • std::multimap<Key, Val>
  • std::pair<First, Second>
  • std::string
  • const char*, char*, char[N]

🛠️ Usage

The insertMultiple and extractMultipleReversed methods can be used to insert objects into or extract them from the byte stream. This applies to supported (defined serialization) and trivially copyable elements.

ByteSequence bs;
int b, a = 42; double d, c = 3.14;
bs.insertMultiple(a, c);
bs.extractMultipleReversed(b, d);

In addition, struct members and class members of fully public classes can be copied. The attributes are parsed by boost::pfr and inserted recursively.

structWhatever{ std::vector<std::vector<std::vector<int>>> m_intVecs; }
ByteSequence bs;
Whatever b, a; a.m_intVecs = = {{{1,2,3}, {4,5,6}}};
bs += a;
bs -= b;

With the XOR encoder ByteSequences can be encoded and decoded.

ByteSequence bs;
bs.insert(data);
std::string key = "...";
bs.encode(key);
bs.decode(key);

If a data type cannot be serialized using the recursive chaining of trivially copyable or supported dynamic containers, a type-specific serialization can be written. This works with both external and member functions. Serialization of unsupported dynamic containers is also possible. Template-based serializations can be used for this purpose.

// Serialization via member functionsstructA {
voidtoByteSequence(ByteSequence& seq) const {
seq.insertMultiple(...);
}
voidfromByteSequence(ByteSequence& seq) {
seq.extractMultipleReversed(...);
}
};
// Serialization via functionsinlinevoidtoByteSequence(const A& a, ByteSequence& seq) {
seq.insertMultiple(...);
}
inlinevoidfromByteSequence(A& a, ByteSequence& seq) {
seq.extractMultipleReversed(...);
}
// Serialization of a dynamic container, example std::vectortemplate<typename T>
inlinevoidtoByteSequence(const std::vector<T>& member, ByteSequence& seq) {
for (auto it = member.rbegin(); it != member.rend(); ++it) {
seq.insert(*it);
}
seq.insert(member.size());
}
template<typename T>
inlinevoidfromByteSequence(std::vector<T>& member, ByteSequence& seq) {
size_t size = seq.get<size_t>();
member.resize(size);
for (size_t i = 0; i < size; i++) {
member[i] = seq.get<T>();
}
}

Using the file and string I/O functions, byte caches can be written to and read from strings or files.

ByteSequence bs;
bs.insert(data);
bs.toFile("path/to/cache.bin");
ByteSequence cachedBS;
cachedBS.fromFile("path/to/cache.bin");
auto restoredData = cachedBS.get<...>();

📊 Limitations / Notes

  • Raw memcpy is platform-dependent; for cross-platform formats, custom wrappers may need to be implemented
  • boost::pfr only works with public members and may be affected by specific constructors or class declarations
  • Complex types with internal allocation (e.g., sparse matrices) should be explicitly serialized

🤝 Many thanks

I would like to express my special thanks to my supervisor Dr. Hendrik Geisler, who was a great help during the development.

Hendrik Geisler was funded by the European Union (ERC, Gen-TSM, project number 101124463) during the supervision period. However, the views and opinions expressed are solely those of the author(s) and do not necessarily reflect those of the European Union or the European Research Council Executive Agency. Neither the European Union nor the funding authority can be held responsible for them.

📚 Libraries used

I would also like to thank the respective developers and maintainers of the open-source libraries used in the project. These are listed below. The corresponding license texts are stored in the thirdPartyLicenses folder.

LibraryLicense
Boost.PFRBoost Software License 1.0

About

Single‑header library for automatic object serialization into byte streams

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

🌐 English | Deutsch

ByteSequence

ByteSequence is a single-header library for binary object serialization. ByteSequence implements byte streams into which objects can be pushed and from which objects can be popped. The focus is on generic serialization (using boost::pfr), the recursive decomposition of dynamic containers (std::vector, std::map, ...), and a minimalist syntax.

🧬 Requirements

  • Language standard: C++20
  • Compiler: gcc/g++
  • Platform: Windows

Lib has not been tested in any other way so far

🚀 Setup

  • Clone ByteSequence into the project
  • Obtain the Boost.PFR dependency or have CMake automatically set it up using add_subdirectory and linking it
git clone https://github.com/tr3dh/ByteSequence.git src
# In own CMakeLists.txt
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/src/ByteSequence")
target_link_libraries(... ... ByteSequence)
  • include Header
#include"path/to/ByteSequence.hpp"

🔧 Features

  • Bytestream interactions insert, extract, insertMultiple, extractMultiple, extractMultipleReversed, get<T>()
  • Lazy Syntax operator += / operator -=
  • file-I/O: toFile, fromFile
  • string-I/O: toString, fromString
  • XOR-Encoder : encode(std::string), decode(std::string)

🏗️ Support

  • Trivial copyable objects (non-dynamic)
  • Struct members
  • Members of fully public classes
  • std::vector<T>
  • std::map<Key, Val>
  • std::unordered_map<Key, Val>
  • std::multimap<Key, Val>
  • std::pair<First, Second>
  • std::string
  • const char*, char*, char[N]

🛠️ Usage

The insertMultiple and extractMultipleReversed methods can be used to insert objects into or extract them from the byte stream. This applies to supported (defined serialization) and trivially copyable elements.

ByteSequence bs;
int b, a = 42; double d, c = 3.14;
bs.insertMultiple(a, c);
bs.extractMultipleReversed(b, d);

In addition, struct members and class members of fully public classes can be copied. The attributes are parsed by boost::pfr and inserted recursively.

structWhatever{ std::vector<std::vector<std::vector<int>>> m_intVecs; }
ByteSequence bs;
Whatever b, a; a.m_intVecs = = {{{1,2,3}, {4,5,6}}};
bs += a;
bs -= b;

With the XOR encoder ByteSequences can be encoded and decoded.

ByteSequence bs;
bs.insert(data);
std::string key = "...";
bs.encode(key);
bs.decode(key);

If a data type cannot be serialized using the recursive chaining of trivially copyable or supported dynamic containers, a type-specific serialization can be written. This works with both external and member functions. Serialization of unsupported dynamic containers is also possible. Template-based serializations can be used for this purpose.

// Serialization via member functionsstructA {
voidtoByteSequence(ByteSequence& seq) const {
seq.insertMultiple(...);
}
voidfromByteSequence(ByteSequence& seq) {
seq.extractMultipleReversed(...);
}
};
// Serialization via functionsinlinevoidtoByteSequence(const A& a, ByteSequence& seq) {
seq.insertMultiple(...);
}
inlinevoidfromByteSequence(A& a, ByteSequence& seq) {
seq.extractMultipleReversed(...);
}
// Serialization of a dynamic container, example std::vectortemplate<typename T>
inlinevoidtoByteSequence(const std::vector<T>& member, ByteSequence& seq) {
for (auto it = member.rbegin(); it != member.rend(); ++it) {
seq.insert(*it);
}
seq.insert(member.size());
}
template<typename T>
inlinevoidfromByteSequence(std::vector<T>& member, ByteSequence& seq) {
size_t size = seq.get<size_t>();
member.resize(size);
for (size_t i = 0; i < size; i++) {
member[i] = seq.get<T>();
}
}

Using the file and string I/O functions, byte caches can be written to and read from strings or files.

ByteSequence bs;
bs.insert(data);
bs.toFile("path/to/cache.bin");
ByteSequence cachedBS;
cachedBS.fromFile("path/to/cache.bin");
auto restoredData = cachedBS.get<...>();

📊 Limitations / Notes

  • Raw memcpy is platform-dependent; for cross-platform formats, custom wrappers may need to be implemented
  • boost::pfr only works with public members and may be affected by specific constructors or class declarations
  • Complex types with internal allocation (e.g., sparse matrices) should be explicitly serialized

🤝 Many thanks

I would like to express my special thanks to my supervisor Dr. Hendrik Geisler, who was a great help during the development.

Hendrik Geisler was funded by the European Union (ERC, Gen-TSM, project number 101124463) during the supervision period. However, the views and opinions expressed are solely those of the author(s) and do not necessarily reflect those of the European Union or the European Research Council Executive Agency. Neither the European Union nor the funding authority can be held responsible for them.

📚 Libraries used

I would also like to thank the respective developers and maintainers of the open-source libraries used in the project. These are listed below. The corresponding license texts are stored in the thirdPartyLicenses folder.

LibraryLicense
Boost.PFRBoost Software License 1.0

About

Single‑header library for automatic object serialization into byte streams

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

🌐 English | Deutsch

ByteSequence

ByteSequence is a single-header library for binary object serialization. ByteSequence implements byte streams into which objects can be pushed and from which objects can be popped. The focus is on generic serialization (using boost::pfr), the recursive decomposition of dynamic containers (std::vector, std::map, ...), and a minimalist syntax.

🧬 Requirements

  • Language standard: C++20
  • Compiler: gcc/g++
  • Platform: Windows

Lib has not been tested in any other way so far

🚀 Setup

  • Clone ByteSequence into the project
  • Obtain the Boost.PFR dependency or have CMake automatically set it up using add_subdirectory and linking it
git clone https://github.com/tr3dh/ByteSequence.git src
# In own CMakeLists.txt
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/src/ByteSequence")
target_link_libraries(... ... ByteSequence)
  • include Header
#include"path/to/ByteSequence.hpp"

🔧 Features

  • Bytestream interactions insert, extract, insertMultiple, extractMultiple, extractMultipleReversed, get<T>()
  • Lazy Syntax operator += / operator -=
  • file-I/O: toFile, fromFile
  • string-I/O: toString, fromString
  • XOR-Encoder : encode(std::string), decode(std::string)

🏗️ Support

  • Trivial copyable objects (non-dynamic)
  • Struct members
  • Members of fully public classes
  • std::vector<T>
  • std::map<Key, Val>
  • std::unordered_map<Key, Val>
  • std::multimap<Key, Val>
  • std::pair<First, Second>
  • std::string
  • const char*, char*, char[N]

🛠️ Usage

The insertMultiple and extractMultipleReversed methods can be used to insert objects into or extract them from the byte stream. This applies to supported (defined serialization) and trivially copyable elements.

ByteSequence bs;
int b, a = 42; double d, c = 3.14;
bs.insertMultiple(a, c);
bs.extractMultipleReversed(b, d);

In addition, struct members and class members of fully public classes can be copied. The attributes are parsed by boost::pfr and inserted recursively.

structWhatever{ std::vector<std::vector<std::vector<int>>> m_intVecs; }
ByteSequence bs;
Whatever b, a; a.m_intVecs = = {{{1,2,3}, {4,5,6}}};
bs += a;
bs -= b;

With the XOR encoder ByteSequences can be encoded and decoded.

ByteSequence bs;
bs.insert(data);
std::string key = "...";
bs.encode(key);
bs.decode(key);

If a data type cannot be serialized using the recursive chaining of trivially copyable or supported dynamic containers, a type-specific serialization can be written. This works with both external and member functions. Serialization of unsupported dynamic containers is also possible. Template-based serializations can be used for this purpose.

// Serialization via member functionsstructA {
voidtoByteSequence(ByteSequence& seq) const {
seq.insertMultiple(...);
}
voidfromByteSequence(ByteSequence& seq) {
seq.extractMultipleReversed(...);
}
};
// Serialization via functionsinlinevoidtoByteSequence(const A& a, ByteSequence& seq) {
seq.insertMultiple(...);
}
inlinevoidfromByteSequence(A& a, ByteSequence& seq) {
seq.extractMultipleReversed(...);
}
// Serialization of a dynamic container, example std::vectortemplate<typename T>
inlinevoidtoByteSequence(const std::vector<T>& member, ByteSequence& seq) {
for (auto it = member.rbegin(); it != member.rend(); ++it) {
seq.insert(*it);
}
seq.insert(member.size());
}
template<typename T>
inlinevoidfromByteSequence(std::vector<T>& member, ByteSequence& seq) {
size_t size = seq.get<size_t>();
member.resize(size);
for (size_t i = 0; i < size; i++) {
member[i] = seq.get<T>();
}
}

Using the file and string I/O functions, byte caches can be written to and read from strings or files.

ByteSequence bs;
bs.insert(data);
bs.toFile("path/to/cache.bin");
ByteSequence cachedBS;
cachedBS.fromFile("path/to/cache.bin");
auto restoredData = cachedBS.get<...>();

📊 Limitations / Notes

  • Raw memcpy is platform-dependent; for cross-platform formats, custom wrappers may need to be implemented
  • boost::pfr only works with public members and may be affected by specific constructors or class declarations
  • Complex types with internal allocation (e.g., sparse matrices) should be explicitly serialized

🤝 Many thanks

I would like to express my special thanks to my supervisor Dr. Hendrik Geisler, who was a great help during the development.

Hendrik Geisler was funded by the European Union (ERC, Gen-TSM, project number 101124463) during the supervision period. However, the views and opinions expressed are solely those of the author(s) and do not necessarily reflect those of the European Union or the European Research Council Executive Agency. Neither the European Union nor the funding authority can be held responsible for them.

📚 Libraries used

I would also like to thank the respective developers and maintainers of the open-source libraries used in the project. These are listed below. The corresponding license texts are stored in the thirdPartyLicenses folder.

LibraryLicense
Boost.PFRBoost Software License 1.0

About

Single‑header library for automatic object serialization into byte streams

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

🌐 English | Deutsch

ByteSequence

ByteSequence is a single-header library for binary object serialization. ByteSequence implements byte streams into which objects can be pushed and from which objects can be popped. The focus is on generic serialization (using boost::pfr), the recursive decomposition of dynamic containers (std::vector, std::map, ...), and a minimalist syntax.

🧬 Requirements

  • Language standard: C++20
  • Compiler: gcc/g++
  • Platform: Windows

Lib has not been tested in any other way so far

🚀 Setup

  • Clone ByteSequence into the project
  • Obtain the Boost.PFR dependency or have CMake automatically set it up using add_subdirectory and linking it
git clone https://github.com/tr3dh/ByteSequence.git src
# In own CMakeLists.txt
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/src/ByteSequence")
target_link_libraries(... ... ByteSequence)
  • include Header
#include"path/to/ByteSequence.hpp"

🔧 Features

  • Bytestream interactions insert, extract, insertMultiple, extractMultiple, extractMultipleReversed, get<T>()
  • Lazy Syntax operator += / operator -=
  • file-I/O: toFile, fromFile
  • string-I/O: toString, fromString
  • XOR-Encoder : encode(std::string), decode(std::string)

🏗️ Support

  • Trivial copyable objects (non-dynamic)
  • Struct members
  • Members of fully public classes
  • std::vector<T>
  • std::map<Key, Val>
  • std::unordered_map<Key, Val>
  • std::multimap<Key, Val>
  • std::pair<First, Second>
  • std::string
  • const char*, char*, char[N]

🛠️ Usage

The insertMultiple and extractMultipleReversed methods can be used to insert objects into or extract them from the byte stream. This applies to supported (defined serialization) and trivially copyable elements.

ByteSequence bs;
int b, a = 42; double d, c = 3.14;
bs.insertMultiple(a, c);
bs.extractMultipleReversed(b, d);

In addition, struct members and class members of fully public classes can be copied. The attributes are parsed by boost::pfr and inserted recursively.

structWhatever{ std::vector<std::vector<std::vector<int>>> m_intVecs; }
ByteSequence bs;
Whatever b, a; a.m_intVecs = = {{{1,2,3}, {4,5,6}}};
bs += a;
bs -= b;

With the XOR encoder ByteSequences can be encoded and decoded.

ByteSequence bs;
bs.insert(data);
std::string key = "...";
bs.encode(key);
bs.decode(key);

If a data type cannot be serialized using the recursive chaining of trivially copyable or supported dynamic containers, a type-specific serialization can be written. This works with both external and member functions. Serialization of unsupported dynamic containers is also possible. Template-based serializations can be used for this purpose.

// Serialization via member functionsstructA {
voidtoByteSequence(ByteSequence& seq) const {
seq.insertMultiple(...);
}
voidfromByteSequence(ByteSequence& seq) {
seq.extractMultipleReversed(...);
}
};
// Serialization via functionsinlinevoidtoByteSequence(const A& a, ByteSequence& seq) {
seq.insertMultiple(...);
}
inlinevoidfromByteSequence(A& a, ByteSequence& seq) {
seq.extractMultipleReversed(...);
}
// Serialization of a dynamic container, example std::vectortemplate<typename T>
inlinevoidtoByteSequence(const std::vector<T>& member, ByteSequence& seq) {
for (auto it = member.rbegin(); it != member.rend(); ++it) {
seq.insert(*it);
}
seq.insert(member.size());
}
template<typename T>
inlinevoidfromByteSequence(std::vector<T>& member, ByteSequence& seq) {
size_t size = seq.get<size_t>();
member.resize(size);
for (size_t i = 0; i < size; i++) {
member[i] = seq.get<T>();
}
}

Using the file and string I/O functions, byte caches can be written to and read from strings or files.

ByteSequence bs;
bs.insert(data);
bs.toFile("path/to/cache.bin");
ByteSequence cachedBS;
cachedBS.fromFile("path/to/cache.bin");
auto restoredData = cachedBS.get<...>();

📊 Limitations / Notes

  • Raw memcpy is platform-dependent; for cross-platform formats, custom wrappers may need to be implemented
  • boost::pfr only works with public members and may be affected by specific constructors or class declarations
  • Complex types with internal allocation (e.g., sparse matrices) should be explicitly serialized

🤝 Many thanks

I would like to express my special thanks to my supervisor Dr. Hendrik Geisler, who was a great help during the development.

Hendrik Geisler was funded by the European Union (ERC, Gen-TSM, project number 101124463) during the supervision period. However, the views and opinions expressed are solely those of the author(s) and do not necessarily reflect those of the European Union or the European Research Council Executive Agency. Neither the European Union nor the funding authority can be held responsible for them.

📚 Libraries used

I would also like to thank the respective developers and maintainers of the open-source libraries used in the project. These are listed below. The corresponding license texts are stored in the thirdPartyLicenses folder.

LibraryLicense
Boost.PFRBoost Software License 1.0

About

Single‑header library for automatic object serialization into byte streams

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

🌐 English | Deutsch

ByteSequence

ByteSequence is a single-header library for binary object serialization. ByteSequence implements byte streams into which objects can be pushed and from which objects can be popped. The focus is on generic serialization (using boost::pfr), the recursive decomposition of dynamic containers (std::vector, std::map, ...), and a minimalist syntax.

🧬 Requirements

  • Language standard: C++20
  • Compiler: gcc/g++
  • Platform: Windows

Lib has not been tested in any other way so far

🚀 Setup

  • Clone ByteSequence into the project
  • Obtain the Boost.PFR dependency or have CMake automatically set it up using add_subdirectory and linking it
git clone https://github.com/tr3dh/ByteSequence.git src
# In own CMakeLists.txt
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/src/ByteSequence")
target_link_libraries(... ... ByteSequence)
  • include Header
#include"path/to/ByteSequence.hpp"

🔧 Features

  • Bytestream interactions insert, extract, insertMultiple, extractMultiple, extractMultipleReversed, get<T>()
  • Lazy Syntax operator += / operator -=
  • file-I/O: toFile, fromFile
  • string-I/O: toString, fromString
  • XOR-Encoder : encode(std::string), decode(std::string)

🏗️ Support

  • Trivial copyable objects (non-dynamic)
  • Struct members
  • Members of fully public classes
  • std::vector<T>
  • std::map<Key, Val>
  • std::unordered_map<Key, Val>
  • std::multimap<Key, Val>
  • std::pair<First, Second>
  • std::string
  • const char*, char*, char[N]

🛠️ Usage

The insertMultiple and extractMultipleReversed methods can be used to insert objects into or extract them from the byte stream. This applies to supported (defined serialization) and trivially copyable elements.

ByteSequence bs;
int b, a = 42; double d, c = 3.14;
bs.insertMultiple(a, c);
bs.extractMultipleReversed(b, d);

In addition, struct members and class members of fully public classes can be copied. The attributes are parsed by boost::pfr and inserted recursively.

structWhatever{ std::vector<std::vector<std::vector<int>>> m_intVecs; }
ByteSequence bs;
Whatever b, a; a.m_intVecs = = {{{1,2,3}, {4,5,6}}};
bs += a;
bs -= b;

With the XOR encoder ByteSequences can be encoded and decoded.

ByteSequence bs;
bs.insert(data);
std::string key = "...";
bs.encode(key);
bs.decode(key);

If a data type cannot be serialized using the recursive chaining of trivially copyable or supported dynamic containers, a type-specific serialization can be written. This works with both external and member functions. Serialization of unsupported dynamic containers is also possible. Template-based serializations can be used for this purpose.

// Serialization via member functionsstructA {
voidtoByteSequence(ByteSequence& seq) const {
seq.insertMultiple(...);
}
voidfromByteSequence(ByteSequence& seq) {
seq.extractMultipleReversed(...);
}
};
// Serialization via functionsinlinevoidtoByteSequence(const A& a, ByteSequence& seq) {
seq.insertMultiple(...);
}
inlinevoidfromByteSequence(A& a, ByteSequence& seq) {
seq.extractMultipleReversed(...);
}
// Serialization of a dynamic container, example std::vectortemplate<typename T>
inlinevoidtoByteSequence(const std::vector<T>& member, ByteSequence& seq) {
for (auto it = member.rbegin(); it != member.rend(); ++it) {
seq.insert(*it);
}
seq.insert(member.size());
}
template<typename T>
inlinevoidfromByteSequence(std::vector<T>& member, ByteSequence& seq) {
size_t size = seq.get<size_t>();
member.resize(size);
for (size_t i = 0; i < size; i++) {
member[i] = seq.get<T>();
}
}

Using the file and string I/O functions, byte caches can be written to and read from strings or files.

ByteSequence bs;
bs.insert(data);
bs.toFile("path/to/cache.bin");
ByteSequence cachedBS;
cachedBS.fromFile("path/to/cache.bin");
auto restoredData = cachedBS.get<...>();

📊 Limitations / Notes

  • Raw memcpy is platform-dependent; for cross-platform formats, custom wrappers may need to be implemented
  • boost::pfr only works with public members and may be affected by specific constructors or class declarations
  • Complex types with internal allocation (e.g., sparse matrices) should be explicitly serialized

🤝 Many thanks

I would like to express my special thanks to my supervisor Dr. Hendrik Geisler, who was a great help during the development.

Hendrik Geisler was funded by the European Union (ERC, Gen-TSM, project number 101124463) during the supervision period. However, the views and opinions expressed are solely those of the author(s) and do not necessarily reflect those of the European Union or the European Research Council Executive Agency. Neither the European Union nor the funding authority can be held responsible for them.

📚 Libraries used

I would also like to thank the respective developers and maintainers of the open-source libraries used in the project. These are listed below. The corresponding license texts are stored in the thirdPartyLicenses folder.

LibraryLicense
Boost.PFRBoost Software License 1.0

About

Single‑header library for automatic object serialization into byte streams

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

🌐 English | Deutsch

ByteSequence

ByteSequence is a single-header library for binary object serialization. ByteSequence implements byte streams into which objects can be pushed and from which objects can be popped. The focus is on generic serialization (using boost::pfr), the recursive decomposition of dynamic containers (std::vector, std::map, ...), and a minimalist syntax.

🧬 Requirements

  • Language standard: C++20
  • Compiler: gcc/g++
  • Platform: Windows

Lib has not been tested in any other way so far

🚀 Setup

  • Clone ByteSequence into the project
  • Obtain the Boost.PFR dependency or have CMake automatically set it up using add_subdirectory and linking it
git clone https://github.com/tr3dh/ByteSequence.git src
# In own CMakeLists.txt
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/src/ByteSequence")
target_link_libraries(... ... ByteSequence)
  • include Header
#include"path/to/ByteSequence.hpp"

🔧 Features

  • Bytestream interactions insert, extract, insertMultiple, extractMultiple, extractMultipleReversed, get<T>()
  • Lazy Syntax operator += / operator -=
  • file-I/O: toFile, fromFile
  • string-I/O: toString, fromString
  • XOR-Encoder : encode(std::string), decode(std::string)

🏗️ Support

  • Trivial copyable objects (non-dynamic)
  • Struct members
  • Members of fully public classes
  • std::vector<T>
  • std::map<Key, Val>
  • std::unordered_map<Key, Val>
  • std::multimap<Key, Val>
  • std::pair<First, Second>
  • std::string
  • const char*, char*, char[N]

🛠️ Usage

The insertMultiple and extractMultipleReversed methods can be used to insert objects into or extract them from the byte stream. This applies to supported (defined serialization) and trivially copyable elements.

ByteSequence bs;
int b, a = 42; double d, c = 3.14;
bs.insertMultiple(a, c);
bs.extractMultipleReversed(b, d);

In addition, struct members and class members of fully public classes can be copied. The attributes are parsed by boost::pfr and inserted recursively.

structWhatever{ std::vector<std::vector<std::vector<int>>> m_intVecs; }
ByteSequence bs;
Whatever b, a; a.m_intVecs = = {{{1,2,3}, {4,5,6}}};
bs += a;
bs -= b;

With the XOR encoder ByteSequences can be encoded and decoded.

ByteSequence bs;
bs.insert(data);
std::string key = "...";
bs.encode(key);
bs.decode(key);

If a data type cannot be serialized using the recursive chaining of trivially copyable or supported dynamic containers, a type-specific serialization can be written. This works with both external and member functions. Serialization of unsupported dynamic containers is also possible. Template-based serializations can be used for this purpose.

// Serialization via member functionsstructA {
voidtoByteSequence(ByteSequence& seq) const {
seq.insertMultiple(...);
}
voidfromByteSequence(ByteSequence& seq) {
seq.extractMultipleReversed(...);
}
};
// Serialization via functionsinlinevoidtoByteSequence(const A& a, ByteSequence& seq) {
seq.insertMultiple(...);
}
inlinevoidfromByteSequence(A& a, ByteSequence& seq) {
seq.extractMultipleReversed(...);
}
// Serialization of a dynamic container, example std::vectortemplate<typename T>
inlinevoidtoByteSequence(const std::vector<T>& member, ByteSequence& seq) {
for (auto it = member.rbegin(); it != member.rend(); ++it) {
seq.insert(*it);
}
seq.insert(member.size());
}
template<typename T>
inlinevoidfromByteSequence(std::vector<T>& member, ByteSequence& seq) {
size_t size = seq.get<size_t>();
member.resize(size);
for (size_t i = 0; i < size; i++) {
member[i] = seq.get<T>();
}
}

Using the file and string I/O functions, byte caches can be written to and read from strings or files.

ByteSequence bs;
bs.insert(data);
bs.toFile("path/to/cache.bin");
ByteSequence cachedBS;
cachedBS.fromFile("path/to/cache.bin");
auto restoredData = cachedBS.get<...>();

📊 Limitations / Notes

  • Raw memcpy is platform-dependent; for cross-platform formats, custom wrappers may need to be implemented
  • boost::pfr only works with public members and may be affected by specific constructors or class declarations
  • Complex types with internal allocation (e.g., sparse matrices) should be explicitly serialized

🤝 Many thanks

I would like to express my special thanks to my supervisor Dr. Hendrik Geisler, who was a great help during the development.

Hendrik Geisler was funded by the European Union (ERC, Gen-TSM, project number 101124463) during the supervision period. However, the views and opinions expressed are solely those of the author(s) and do not necessarily reflect those of the European Union or the European Research Council Executive Agency. Neither the European Union nor the funding authority can be held responsible for them.

📚 Libraries used

I would also like to thank the respective developers and maintainers of the open-source libraries used in the project. These are listed below. The corresponding license texts are stored in the thirdPartyLicenses folder.

LibraryLicense
Boost.PFRBoost Software License 1.0

About

Single‑header library for automatic object serialization into byte streams

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

🌐 English | Deutsch

ByteSequence

ByteSequence is a single-header library for binary object serialization. ByteSequence implements byte streams into which objects can be pushed and from which objects can be popped. The focus is on generic serialization (using boost::pfr), the recursive decomposition of dynamic containers (std::vector, std::map, ...), and a minimalist syntax.

🧬 Requirements

  • Language standard: C++20
  • Compiler: gcc/g++
  • Platform: Windows

Lib has not been tested in any other way so far

🚀 Setup

  • Clone ByteSequence into the project
  • Obtain the Boost.PFR dependency or have CMake automatically set it up using add_subdirectory and linking it
git clone https://github.com/tr3dh/ByteSequence.git src
# In own CMakeLists.txt
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/src/ByteSequence")
target_link_libraries(... ... ByteSequence)
  • include Header
#include"path/to/ByteSequence.hpp"

🔧 Features

  • Bytestream interactions insert, extract, insertMultiple, extractMultiple, extractMultipleReversed, get<T>()
  • Lazy Syntax operator += / operator -=
  • file-I/O: toFile, fromFile
  • string-I/O: toString, fromString
  • XOR-Encoder : encode(std::string), decode(std::string)

🏗️ Support

  • Trivial copyable objects (non-dynamic)
  • Struct members
  • Members of fully public classes
  • std::vector<T>
  • std::map<Key, Val>
  • std::unordered_map<Key, Val>
  • std::multimap<Key, Val>
  • std::pair<First, Second>
  • std::string
  • const char*, char*, char[N]

🛠️ Usage

The insertMultiple and extractMultipleReversed methods can be used to insert objects into or extract them from the byte stream. This applies to supported (defined serialization) and trivially copyable elements.

ByteSequence bs;
int b, a = 42; double d, c = 3.14;
bs.insertMultiple(a, c);
bs.extractMultipleReversed(b, d);

In addition, struct members and class members of fully public classes can be copied. The attributes are parsed by boost::pfr and inserted recursively.

structWhatever{ std::vector<std::vector<std::vector<int>>> m_intVecs; }
ByteSequence bs;
Whatever b, a; a.m_intVecs = = {{{1,2,3}, {4,5,6}}};
bs += a;
bs -= b;

With the XOR encoder ByteSequences can be encoded and decoded.

ByteSequence bs;
bs.insert(data);
std::string key = "...";
bs.encode(key);
bs.decode(key);

If a data type cannot be serialized using the recursive chaining of trivially copyable or supported dynamic containers, a type-specific serialization can be written. This works with both external and member functions. Serialization of unsupported dynamic containers is also possible. Template-based serializations can be used for this purpose.

// Serialization via member functionsstructA {
voidtoByteSequence(ByteSequence& seq) const {
seq.insertMultiple(...);
}
voidfromByteSequence(ByteSequence& seq) {
seq.extractMultipleReversed(...);
}
};
// Serialization via functionsinlinevoidtoByteSequence(const A& a, ByteSequence& seq) {
seq.insertMultiple(...);
}
inlinevoidfromByteSequence(A& a, ByteSequence& seq) {
seq.extractMultipleReversed(...);
}
// Serialization of a dynamic container, example std::vectortemplate<typename T>
inlinevoidtoByteSequence(const std::vector<T>& member, ByteSequence& seq) {
for (auto it = member.rbegin(); it != member.rend(); ++it) {
seq.insert(*it);
}
seq.insert(member.size());
}
template<typename T>
inlinevoidfromByteSequence(std::vector<T>& member, ByteSequence& seq) {
size_t size = seq.get<size_t>();
member.resize(size);
for (size_t i = 0; i < size; i++) {
member[i] = seq.get<T>();
}
}

Using the file and string I/O functions, byte caches can be written to and read from strings or files.

ByteSequence bs;
bs.insert(data);
bs.toFile("path/to/cache.bin");
ByteSequence cachedBS;
cachedBS.fromFile("path/to/cache.bin");
auto restoredData = cachedBS.get<...>();

📊 Limitations / Notes

  • Raw memcpy is platform-dependent; for cross-platform formats, custom wrappers may need to be implemented
  • boost::pfr only works with public members and may be affected by specific constructors or class declarations
  • Complex types with internal allocation (e.g., sparse matrices) should be explicitly serialized

🤝 Many thanks

I would like to express my special thanks to my supervisor Dr. Hendrik Geisler, who was a great help during the development.

Hendrik Geisler was funded by the European Union (ERC, Gen-TSM, project number 101124463) during the supervision period. However, the views and opinions expressed are solely those of the author(s) and do not necessarily reflect those of the European Union or the European Research Council Executive Agency. Neither the European Union nor the funding authority can be held responsible for them.

📚 Libraries used

I would also like to thank the respective developers and maintainers of the open-source libraries used in the project. These are listed below. The corresponding license texts are stored in the thirdPartyLicenses folder.

LibraryLicense
Boost.PFRBoost Software License 1.0

About

Single‑header library for automatic object serialization into byte streams

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Packages

Contributors

Languages