Crunch Logo
Crunch is a C++ message definition and serialization framework for mission-critical, resource-constrained systems where message semantics matter as much as structure.
See the Doxygen for API reference and detailed documentation.
Key Features
- Opt-out validation: Semantic field and cross-field validation are first-class, built-in, and happen by default.
- Static memory allocation: For use in resource-constrained systems.
- Flexible serialization: Swap serialization formats (e.g., TLV, static layout) without changing message definitions.
- Built-in integrity checks: Support for CRC16 or parity is built-in.
- Zero exceptions: Uses
std::expected and std::optional for error handling to be compatible with real-time requirements.
Dependencies
Crunch requires C++23 and uses some STL libraries.
None of the STL libraries used by Crunch perform dynamic memory allocation.
Installation
Crunch is a header-only library. You can vendor it directly or use a build system.
Vendoring
Copy the include/ directory to your project:
cp -r crunch/include/ your_project/vendor/
Then add the include path to your compiler:
g++ -I vendor -std=c++23 your_code.cpp
CMake
Add Crunch as a subdirectory:
add_subdirectory(vendor/crunch)
target_link_libraries(your_target PRIVATE Crunch::crunch)
Bazel
Add the dependency to your BUILD file:
cc_binary(
name = "your_target",
srcs = ["main.cpp"],
deps = ["//include:crunch"],
)
Quick Start
#include <crunch/crunch.hpp>
using namespace Crunch::fields;
using namespace Crunch::messages;
struct SensorReading {
CRUNCH_MESSAGE_FIELDS(temperature, humidity);
constexpr auto Validate() const -> std::optional<
Error> {
if (*humidity.get() > 90.0f && *temperature.get() > 50.0f) {
return Error::validation(2, "humidity > 90% invalid above 50C");
}
return std::nullopt;
}
bool operator==(const SensorReading&) const = default;
};
int main() {
SensorReading msg;
msg.temperature.set(23.5f);
msg.humidity.set(65.0f);
auto buffer = GetBuffer<SensorReading, integrity::CRC16, serdes::PackedLayout>();
if (
auto err =
Serialize(buffer, msg); err) {
return 1;
}
SensorReading decoded;
return 1;
}
assert(msg == decoded);
}
A validated, typed message field.
Definition: crunch_scalar.hpp:24
Wrapper for a message field within a CrunchMessage.
Definition: crunch_field.hpp:50
The public API for Crunch.
Definition: crunch_endian.hpp:10
constexpr auto Deserialize(const BufferType &buffer, Message &out_message) -> std::optional< Error >
Deserializes a message from a buffer.
Definition: crunch.hpp:164
int32_t MessageId
Unique identifier for a message type.
Definition: crunch_types.hpp:25
constexpr auto Serialize(BufferType &buffer, const Message &message) noexcept -> std::optional< Error >
Serializes a message into the provided buffer.
Definition: crunch.hpp:107
Represents an error occurred during Crunch operations.
Definition: crunch_types.hpp:73
Presence validator enforcing that a field MUST be set.
Definition: crunch_validators.hpp:35
Message Definition
Messages must define:
- A unique
MessageId
- A
CRUNCH_MESSAGE_FIELDS macro listing all fields
- A
Validate method returning std::optional<Error>
- An
operator== for equality comparison
Supported Field Types
| Category | Types |
| Integers | Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64 |
| Floats | Float32, Float64 |
| Other | Bool, String, Enum |
| Aggregate | Submessage, Array, Map |
See Field Types for detailed examples of each type.
Validation Flow
When serializing or deserializing, validation occurs in order:
- Field Presence: Checks that all
Required fields are set.
- Field Values: Checks that set fields satisfy their validators.
- Message Logic: Executes the user-defined
Validate() method.
Validation can be bypassed using SerializeWithoutValidation.
Serialization
Crunch supports pluggable serialization:
serdes::StaticLayout<Alignment> - Deterministic, fixed-size binary format
serdes::TlvLayout - Tag-Length-Value format for flexibility
See Serialization Formats for wire format details.
Roadmap
Done:
- Basic message definitions, field/message validation
- Scalar fields, enums, strings, submessages, arrays, maps
- Static layout and TLV serialization
- CRC16 and parity integrity checking
- Unit testing, documentation, CI/CD
Upcoming:
- Test coverage reporting
- QEMU-based cross-platform testing
- Fuzz testing
- Performance benchmarks
- C, Rust, Python bindings
Follow along at volatileint.dev for roadmap updates!