More about Unions in Vala

In a previous post I speculated about adding tagged unions to Vala. Let’s do that again.

In order to support the C usecase, Vala would need to include 2 types of tagged unions, a legacy one, and an idiomatic one. The legacy should look like the C version of a tagged union:

struct tagged {
    short tag;
    union variants {
        string text;
        int num;
    }
} tagged;

This is needed to bind the C libs out there. The type of the tag should be something that can be easily compared IMO (numeric datatypes, C enums, and string). The binding would then look like this:

[CCode (cname = "tagged", union_tag_field = "tag" union_tag_type = "short" union_field = "variants")]
union Tagged {
    [CCode (cname = "text", union_tag_id = "1")]
    TEXT(string),
    [CCode (cname = "num", union_tag_id = "2")]
    NUM(int)
}

The idiomatic ones, however, would actually look like a Rust struct, so if we declare:

public union OrderStatus {
	ACCEPTED,
	CANCELLED {string reason, string cancelled_by},
	REJECTED {string reason},
	COMPLETED {DateTime completed_at},
	ON_HOLD {string reason, Datetime until}
}

We should get:

enum OrderStatusTag {
	ACCEPTED,
	CANCELLED,
	REJECTED,
	COMPLETED,
	ON_HOLD
} OrderStatusTag

union order_status {
    struct accepted {OrderStatusTag tag};
    struct cancelled {OrderStatusTag tag; string reason, string cancelled_by};
    struct rejected {OrderStatusTag tag; string reason};
    struct completed {OrderStatusTag tag; GDateTime completed_at};
    struct on_hold {OrderStatusTag tag; string reason; GDatetime until};
} OrderStatus;

Fun things to support: GVariant variant types (unboxing, serialization, etc.), GValue, JSON representations.

Advertisements

Converting Array fields from PostgreSQL in jOOQ

There’s currently a “bug” (not really a bug, but it works for me in MySQL) that prevents jOOQ from reusing a forcedType when it appears as an array instead of a single value. I have a workaround for this: a forcedType for the array field, and binding it by field name. To facilitate the creation of an Array Converter, just subclass this and pass the right converter in the super() call: