qtty-cpp 0.4.5
Header-only C++ wrapper for qtty
Loading...
Searching...
No Matches
serialization.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSD-3-Clause
2// Copyright (C) 2026 Vallés Puig, Ramon
3
4#pragma once
5
11#include <stdexcept>
12#include <string>
13#include <string_view>
14#include <type_traits>
15extern "C" {
16#include "qtty_ffi.h"
17}
18#include "ffi_core.hpp"
19
20// Forward declarations for JSON-related FFI functions. These may not be present
21// in older generated headers; we declare them here to ensure availability at
22// compile time when linking against a serde-enabled qtty-ffi.
23extern "C" {
24int32_t qtty_quantity_to_json_value(qtty_quantity_t src, char **out_json);
25int32_t qtty_quantity_from_json_value(UnitId unit, const char *json, qtty_quantity_t *out);
26int32_t qtty_quantity_to_json(qtty_quantity_t src, char **out_json);
27int32_t qtty_quantity_from_json(const char *json, qtty_quantity_t *out);
28int32_t qtty_derived_to_json(qtty_derived_quantity_t src, char **out);
29int32_t qtty_derived_from_json(const char *json, qtty_derived_quantity_t *out);
30void qtty_string_free(char *s);
31}
32
33namespace qtty {
34namespace serialization {
35
36// Thin wrappers over Rust FFI JSON serialize/deserialize.
37// Requires qtty-ffi to be built with the `qtty_serde` Cargo feature.
38
44inline std::string from_owned_c(char *ptr) {
45 if (!ptr)
46 return {};
47 std::string s(ptr);
48 // Free via FFI allocator
50 return s;
51}
52
53// Serialize only the numeric value as a JSON number string.
54// Mirrors Rust's default serde for quantities.
55
62template <typename UnitTag> std::string to_json_value(const Quantity<UnitTag> &q) {
65 check_status(static_cast<QttyStatus>(status), "Creating source quantity for to_json_value");
66
67 char *out = nullptr;
69 check_status(static_cast<QttyStatus>(status), "Serializing value to JSON");
70 return from_owned_c(out);
71}
72
79template <typename T>
81 using UnitTag = typename ExtractTag<T>::type;
85 check_status(static_cast<QttyStatus>(status), "Deserializing value from JSON");
86 return Quantity<UnitTag>(out_qty.value);
87}
88
89// Serialize value and unit_id into an object {"value":<f64>, "unit_id":<u32>}.
90
97template <typename UnitTag> std::string to_json(const Quantity<UnitTag> &q) {
100 check_status(static_cast<QttyStatus>(status), "Creating source quantity for to_json");
101
102 char *out = nullptr;
104 check_status(static_cast<QttyStatus>(status), "Serializing quantity to JSON");
105 return from_owned_c(out);
106}
107
109 // cbindgen exposes UnitId directly; cast is safe for values from Rust
110 return static_cast<UnitId>(raw);
111}
112
113// Parse {"value":<f64>, "unit_id":<u32>} and construct a typed quantity.
114// Rejects mismatched dimensions and unknown unit_ids at the Rust boundary.
115
122template <typename T> Quantity<typename ExtractTag<T>::type> from_json(std::string_view json) {
123 using UnitTag = typename ExtractTag<T>::type;
126 check_status(static_cast<QttyStatus>(status), "Deserializing quantity from JSON");
127
128 // Convert to requested UnitTag if needed; Rust returns the unit in JSON
132 check_status(static_cast<QttyStatus>(status),
133 "Converting deserialized quantity to target unit");
134 return Quantity<UnitTag>(conv.value);
135 }
136 return Quantity<UnitTag>(out_qty.value);
137}
138
139} // namespace serialization
140
141// ============================================================================
142// Compound Quantity Serialization
143// ============================================================================
144// Serialize/deserialize derived quantities (e.g., velocity) via the Rust FFI.
145
146namespace derived_serialization {
147
154template <typename Tag> std::string to_json(const Quantity<Tag> &q) {
155 static_assert(is_compound_v<Tag>, "derived_serialization::to_json requires a compound quantity");
159 check_status(static_cast<QttyStatus>(status), "Creating derived quantity for serialization");
160
161 char *out = nullptr;
163 check_status(static_cast<QttyStatus>(status), "Serializing derived quantity to JSON");
165}
166
173template <typename T> Quantity<typename ExtractTag<T>::type> from_json(std::string_view json) {
174 using Tag = typename ExtractTag<T>::type;
175 static_assert(is_compound_v<Tag>, "derived_serialization::from_json requires a compound type");
178 check_status(static_cast<QttyStatus>(status), "Deserializing derived quantity from JSON");
179
180 // Convert to requested units if needed
181 if (out_qty.numerator != UnitTraits<Tag>::numerator_unit_id() ||
186 check_status(static_cast<QttyStatus>(status), "Converting deserialized derived quantity");
187 return Quantity<Tag>(conv.value);
188 }
189 return Quantity<Tag>(out_qty.value);
190}
191
192} // namespace derived_serialization
193} // namespace qtty
Core quantity template and error translation utilities.
Quantity< typename ExtractTag< T >::type > from_json(std::string_view json)
Deserialize a JSON string into a compound quantity.
std::string to_json(const Quantity< Tag > &q)
Serialize a compound quantity as JSON.
Quantity< typename ExtractTag< T >::type > from_json_value(std::string_view json)
Deserialize a JSON numeric value into a typed quantity.
std::string to_json(const Quantity< UnitTag > &q)
Serialize a typed quantity as JSON object with value and unit id.
std::string to_json_value(const Quantity< UnitTag > &q)
Serialize only the numeric value as JSON for a typed quantity.
UnitId unit_id_from_u32(uint32_t raw)
Quantity< typename ExtractTag< T >::type > from_json(std::string_view json)
Deserialize a JSON quantity object into a requested target type.
std::string from_owned_c(char *ptr)
Convert an owned C string from FFI into std::string and free it.
constexpr bool is_angular_v
Definition angles.hpp:49
void check_status(QttyStatus status, const char *operation)
Convert qtty FFI status codes into typed C++ exceptions.
Definition ffi_core.hpp:91
int32_t qtty_quantity_from_json_value(UnitId unit, const char *json, qtty_quantity_t *out)
void qtty_string_free(char *s)
int32_t qtty_derived_from_json(const char *json, qtty_derived_quantity_t *out)
int32_t qtty_quantity_from_json(const char *json, qtty_quantity_t *out)
int32_t qtty_quantity_to_json_value(qtty_quantity_t src, char **out_json)
int32_t qtty_derived_to_json(qtty_derived_quantity_t src, char **out)
int32_t qtty_quantity_to_json(qtty_quantity_t src, char **out_json)