@@ -2015,6 +2015,46 @@ CANARD_INTERNAL bool tableDecodeCore(const CanardCodingTableEntry* entry,
20152015 break ;
20162016 }
20172017
2018+ case CANARD_TABLE_CODING_UNION : {
2019+ uint8_t num_tags = bitlen ;
2020+ const CanardCodingTableEntry * aux = ++ entry ;
2021+ const CanardCodingTableEntry * union_header = ++ entry ;
2022+ const CanardCodingTableEntry * union_entry = union_header + num_tags ;
2023+
2024+ uint8_t union_tag ;
2025+ uint8_t tag_bitlen = aux -> bitlen ;
2026+ canardDecodeScalar (transfer , * bit_ofs , tag_bitlen , false, & union_tag );
2027+ * bit_ofs += tag_bitlen ;
2028+ if (union_tag >= num_tags ) {
2029+ return true; // invalid value
2030+ }
2031+
2032+ void * tag_p = (char * )msg + aux -> offset ;
2033+ // we know 254 is the max tag value, but the chars taken is compiler dependent
2034+ if (sizeof (CanardCodingTableUnionEnum ) == sizeof (uint8_t )) {
2035+ * (uint8_t * )tag_p = union_tag ;
2036+ } else if (sizeof (CanardCodingTableUnionEnum ) == sizeof (uint16_t )) {
2037+ * (uint16_t * )tag_p = union_tag ;
2038+ } else if (sizeof (CanardCodingTableUnionEnum ) == sizeof (uint32_t )) {
2039+ * (uint32_t * )tag_p = union_tag ;
2040+ } else {
2041+ * (uint64_t * )tag_p = union_tag ;
2042+ }
2043+
2044+ // check each tag so we can keep track of the entry pointers
2045+ for (uint8_t tag = 0 ; tag < num_tags ; tag ++ ) {
2046+ uint8_t num_entries = (union_header ++ )-> bitlen ;
2047+ if (num_entries && tag == union_tag ) { // can't decode 0 entries, so check that in addition to match
2048+ tableDecodeCore (union_entry , union_entry + num_entries - 1 , transfer , bit_ofs , p , tao );
2049+ }
2050+ union_entry += num_entries ;
2051+ }
2052+
2053+ entry = union_entry - 1 ; // point entry to last for ++entry at end of loop
2054+
2055+ break ;
2056+ }
2057+
20182058 default :
20192059 return true; // invalid type
20202060 }
@@ -2116,6 +2156,44 @@ CANARD_INTERNAL void tableEncodeCore(const CanardCodingTableEntry* entry,
21162156 break ;
21172157 }
21182158
2159+ case CANARD_TABLE_CODING_UNION : {
2160+ uint8_t num_fields = bitlen ;
2161+ const CanardCodingTableEntry * aux = ++ entry ;
2162+ const CanardCodingTableEntry * union_header = ++ entry ;
2163+ const CanardCodingTableEntry * union_entry = union_header + num_fields ;
2164+
2165+ const void * tag_p = (const char * )msg + aux -> offset ;
2166+ uint8_t union_tag ;
2167+ // we know 254 is the max tag value, but the chars taken is compiler dependent
2168+ if (sizeof (CanardCodingTableUnionEnum ) == sizeof (uint8_t )) {
2169+ union_tag = (uint8_t )* (const uint8_t * )tag_p ;
2170+ } else if (sizeof (CanardCodingTableUnionEnum ) == sizeof (uint16_t )) {
2171+ union_tag = (uint16_t )* (const uint16_t * )tag_p ;
2172+ } else if (sizeof (CanardCodingTableUnionEnum ) == sizeof (uint32_t )) {
2173+ union_tag = (uint32_t )* (const uint32_t * )tag_p ;
2174+ } else {
2175+ union_tag = (uint64_t )* (const uint64_t * )tag_p ;
2176+ }
2177+ // the native type is an enum so assume it can't be out of range
2178+
2179+ uint8_t tag_bitlen = aux -> bitlen ;
2180+ canardEncodeScalar (buffer , * bit_ofs , tag_bitlen , & union_tag );
2181+ * bit_ofs += tag_bitlen ;
2182+
2183+ // check each tag so we can keep track of the entry pointers
2184+ for (uint8_t tag = 0 ; tag < num_fields ; tag ++ ) {
2185+ uint8_t num_entries = (union_header ++ )-> bitlen ;
2186+ if (num_entries && tag == union_tag ) { // can't encode 0 entries, so check that in addition to match
2187+ tableEncodeCore (union_entry , union_entry + num_entries - 1 , buffer , bit_ofs , p , tao );
2188+ }
2189+ union_entry += num_entries ;
2190+ }
2191+
2192+ entry = union_entry - 1 ; // point entry to last for ++entry at end of loop
2193+
2194+ break ;
2195+ }
2196+
21192197 default :
21202198 return ; // invalid type
21212199 }
0 commit comments