@@ -14,9 +14,9 @@ use rayon::prelude::*;
14
14
use crate :: {
15
15
codegen:: { autogen_warning, common:: collect_examples_for_api_docs} ,
16
16
format_path,
17
- objects:: ObjectType ,
18
- ArrowRegistry , Docs , ElementType , GeneratedFiles , Object , ObjectField , ObjectKind ,
19
- ObjectSpecifics , Objects , Reporter , Type , ATTR_CPP_NO_FIELD_CTORS ,
17
+ objects:: ObjectClass ,
18
+ ArrowRegistry , Docs , ElementType , GeneratedFiles , Object , ObjectField , ObjectKind , Objects ,
19
+ Reporter , Type , ATTR_CPP_NO_FIELD_CTORS ,
20
20
} ;
21
21
22
22
use self :: array_builder:: { arrow_array_builder_type, arrow_array_builder_type_object} ;
@@ -381,14 +381,15 @@ struct QuotedObject {
381
381
}
382
382
383
383
impl QuotedObject {
384
+ #[ allow( clippy:: unnecessary_wraps) ] // TODO(emilk): implement proper error handling instead of panicking
384
385
pub fn new (
385
386
objects : & Objects ,
386
387
obj : & Object ,
387
388
hpp_includes : Includes ,
388
389
hpp_type_extensions : & TokenStream ,
389
390
) -> Result < Self > {
390
- match obj. typ ( ) {
391
- ObjectType :: Struct => match obj. kind {
391
+ match obj. class {
392
+ ObjectClass :: Struct => match obj. kind {
392
393
ObjectKind :: Datatype | ObjectKind :: Component => Ok ( Self :: from_struct (
393
394
objects,
394
395
obj,
@@ -399,15 +400,13 @@ impl QuotedObject {
399
400
Ok ( Self :: from_archetype ( obj, hpp_includes, hpp_type_extensions) )
400
401
}
401
402
} ,
402
- ObjectType :: Union => Ok ( Self :: from_union (
403
+ ObjectClass :: Enum => Ok ( Self :: from_enum ( objects, obj, hpp_includes) ) ,
404
+ ObjectClass :: Union => Ok ( Self :: from_union (
403
405
objects,
404
406
obj,
405
407
hpp_includes,
406
408
hpp_type_extensions,
407
409
) ) ,
408
- ObjectType :: Enum => {
409
- anyhow:: bail!( "Enums are not implemented in C++" )
410
- }
411
410
}
412
411
}
413
412
@@ -1160,6 +1159,78 @@ impl QuotedObject {
1160
1159
1161
1160
Self { hpp, cpp }
1162
1161
}
1162
+
1163
+ // C-style enum
1164
+ fn from_enum ( objects : & Objects , obj : & Object , mut hpp_includes : Includes ) -> QuotedObject {
1165
+ // We use a simple `enum class`, which is a type-safe enum.
1166
+ // They don't support methods, but we don't need them,
1167
+ // since `Loggable` is implemented outside the type.
1168
+
1169
+ let namespace_ident = obj. namespace_ident ( ) ;
1170
+
1171
+ let quoted_namespace = if let Some ( scope) = obj. scope ( ) {
1172
+ let scope = format_ident ! ( "{}" , scope) ;
1173
+ quote ! { #scope:: #namespace_ident}
1174
+ } else {
1175
+ quote ! { #namespace_ident}
1176
+ } ;
1177
+
1178
+ let type_ident = obj. ident ( ) ;
1179
+ let quoted_docs = quote_obj_docs ( obj) ;
1180
+ let deprecation_notice = quote_deprecation_notice ( obj) ;
1181
+
1182
+ let mut cpp_includes = Includes :: new ( obj. fqname . clone ( ) , obj. scope ( ) ) ;
1183
+ let mut hpp_declarations = ForwardDecls :: default ( ) ;
1184
+
1185
+ let field_declarations = obj
1186
+ . fields
1187
+ . iter ( )
1188
+ . enumerate ( )
1189
+ . map ( |( i, obj_field) | {
1190
+ let docstring = quote_field_docs ( obj_field) ;
1191
+ let field_name = format_ident ! ( "{}" , obj_field. name) ;
1192
+
1193
+ // We assign the arrow type index to the enum fields to make encoding simpler and faster:
1194
+ let arrow_type_index = proc_macro2:: Literal :: usize_unsuffixed ( 1 + i) ; // 0 is reserved for `_null_markers`
1195
+
1196
+ quote ! {
1197
+ #NEWLINE_TOKEN
1198
+ #docstring
1199
+ #field_name = #arrow_type_index
1200
+ }
1201
+ } )
1202
+ . collect_vec ( ) ;
1203
+
1204
+ let ( hpp_loggable, cpp_loggable) = quote_loggable_hpp_and_cpp (
1205
+ obj,
1206
+ objects,
1207
+ & mut hpp_includes,
1208
+ & mut cpp_includes,
1209
+ & mut hpp_declarations,
1210
+ ) ;
1211
+
1212
+ let hpp = quote ! {
1213
+ #hpp_includes
1214
+
1215
+ #hpp_declarations
1216
+
1217
+ namespace rerun:: #quoted_namespace {
1218
+ #quoted_docs
1219
+ enum class #deprecation_notice #type_ident : uint8_t {
1220
+ #( #field_declarations, ) *
1221
+ } ;
1222
+ }
1223
+
1224
+ #hpp_loggable
1225
+ } ;
1226
+ let cpp = quote ! {
1227
+ #cpp_includes
1228
+
1229
+ #cpp_loggable
1230
+ } ;
1231
+
1232
+ Self { hpp, cpp }
1233
+ }
1163
1234
}
1164
1235
1165
1236
fn single_field_constructor_methods (
@@ -1515,22 +1586,22 @@ fn quote_fill_arrow_array_builder(
1515
1586
}
1516
1587
}
1517
1588
} else {
1518
- match obj. specifics {
1519
- ObjectSpecifics :: Struct => {
1589
+ match obj. class {
1590
+ ObjectClass :: Struct => {
1520
1591
let fill_fields = obj. fields . iter ( ) . enumerate ( ) . map (
1521
- |( field_index, field) | {
1522
- let field_index = quote_integer ( field_index) ;
1523
- let field_builder = format_ident ! ( "field_builder" ) ;
1524
- let field_builder_type = arrow_array_builder_type ( & field. typ , objects) ;
1525
- let field_append = quote_append_field_to_builder ( field, & field_builder, false , includes, objects) ;
1526
- quote ! {
1527
- {
1528
- auto #field_builder = static_cast<arrow:: #field_builder_type* >( builder->field_builder( #field_index) ) ;
1529
- #field_append
1592
+ |( field_index, field) | {
1593
+ let field_index = quote_integer ( field_index) ;
1594
+ let field_builder = format_ident ! ( "field_builder" ) ;
1595
+ let field_builder_type = arrow_array_builder_type ( & field. typ , objects) ;
1596
+ let field_append = quote_append_field_to_builder ( field, & field_builder, false , includes, objects) ;
1597
+ quote ! {
1598
+ {
1599
+ auto #field_builder = static_cast<arrow:: #field_builder_type* >( builder->field_builder( #field_index) ) ;
1600
+ #field_append
1601
+ }
1530
1602
}
1531
- }
1532
- } ,
1533
- ) ;
1603
+ } ,
1604
+ ) ;
1534
1605
1535
1606
quote ! {
1536
1607
#parameter_check
@@ -1539,7 +1610,21 @@ fn quote_fill_arrow_array_builder(
1539
1610
ARROW_RETURN_NOT_OK ( builder->AppendValues ( static_cast<int64_t>( num_elements) , nullptr) ) ;
1540
1611
}
1541
1612
}
1542
- ObjectSpecifics :: Union { .. } => {
1613
+
1614
+ // C-style enum, encoded as a sparse arrow union
1615
+ ObjectClass :: Enum => {
1616
+ quote ! {
1617
+ #parameter_check
1618
+ ARROW_RETURN_NOT_OK ( #builder->Reserve ( static_cast<int64_t>( num_elements) ) ) ;
1619
+ for ( size_t elem_idx = 0 ; elem_idx < num_elements; elem_idx += 1 ) {
1620
+ const auto variant = elements[ elem_idx] ;
1621
+ ARROW_RETURN_NOT_OK ( #builder->Append ( static_cast<int8_t>( variant) ) ) ;
1622
+ }
1623
+ }
1624
+ }
1625
+
1626
+ // sum-type union, encoded as a dense arrow union
1627
+ ObjectClass :: Union => {
1543
1628
let variant_builder = format_ident ! ( "variant_builder" ) ;
1544
1629
1545
1630
let tag_cases = obj. fields
@@ -2227,16 +2312,25 @@ fn quote_arrow_data_type(
2227
2312
. iter ( )
2228
2313
. map ( |field| quote_arrow_field_type ( field, objects, includes) ) ;
2229
2314
2230
- match & obj. specifics {
2231
- ObjectSpecifics :: Union { .. } => {
2315
+ match & obj. class {
2316
+ ObjectClass :: Struct => {
2317
+ quote ! ( arrow:: struct_( { #( #quoted_fields, ) * } ) )
2318
+ }
2319
+ ObjectClass :: Enum => {
2232
2320
quote ! {
2233
- arrow:: dense_union( {
2234
- arrow:: field( "_null_markers" , arrow:: null( ) , true , nullptr) , #( #quoted_fields, ) *
2321
+ arrow:: sparse_union( {
2322
+ arrow:: field( "_null_markers" , arrow:: null( ) , true , nullptr) ,
2323
+ #( #quoted_fields, ) *
2235
2324
} )
2236
2325
}
2237
2326
}
2238
- ObjectSpecifics :: Struct => {
2239
- quote ! ( arrow:: struct_( { #( #quoted_fields, ) * } ) )
2327
+ ObjectClass :: Union => {
2328
+ quote ! {
2329
+ arrow:: dense_union( {
2330
+ arrow:: field( "_null_markers" , arrow:: null( ) , true , nullptr) ,
2331
+ #( #quoted_fields, ) *
2332
+ } )
2333
+ }
2240
2334
}
2241
2335
}
2242
2336
}
0 commit comments