@@ -1990,6 +1990,46 @@ CANARD_INTERNAL bool tableDecodeCore(const CanardCodingTableEntry* entry,
19901990 break ;
19911991 }
19921992
1993+ case CANARD_TABLE_CODING_UNION : {
1994+ uint8_t num_tags = bitlen ;
1995+ const CanardCodingTableEntry * aux = ++ entry ;
1996+ const CanardCodingTableEntry * union_header = ++ entry ;
1997+ const CanardCodingTableEntry * union_entry = union_header + num_tags ;
1998+
1999+ uint8_t union_tag ;
2000+ uint8_t tag_bitlen = aux -> bitlen ;
2001+ canardDecodeScalar (transfer , * bit_ofs , tag_bitlen , false, & union_tag );
2002+ * bit_ofs += tag_bitlen ;
2003+ if (union_tag >= num_tags ) {
2004+ return true; // invalid value
2005+ }
2006+
2007+ void * tag_p = (char * )msg + aux -> offset ;
2008+ // we know 254 is the max tag value, but the chars taken is compiler dependent
2009+ if (sizeof (CanardCodingTableUnionEnum ) == sizeof (uint8_t )) {
2010+ * (uint8_t * )tag_p = union_tag ;
2011+ } else if (sizeof (CanardCodingTableUnionEnum ) == sizeof (uint16_t )) {
2012+ * (uint16_t * )tag_p = union_tag ;
2013+ } else if (sizeof (CanardCodingTableUnionEnum ) == sizeof (uint32_t )) {
2014+ * (uint32_t * )tag_p = union_tag ;
2015+ } else {
2016+ * (uint64_t * )tag_p = union_tag ;
2017+ }
2018+
2019+ // check each tag so we can keep track of the entry pointers
2020+ for (uint8_t tag = 0 ; tag < num_tags ; tag ++ ) {
2021+ uint8_t num_entries = (union_header ++ )-> bitlen ;
2022+ if (num_entries && tag == union_tag ) { // can't decode 0 entries, so check that in addition to match
2023+ tableDecodeCore (union_entry , union_entry + num_entries - 1 , transfer , bit_ofs , p , tao );
2024+ }
2025+ union_entry += num_entries ;
2026+ }
2027+
2028+ entry = union_entry - 1 ; // point entry to last for ++entry at end of loop
2029+
2030+ break ;
2031+ }
2032+
19932033 default :
19942034 return true; // invalid type
19952035 }
@@ -2088,6 +2128,44 @@ CANARD_INTERNAL void tableEncodeCore(const CanardCodingTableEntry* entry,
20882128 break ;
20892129 }
20902130
2131+ case CANARD_TABLE_CODING_UNION : {
2132+ uint8_t num_fields = bitlen ;
2133+ const CanardCodingTableEntry * aux = ++ entry ;
2134+ const CanardCodingTableEntry * union_header = ++ entry ;
2135+ const CanardCodingTableEntry * union_entry = union_header + num_fields ;
2136+
2137+ const void * tag_p = (const char * )msg + aux -> offset ;
2138+ uint8_t union_tag ;
2139+ // we know 254 is the max tag value, but the chars taken is compiler dependent
2140+ if (sizeof (CanardCodingTableUnionEnum ) == sizeof (uint8_t )) {
2141+ union_tag = (uint8_t )* (const uint8_t * )tag_p ;
2142+ } else if (sizeof (CanardCodingTableUnionEnum ) == sizeof (uint16_t )) {
2143+ union_tag = (uint16_t )* (const uint16_t * )tag_p ;
2144+ } else if (sizeof (CanardCodingTableUnionEnum ) == sizeof (uint32_t )) {
2145+ union_tag = (uint32_t )* (const uint32_t * )tag_p ;
2146+ } else {
2147+ union_tag = (uint64_t )* (const uint64_t * )tag_p ;
2148+ }
2149+ // the native type is an enum so assume it can't be out of range
2150+
2151+ uint8_t tag_bitlen = aux -> bitlen ;
2152+ canardEncodeScalar (buffer , * bit_ofs , tag_bitlen , & union_tag );
2153+ * bit_ofs += tag_bitlen ;
2154+
2155+ // check each tag so we can keep track of the entry pointers
2156+ for (uint8_t tag = 0 ; tag < num_fields ; tag ++ ) {
2157+ uint8_t num_entries = (union_header ++ )-> bitlen ;
2158+ if (num_entries && tag == union_tag ) { // can't encode 0 entries, so check that in addition to match
2159+ tableEncodeCore (union_entry , union_entry + num_entries - 1 , buffer , bit_ofs , p , tao );
2160+ }
2161+ union_entry += num_entries ;
2162+ }
2163+
2164+ entry = union_entry - 1 ; // point entry to last for ++entry at end of loop
2165+
2166+ break ;
2167+ }
2168+
20912169 default :
20922170 return ; // invalid type
20932171 }
0 commit comments