# Wrong union tag size

**URL:** <https://forum.opencyphal.org/t/wrong-union-tag-size/688>\
**Category:** Libcanard\
**Created:** [November 19, 2019, 9:23am UTC](https://forum.opencyphal.org/t/wrong-union-tag-size/688 "2019-11-19T09:23:47Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![deekay](https://forum.opencyphal.org/letter_avatar_proxy/v4/letter/d/8491ac/32.png) [@deekay](https://forum.opencyphal.org/u/deekay)\
**Post date:** [November 19, 2019, 9:23am UTC](https://forum.opencyphal.org/t/wrong-union-tag-size/688/1 "2019-11-19T09:23:47Z")

</div>

I do not know if my topic below is related to [Custom message signature fail](https://forum.opencyphal.org/t/custom-message-signature-fail/372)  
but, here I go:

I have a DSDL definition that looks like:  
myDSDL.uavcan

```auto
@union
uint8 value1
uint8 value2
uint8 value3
uint8 value4

```

When compiled with libcanard dsdl\_compiler, I can see in the \_myDSDL\_encode\_internal(…) function that tag size is 3 bits, I expected 2…:

```auto
uint32_t test_MyDSDL_encode_internal(test_MyDSDL* source,
  void* msg_buf,
  uint32_t offset,
  uint8_t CANARD_MAYBE_UNUSED(root_item))
{
    // Max Union Tag Value
    CANARD_ASSERT(source->union_tag <= 3);

    // Union Tag 3 bits
    canardEncodeScalar(msg_buf, offset, 3, (void*)&source->union_tag); // 3 bits
    offset += 3;

    if (source->union_tag == 0) {
    canardEncodeScalar(msg_buf, offset, 8, (void*)&source->value1); // 255
    offset += 8;

    }
    else if (source->union_tag == 1) {
    canardEncodeScalar(msg_buf, offset, 8, (void*)&source->value2); // 255
    offset += 8;

    }
    else if (source->union_tag == 2) {
    canardEncodeScalar(msg_buf, offset, 8, (void*)&source->value3); // 255
    offset += 8;

    }
    else if (source->union_tag == 3) {
    canardEncodeScalar(msg_buf, offset, 8, (void*)&source->value4); // 255
    offset += 8;

    }

    return offset;
}

```

libuavcan compiler generates tag size = 2.

What is wrong?

Regards

---

<div class="post-metadata">

**Author:** ![pavel.kirienko](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/pavel.kirienko/32/9_2.png) [@pavel.kirienko](https://forum.opencyphal.org/u/pavel.kirienko)\
**Post date:** [November 19, 2019, 9:45am UTC](https://forum.opencyphal.org/t/wrong-union-tag-size/688/2 "2019-11-19T09:45:54Z")

</div>

The DSDL compiler in Libcanard was broken so we removed it. If you check the upstream, there is no compiler there. Please don’t use it.

---

<div class="post-metadata">

**Author:** ![deekay](https://forum.opencyphal.org/letter_avatar_proxy/v4/letter/d/8491ac/32.png) [@deekay](https://forum.opencyphal.org/u/deekay)\
**Post date:** [November 19, 2019, 9:49am UTC](https://forum.opencyphal.org/t/wrong-union-tag-size/688/3 "2019-11-19T09:49:55Z")

</div>

If compiling libcanard for v0, what compiler shall I use?

---

<div class="post-metadata">

**Author:** ![deekay](https://forum.opencyphal.org/letter_avatar_proxy/v4/letter/d/8491ac/32.png) [@deekay](https://forum.opencyphal.org/u/deekay)\
**Post date:** [November 19, 2019, 10:38am UTC](https://forum.opencyphal.org/t/wrong-union-tag-size/688/4 "2019-11-19T10:38:37Z")

</div>

If I am not completely wrong, is this the place were union is calculated?

In **init**.py:

```auto
    if t.kind == t.KIND_MESSAGE:
        t.has_array = inject_cpp_types(t.fields)
        t.has_float16 = has_float16(t.fields)
        inject_cpp_types(t.constants)
        t.all_attributes = t.fields + t.constants
        t.union = t.union and len(t.fields)
        if t.union:
            t.union = len(t.fields).bit_length()
    else:
        t.request_has_array = inject_cpp_types(t.request_fields)
        t.request_has_float16 = has_float16(t.request_fields)
        inject_cpp_types(t.request_constants)
        t.response_has_array = inject_cpp_types(t.response_fields)
        t.response_has_float16 = has_float16(t.response_fields)
        inject_cpp_types(t.response_constants)
        t.all_attributes = t.request_fields + t.request_constants + t.response_fields + t.response_constants
        t.request_union = t.request_union and len(t.request_fields)
        t.response_union = t.response_union and len(t.response_fields)
        if t.request_union:
            t.request_union = len(t.request_fields).bit_length()
        if t.response_union:
            t.response_union = len(t.response_fields).bit_length()

```

If so, to just fix my issue with wrong union tag size, can some of the above rows be changed to work properly?

---

<div class="post-metadata">

**Author:** ![pavel.kirienko](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/pavel.kirienko/32/9_2.png) [@pavel.kirienko](https://forum.opencyphal.org/u/pavel.kirienko)\
**Post date:** [November 19, 2019, 11:00am UTC](https://forum.opencyphal.org/t/wrong-union-tag-size/688/5 "2019-11-19T11:00:19Z")

</div>

> [@deekay](#):
>
> If compiling libcanard for v0, what compiler shall I use?

Currently, there is no DSDL compiler for libcanard. We may develop one later for v1.

> [@deekay](#):
>
> If so, to just fix my issue with wrong union tag size, can some of the above rows be changed to work properly?

I suppose you should subtract one from `len(...).bit_length()`.

---

<div class="post-metadata">

**Author:** ![deekay](https://forum.opencyphal.org/letter_avatar_proxy/v4/letter/d/8491ac/32.png) [@deekay](https://forum.opencyphal.org/u/deekay)\
**Post date:** [November 24, 2019, 1:21pm UTC](https://forum.opencyphal.org/t/wrong-union-tag-size/688/6 "2019-11-24T13:21:57Z")

</div>

Correct.  
`(len(...)-1).bit_length()`  
solved it.
