Implementing Discriminated Unions in HIDL

This change augments hidl-gen to generate C++ code for HIDL safe_union
constructs. The HIDL declaration is similar to regular structs/unions:

safe_union SafeUnion {
	uint8_t a;
	string b;
}

The emitted C++ code is:

struct SafeUnion final {
public:
    enum class hidl_discriminator : uint8_t {
        a,
        b,
        hidl_no_init
    };

    SafeUnion();
    ~SafeUnion();
    SafeUnion(const SafeUnion&);

    void a(uint8_t);
    uint8_t& a();
    uint8_t a() const;

    void b(const ::android::hardware::hidl_string&);
    ::android::hardware::hidl_string& b();
    const ::android::hardware::hidl_string& b() const;

    // Utility method
    hidl_discriminator getDiscriminator() const;

private:
    void hidl_destructUnion();

    union hidl_union final {
        uint8_t a __attribute__ ((aligned(1)));
        ::android::hardware::hidl_string b __attribute__ ((aligned(8)));

	hidl_union();
	~hidl_union();
    } u;

    hidl_discriminator d __attribute__ ((aligned(1)))\
    {hidl_discriminator::hidl_no_init};
};

Also synthesizes the appropriate toString, operator== and
{read,write}Embedded{From,To}Parcel methods.

Bug: 79878527
Test: Ran the existing hidl_test suite, tested safe_union get/set
methods on a test HAL.

Change-Id: I894c144204ab3bdbe446022b2805a64a211d28b3
Merged-In: I894c144204ab3bdbe446022b2805a64a211d28b3
diff --git a/CompoundType.h b/CompoundType.h
index 7295f40..58961d1 100644
--- a/CompoundType.h
+++ b/CompoundType.h
@@ -29,6 +29,7 @@
     enum Style {
         STYLE_STRUCT,
         STYLE_UNION,
+        STYLE_SAFE_UNION,
     };
 
     CompoundType(Style style, const char* localName, const FQName& fullName,
@@ -48,6 +49,7 @@
 
     status_t validate() const override;
     status_t validateUniqueNames() const;
+    status_t validateSubTypeNames() const;
 
     std::string getCppType(StorageMode mode,
                            bool specifyNamespaces) const override;
@@ -142,9 +144,38 @@
 
     bool containsInterface() const;
 private:
+
+    struct Layout {
+        size_t offset;
+        size_t align;
+        size_t size;
+
+        Layout() : offset(0), align(1), size(0) {}
+        static size_t getPad(size_t offset, size_t align);
+    };
+
+    struct CompoundLayout {
+        Layout overall;
+        Layout innerStruct;
+        Layout discriminator;
+    };
+
     Style mStyle;
     std::vector<NamedReference<Type>*>* mFields;
 
+    void emitLayoutAsserts(Formatter& out, const Layout& localLayout,
+                           const std::string& localLayoutName) const;
+
+    void emitInvalidSubTypeNamesError(const std::string& subTypeName,
+                                      const Location& location) const;
+
+    void emitSafeUnionTypeDefinitions(Formatter& out) const;
+    void emitSafeUnionTypeConstructors(Formatter& out) const;
+    void emitSafeUnionTypeDeclarations(Formatter& out) const;
+    std::unique_ptr<ScalarType> getUnionDiscriminatorType() const;
+
+    CompoundLayout getCompoundAlignmentAndSize() const;
+
     void emitStructReaderWriter(
             Formatter &out, const std::string &prefix, bool isReader) const;
     void emitResolveReferenceDef(Formatter& out, const std::string& prefix, bool isReader) const;