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