@@ -2007,6 +2007,46 @@ CANARD_INTERNAL bool tableDecodeCore(const CanardCodingTableEntry* entry,
20072007 break ;
20082008 }
20092009
2010+ case CANARD_TABLE_CODING_UNION : {
2011+ uint8_t num_tags = bitlen ;
2012+ const CanardCodingTableEntry * aux = ++ entry ;
2013+ const CanardCodingTableEntry * union_header = ++ entry ;
2014+ const CanardCodingTableEntry * union_entry = union_header + num_tags ;
2015+
2016+ uint8_t union_tag ;
2017+ uint8_t tag_bitlen = aux -> bitlen ;
2018+ canardDecodeScalar (transfer , * bit_ofs , tag_bitlen , false, & union_tag );
2019+ * bit_ofs += tag_bitlen ;
2020+ if (union_tag >= num_tags ) {
2021+ return true; // invalid value
2022+ }
2023+
2024+ void * tag_p = (char * )msg + aux -> offset ;
2025+ // we know 254 is the max tag value, but the chars taken is compiler dependent
2026+ if (sizeof (CanardCodingTableUnionEnum ) == sizeof (uint8_t )) {
2027+ * (uint8_t * )tag_p = union_tag ;
2028+ } else if (sizeof (CanardCodingTableUnionEnum ) == sizeof (uint16_t )) {
2029+ * (uint16_t * )tag_p = union_tag ;
2030+ } else if (sizeof (CanardCodingTableUnionEnum ) == sizeof (uint32_t )) {
2031+ * (uint32_t * )tag_p = union_tag ;
2032+ } else {
2033+ * (uint64_t * )tag_p = union_tag ;
2034+ }
2035+
2036+ // check each tag so we can keep track of the entry pointers
2037+ for (uint8_t tag = 0 ; tag < num_tags ; tag ++ ) {
2038+ uint8_t num_entries = (union_header ++ )-> bitlen ;
2039+ if (num_entries && tag == union_tag ) { // can't decode 0 entries, so check that in addition to match
2040+ tableDecodeCore (union_entry , union_entry + num_entries - 1 , transfer , bit_ofs , p , tao );
2041+ }
2042+ union_entry += num_entries ;
2043+ }
2044+
2045+ entry = union_entry - 1 ; // point entry to last for ++entry at end of loop
2046+
2047+ break ;
2048+ }
2049+
20102050 default :
20112051 return true; // invalid type
20122052 }
@@ -2108,6 +2148,44 @@ CANARD_INTERNAL void tableEncodeCore(const CanardCodingTableEntry* entry,
21082148 break ;
21092149 }
21102150
2151+ case CANARD_TABLE_CODING_UNION : {
2152+ uint8_t num_fields = bitlen ;
2153+ const CanardCodingTableEntry * aux = ++ entry ;
2154+ const CanardCodingTableEntry * union_header = ++ entry ;
2155+ const CanardCodingTableEntry * union_entry = union_header + num_fields ;
2156+
2157+ const void * tag_p = (const char * )msg + aux -> offset ;
2158+ uint8_t union_tag ;
2159+ // we know 254 is the max tag value, but the chars taken is compiler dependent
2160+ if (sizeof (CanardCodingTableUnionEnum ) == sizeof (uint8_t )) {
2161+ union_tag = (uint8_t )* (const uint8_t * )tag_p ;
2162+ } else if (sizeof (CanardCodingTableUnionEnum ) == sizeof (uint16_t )) {
2163+ union_tag = (uint16_t )* (const uint16_t * )tag_p ;
2164+ } else if (sizeof (CanardCodingTableUnionEnum ) == sizeof (uint32_t )) {
2165+ union_tag = (uint32_t )* (const uint32_t * )tag_p ;
2166+ } else {
2167+ union_tag = (uint64_t )* (const uint64_t * )tag_p ;
2168+ }
2169+ // the native type is an enum so assume it can't be out of range
2170+
2171+ uint8_t tag_bitlen = aux -> bitlen ;
2172+ canardEncodeScalar (buffer , * bit_ofs , tag_bitlen , & union_tag );
2173+ * bit_ofs += tag_bitlen ;
2174+
2175+ // check each tag so we can keep track of the entry pointers
2176+ for (uint8_t tag = 0 ; tag < num_fields ; tag ++ ) {
2177+ uint8_t num_entries = (union_header ++ )-> bitlen ;
2178+ if (num_entries && tag == union_tag ) { // can't encode 0 entries, so check that in addition to match
2179+ tableEncodeCore (union_entry , union_entry + num_entries - 1 , buffer , bit_ofs , p , tao );
2180+ }
2181+ union_entry += num_entries ;
2182+ }
2183+
2184+ entry = union_entry - 1 ; // point entry to last for ++entry at end of loop
2185+
2186+ break ;
2187+ }
2188+
21112189 default :
21122190 return ; // invalid type
21132191 }
0 commit comments