@@ -20,12 +20,6 @@ namespace eventide::serde::schema {
2020
2121struct field_info ;
2222
23- // ---------------------------------------------------------------------------
24- // type_kind — unified type classification
25- // ---------------------------------------------------------------------------
26-
27- // / Unified type classification replacing the old type_kind + scalar_kind pair.
28- // / Scalars use fine-grained values; compound types use broad categories.
2923enum class type_kind : std::uint8_t {
3024 // Scalars (fine-grained)
3125 null = 0 ,
@@ -60,23 +54,13 @@ enum class type_kind : std::uint8_t {
6054 any = 255 , // future: runtime dynamic type
6155};
6256
63- // ---------------------------------------------------------------------------
64- // tag_mode — variant tagging strategy
65- // ---------------------------------------------------------------------------
66-
6757enum class tag_mode : std::uint8_t {
6858 none,
6959 external,
7060 internal,
7161 adjacent,
7262};
7363
74- // ---------------------------------------------------------------------------
75- // type_info — base class and subtypes
76- // ---------------------------------------------------------------------------
77-
78- // / Base type descriptor. Scalars use this directly; compound types downcast
79- // / to the appropriate subclass via `kind`.
8064struct type_info {
8165 type_kind kind;
8266 std::string_view type_name;
@@ -106,30 +90,25 @@ struct type_info {
10690 }
10791};
10892
109- // / array / set
11093struct array_type_info : type_info {
11194 const type_info* element;
11295};
11396
114- // / map
11597struct map_type_info : type_info {
11698 const type_info* key;
11799 const type_info* value;
118100};
119101
120- // / enum — runtime-accessible enum metadata
121102struct enum_type_info : type_info {
122103 std::span<const std::string_view> member_names;
123104 std::span<const std::int64_t > member_values;
124105 type_kind underlying_kind;
125106};
126107
127- // / tuple / pair
128108struct tuple_type_info : type_info {
129109 std::span<const type_info* const > elements;
130110};
131111
132- // / variant — includes tagging metadata
133112struct variant_type_info : type_info {
134113 std::span<const type_info* const > alternatives;
135114 tag_mode tagging = tag_mode::none;
@@ -138,52 +117,33 @@ struct variant_type_info : type_info {
138117 std::span<const std::string_view> alt_names;
139118};
140119
141- // / optional / smart_ptr — wraps the inner type
142120struct optional_type_info : type_info {
143121 const type_info* inner;
144122};
145123
146- // ---------------------------------------------------------------------------
147- // field_info
148- // ---------------------------------------------------------------------------
149-
150124struct field_info {
151- std::string_view name; // canonical wire name
152- std::span<const std::string_view> aliases; // alias names
153- std::size_t offset; // byte offset from struct start
154- std::size_t physical_index; // original C++ struct field index
155- const type_info* type; // recursive type descriptor (wire view)
156-
157- // Level 1 flags
158- bool has_default; // schema::default_value
159- bool is_literal; // schema::literal
160- bool has_skip_if; // behavior::skip_if present
161- bool has_behavior; // with/as/enum_string present
125+ std::string_view name;
126+ std::span<const std::string_view> aliases;
127+ std::size_t offset;
128+ std::size_t physical_index;
129+ const type_info* type;
130+
131+ bool has_default;
132+ bool is_literal;
133+ bool has_skip_if;
134+ bool has_behavior;
162135};
163136
164- // / struct — placed after field_info so that std::span<const field_info> sees a complete type.
165137struct struct_type_info : type_info {
166138 std::span<const field_info> fields;
167139 bool is_trivial_layout;
168140};
169141
170- // ---------------------------------------------------------------------------
171- // schema_opaque — opt-out from recursive type decomposition
172- // ---------------------------------------------------------------------------
173-
174- // / Types marked schema_opaque are treated as opaque by the schema system.
175- // / They get kind=unknown and are not recursively decomposed in type_info_instance.
176- // / Backend-specific serialize/deserialize hooks handle these types directly.
177142template <typename T>
178143constexpr inline bool schema_opaque = false ;
179144
180- // ---------------------------------------------------------------------------
181- // kind_of<T>() — map C++ types to type_kind values
182- // ---------------------------------------------------------------------------
183-
184145namespace detail {
185146
186- // / Map signed integer types to their exact-width type_kind.
187147template <typename T>
188148consteval type_kind signed_int_kind () {
189149 if constexpr (sizeof (T) == 1 ) {
@@ -198,7 +158,6 @@ consteval type_kind signed_int_kind() {
198158 }
199159}
200160
201- // / Map unsigned integer types to their exact-width type_kind.
202161template <typename T>
203162consteval type_kind unsigned_int_kind () {
204163 if constexpr (sizeof (T) == 1 ) {
@@ -213,7 +172,6 @@ consteval type_kind unsigned_int_kind() {
213172 }
214173}
215174
216- // / Map floating-point types to their type_kind.
217175template <typename T>
218176consteval type_kind floating_kind () {
219177 if constexpr (sizeof (T) <= 4 ) {
@@ -225,82 +183,42 @@ consteval type_kind floating_kind() {
225183
226184} // namespace detail
227185
228- // / Map a C++ type to its type_kind value.
229- // /
230- // / Scalars yield fine-grained kinds (int8, float64, etc.);
231- // / compound types yield broad categories (array, map, structure, etc.).
232- // /
233- // / The ordering of checks mirrors the dispatch chain in serde.h:
234- // / annotated_type -> enum -> bool -> int -> uint -> float -> char ->
235- // / str -> bytes -> null -> optional -> pointer -> variant -> tuple ->
236- // / range -> reflectable_class
237186template <typename T>
238187consteval type_kind kind_of () {
239188 using V = std::remove_cvref_t <T>;
240189
241- // Unwrap annotation to get the underlying type
242190 if constexpr (serde::annotated_type<V>) {
243191 return kind_of<typename V::annotated_type>();
244- }
245- // Opaque types with custom hooks — do not decompose
246- else if constexpr (schema_opaque<V>) {
192+ } else if constexpr (schema_opaque<V>) {
247193 return type_kind::unknown;
248- }
249- // Enum -> enumeration
250- else if constexpr (std::is_enum_v<V>) {
194+ } else if constexpr (std::is_enum_v<V>) {
251195 return type_kind::enumeration;
252- }
253- // Bool
254- else if constexpr (serde::bool_like<V>) {
196+ } else if constexpr (serde::bool_like<V>) {
255197 return type_kind::boolean;
256- }
257- // Signed integers — size-based dispatch
258- else if constexpr (serde::int_like<V>) {
198+ } else if constexpr (serde::int_like<V>) {
259199 return detail::signed_int_kind<V>();
260- }
261- // Unsigned integers — size-based dispatch
262- else if constexpr (serde::uint_like<V>) {
200+ } else if constexpr (serde::uint_like<V>) {
263201 return detail::unsigned_int_kind<V>();
264- }
265- // Floating-point
266- else if constexpr (serde::floating_like<V>) {
202+ } else if constexpr (serde::floating_like<V>) {
267203 return detail::floating_kind<V>();
268- }
269- // Character
270- else if constexpr (serde::char_like<V>) {
204+ } else if constexpr (serde::char_like<V>) {
271205 return type_kind::character;
272- }
273- // String
274- else if constexpr (serde::str_like<V>) {
206+ } else if constexpr (serde::str_like<V>) {
275207 return type_kind::string;
276- }
277- // Bytes
278- else if constexpr (serde::bytes_like<V>) {
208+ } else if constexpr (serde::bytes_like<V>) {
279209 return type_kind::bytes;
280- }
281- // Null
282- else if constexpr (serde::null_like<V>) {
210+ } else if constexpr (serde::null_like<V>) {
283211 return type_kind::null;
284- }
285- // Optional
286- else if constexpr (is_optional_v<V>) {
212+ } else if constexpr (is_optional_v<V>) {
287213 return type_kind::optional;
288- }
289- // Smart pointers
290- else if constexpr (is_specialization_of<std::unique_ptr, V> ||
291- is_specialization_of<std::shared_ptr, V>) {
214+ } else if constexpr (is_specialization_of<std::unique_ptr, V> ||
215+ is_specialization_of<std::shared_ptr, V>) {
292216 return type_kind::pointer;
293- }
294- // Variant
295- else if constexpr (is_specialization_of<std::variant, V>) {
217+ } else if constexpr (is_specialization_of<std::variant, V>) {
296218 return type_kind::variant;
297- }
298- // Tuple / pair (before range, since some tuples might satisfy range)
299- else if constexpr (serde::tuple_like<V>) {
219+ } else if constexpr (serde::tuple_like<V>) {
300220 return type_kind::tuple;
301- }
302- // Range types: map / set / sequence
303- else if constexpr (std::ranges::input_range<V>) {
221+ } else if constexpr (std::ranges::input_range<V>) {
304222 constexpr auto fmt = format_kind<V>;
305223 if constexpr (fmt == range_format::map) {
306224 return type_kind::map;
@@ -309,13 +227,9 @@ consteval type_kind kind_of() {
309227 } else {
310228 return type_kind::array;
311229 }
312- }
313- // Reflectable struct
314- else if constexpr (refl::reflectable_class<V>) {
230+ } else if constexpr (refl::reflectable_class<V>) {
315231 return type_kind::structure;
316- }
317- // Unknown — no matching category
318- else {
232+ } else {
319233 return type_kind::unknown;
320234 }
321235}
0 commit comments