11#include < csp/engine/InputId.h>
22#include < csp/engine/Node.h>
33#include < csp/engine/CspEnum.h>
4+ #include < csp/engine/PartialSwitchCspType.h>
45#include < csp/engine/Struct.h>
56#include < csp/python/Conversions.h>
67#include < csp/python/Exception.h>
1718#include < unordered_map>
1819#include < cstring>
1920#include < iostream>
21+ #include < type_traits>
2022
2123namespace csp ::python
2224{
@@ -30,18 +32,54 @@ extern "C" CSPIMPL_EXPORT int64_t csp_numba_struct_enum_field_value( const void
3032 return enumField -> value ();
3133}
3234
33- extern " C" CSPIMPL_EXPORT void csp_numba_struct_enum_field_set ( void * struct_ptr, int64_t field_offset, int64_t value )
35+ extern " C" CSPIMPL_EXPORT void csp_numba_struct_enum_field_set (
36+ void * struct_ptr,
37+ int64_t field_offset,
38+ int64_t value,
39+ const void * struct_type
40+ )
3441{
35- // Rebuild the field from its existing enum meta rather than treating the
36- // destination as a raw int64 slot.
37- char * bytes = static_cast <char *>( struct_ptr );
38- auto * enumField = reinterpret_cast <CspEnum *>( bytes + field_offset );
39- *enumField = enumField -> meta () -> create ( value );
42+ // An unset enum field does not contain enum metadata. Resolve the declared
43+ // field type through the owning struct type and use the field setter so its
44+ // set bit is updated as well.
45+ const auto * pyStructMeta = static_cast <const PyStructMeta *>( struct_type );
46+ const auto & fields = pyStructMeta -> structMeta -> fields ();
47+ auto fieldIt = std::find_if ( fields.begin (), fields.end (), [field_offset]( const auto & field )
48+ {
49+ return field -> offset () == static_cast <size_t >( field_offset );
50+ } );
51+ CSP_ASSERT ( fieldIt != fields.end () );
52+ CSP_ASSERT ( ( *fieldIt ) -> type () -> type () == CspType::Type::ENUM );
53+
54+ const auto * enumType = static_cast <const CspEnumType *>( ( *fieldIt ) -> type ().get () );
55+ ( *fieldIt ) -> setValue<CspEnum>(
56+ static_cast <Struct *>( struct_ptr ),
57+ enumType -> meta () -> create ( value )
58+ );
4059}
4160
4261namespace
4362{
4463constexpr size_t OUTPUT_VALUE_SLOT_BYTES = sizeof ( int64_t );
64+
65+ using NumbaInputTypeSwitch = PartialSwitchCspType<
66+ CspType::Type::BOOL ,
67+ CspType::Type::INT64 ,
68+ CspType::Type::DOUBLE ,
69+ CspType::Type::DATETIME ,
70+ CspType::Type::TIMEDELTA ,
71+ CspType::Type::ENUM ,
72+ CspType::Type::STRUCT
73+ >;
74+
75+ using NumbaOutputTypeSwitch = PartialSwitchCspType<
76+ CspType::Type::BOOL ,
77+ CspType::Type::INT64 ,
78+ CspType::Type::DOUBLE ,
79+ CspType::Type::DATETIME ,
80+ CspType::Type::TIMEDELTA ,
81+ CspType::Type::ENUM
82+ >;
4583}
4684
4785PyNumbaNode::PyNumbaNode (
@@ -303,33 +341,21 @@ void PyNumbaNode::executeImpl()
303341 {
304342 const CspType * cspType = ts -> type ();
305343 CSP_ASSERT ( cspType != nullptr );
306- switch ( cspType -> type () )
344+ NumbaInputTypeSwitch::invoke ( cspType, [ this , ts, i]( auto tag )
307345 {
308- case CspType::Type::INT64 :
309- m_inputArgs[ i ] = &( ts -> lastValueTyped<int64_t >() );
310- break ;
311- case CspType::Type::DOUBLE :
312- m_inputArgs[ i ] = &( ts -> lastValueTyped<double >() );
313- break ;
314- case CspType::Type::BOOL :
315- m_inputArgs[ i ] = &( ts -> lastValueTyped<bool >() );
316- break ;
317- case CspType::Type::DATETIME :
318- m_inputArgs[ i ] = &( ts -> lastValueTyped<DateTime>() );
319- break ;
320- case CspType::Type::TIMEDELTA :
321- m_inputArgs[ i ] = &( ts -> lastValueTyped<TimeDelta>() );
322- break ;
323- case CspType::Type::ENUM :
346+ using CType = typename decltype ( tag )::type;
347+ if constexpr ( std::is_same_v<CType, CspEnum> )
348+ {
324349 m_inputEnumStorage[ i ] = ts -> lastValueTyped<CspEnum>().value ();
325350 m_inputArgs[ i ] = &m_inputEnumStorage[ i ];
326- break ;
327- case CspType::Type::STRUCT :
351+ }
352+ else if constexpr ( std::is_same_v<CType, StructPtr> )
353+ {
328354 m_inputArgs[ i ] = ts -> lastValueTyped<StructPtr>().get ();
329- break ;
330- default :
331- break ;
332- }
355+ }
356+ else
357+ m_inputArgs[ i ] = &( ts -> lastValueTyped<CType>() ) ;
358+ } );
333359 }
334360 }
335361 }
@@ -360,52 +386,38 @@ void PyNumbaNode::executeImpl()
360386 {
361387 const CspType * cspType = ts -> type ();
362388 CSP_ASSERT ( cspType != nullptr );
363- switch ( cspType -> type () )
389+ NumbaOutputTypeSwitch::invoke ( cspType, [ this , ts, cspType, i, currentCycleCount, currentTime]( auto tag )
364390 {
365- case CspType::Type::INT64 :
366- ts -> outputTickTyped<int64_t >(
367- currentCycleCount, currentTime,
368- *static_cast <int64_t *>( m_outputValueSlots[ i ] )
369- );
370- break ;
371- case CspType::Type::DOUBLE :
372- ts -> outputTickTyped<double >(
373- currentCycleCount, currentTime,
374- *static_cast <double *>( m_outputValueSlots[ i ] )
375- );
376- break ;
377- case CspType::Type::BOOL :
378- ts -> outputTickTyped<bool >(
379- currentCycleCount, currentTime,
380- *static_cast <bool *>( m_outputValueSlots[ i ] )
381- );
382- break ;
383- case CspType::Type::DATETIME :
391+ using CType = typename decltype ( tag )::type;
392+ if constexpr ( std::is_same_v<CType, DateTime> )
393+ {
384394 ts -> outputTickTyped<DateTime>(
385395 currentCycleCount, currentTime,
386396 DateTime::fromNanoseconds ( *static_cast <int64_t *>( m_outputValueSlots[ i ] ) )
387397 );
388- break ;
389- case CspType::Type::TIMEDELTA :
398+ }
399+ else if constexpr ( std::is_same_v<CType, TimeDelta> )
400+ {
390401 ts -> outputTickTyped<TimeDelta>(
391402 currentCycleCount, currentTime,
392403 TimeDelta::fromNanoseconds ( *static_cast <int64_t *>( m_outputValueSlots[ i ] ) )
393404 );
394- break ;
395- case CspType::Type:: ENUM :
405+ }
406+ else if constexpr ( std::is_same_v<CType, CspEnum> )
396407 {
397408 auto enumType = static_cast <const CspEnumType *>( cspType );
398409 int64_t enumValue = *static_cast <int64_t *>( m_outputValueSlots[ i ] );
399- CspEnum enumInstance = enumType -> meta () -> create ( enumValue );
400410 ts -> outputTickTyped<CspEnum>(
401411 currentCycleCount, currentTime,
402- enumInstance
412+ enumType -> meta () -> create ( enumValue )
403413 );
404- break ;
405414 }
406- default :
407- break ;
408- }
415+ else
416+ ts -> outputTickTyped<CType>(
417+ currentCycleCount, currentTime,
418+ *static_cast <CType *>( m_outputValueSlots[ i ] )
419+ );
420+ } );
409421 }
410422 }
411423 }
0 commit comments