Skip to content

Add support for variant types - #32

Open
logmanoriginal wants to merge 1 commit into
masterfrom
31-variants
Open

Add support for variant types#32
logmanoriginal wants to merge 1 commit into
masterfrom
31-variants

Conversation

@logmanoriginal

@logmanoriginal logmanoriginal commented Aug 28, 2026

Copy link
Copy Markdown
Owner

This is a major addition for (de-)composition of variant types that enables the use of variant elements inside composable types.

Variant types behave different from other types. When used as terminals on the connector pane, whatever type is connected to it will keep its original type, which means that the type can be handled as if working with the original.

When a type is "boxed" inside a variant - for example, when using variant Maps - the embedded type is serialized into the data string of the variant.

Variant data consists of several key fields:

4 Bytes - Version

This is the LabVIEW version used to serialize the variant. For exapmle, [0x17,0x00,0x80,0x00] for LabVIEW 2017 SP1 or [0x19,0x00,0x80,0x00] for LabVIEW 2019 SP1. The major version number is clearly visible in the first byte when viewed in hexadecimal. The service pack version appears to be part of the third byte.

4 Bytes - Number of type definitions

A variant can box many type definitions, each of which represents one type. The order in which these types are defined is important because when using a container (e.g., cluster), it references back to one of the previously defined types. This means that duplicate types only appear once in the definition.

For example, if a cluster contains two strings, the type definition of the string only appears once and is referenced twice. Regardless of how many times a type appears, it is always referenced by the container. Only when the container is not further divided, will it be the sole type definition.

Once all type definitions are identified, the backrefs must be resolved.

TDs

What follows are the type definitions. Simply extracted by reading the first two bytes (length) and then the rest to fill up that length.

2 Bytes - Number of "top-level" types (I think)

The next two bytes are not 100% clear but I believe they specify how many top-level types there are. I have only observed 0x0001 always and don't know if there is any way to change that. Alternatively it might specify how many words of backrefs follow (next 2 bytes) but this is also just speculation because I don't think there are so many types (unless typedefs count)... currently ignored.

2 Bytes - Number of backrefs

This count depends on how many backref type definitions exist.

Data

What follows is the data section, which is the data for the top-level type and all its nested types. This can be anything.

4 Bytes - Number of attributes

Next up are four bytes that specify the number of attributes on a variant. Since attributes are optional, the count can be zero.

Attributes

Finally, if there are any attributes, they all follow the same convention: 4 Bytes for the length of the key, followed by the key, followed by the value as boxed variant.

Since attributes can contain variants with attributes, all of this is recursive.

Further information can be found in the official documentation 1 2

Closes #31

This is a major addition for (de-)composition of variant types that
enables the use of variant elements inside composable types.

Variant types behave different from other types. When used as terminals
on the connector pane, whatever type is connected to it will keep its
original type, which means that the type can be handled as if working
with the original.

When a type is "boxed" inside a variant - for example, when using
variant Maps - the embedded type is serialized into the data string of
the variant.

Variant data consists of several key fields:

4 Bytes - Version
-----------------
This is the LabVIEW version used to serialize the variant. For exapmle,
[0x17,0x00,0x80,0x00] for LabVIEW 2017 SP1 or [0x19,0x00,0x80,0x00] for
LabVIEW 2019 SP1. The major version number is clearly visible in the
first byte when viewed in hexadecimal. The service pack version appears
to be part of the third byte.

4 Bytes - Number of type definitions
------------------------------------
A variant can box many type definitions, each of which represents one
type. The order in which these types are defined is important because
when using a container (e.g., cluster), it references back to one of the
previously defined types. This means that duplicate types only appear
once in the definition.

For example, if a cluster contains two strings, the type definition of the
string only appears once and is referenced twice. Regardless of how many
times a type appears, it is always referenced by the container. Only
when the container is not further divided, will it be the sole type
definition.

Once all type definitions are identified, the backrefs must be resolved.

TDs
---
What follows are the type definitions. Simply extracted by reading the
first two bytes (length) and then the rest to fill up that length.

2 Bytes - Number of "top-level" types (I think)
-------------------------------------
The next two bytes are not 100% clear but I believe they specify how
many top-level types there are. I have only observed 0x0001 always and
don't know if there is any way to change that. Alternatively it might
specify how many words of backrefs follow (next 2 bytes) but this is
also just speculation because I don't think there are so many types
(unless typedefs count)... currently ignored.

2 Bytes - Number of backrefs
----------------------------
This count depends on how many backref type definitions exist.

Data
----
What follows is the data section, which is the data for the top-level
type and all its nested types. This can be anything.

4 Bytes - Number of attributes
------------------------------
Next up are four bytes that specify the number of attributes on a
variant. Since attributes are optional, the count can be zero.

Attributes
----------
Finally, if there are any attributes, they all follow the same
convention: 4 Bytes for the length of the key, followed by the key,
followed by the value as boxed variant.

Since attributes can contain variants with attributes, all of this is
recursive.

Further information can be found in the official documentation [1][2]

[1]: https://knowledge.ni.com/KnowledgeArticleDetails?id=kA03q000000YGQrCAO&l=en-US
[2]: https://www.ni.com/docs/en-US/bundle/labview/page/type-descriptors.html
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Error decomposing map of map of variant

1 participant