Hi,

On Fri, Sep 29, 2023 at 03:41:27PM +0200, Victor Toso wrote:
> Hi,
> 
> On Thu, Sep 28, 2023 at 03:21:59PM +0100, Daniel P. Berrangé wrote:
> > On Wed, Sep 27, 2023 at 01:25:40PM +0200, Victor Toso wrote:
> > > This patch handles QAPI union types and generates the equivalent data
> > > structures and methods in Go to handle it.
> > > 
> > > The QAPI union type has two types of fields: The @base and the
> > > @Variants members. The @base fields can be considered common members
> > > for the union while only one field maximum is set for the @Variants.
> > > 
> > > In the QAPI specification, it defines a @discriminator field, which is
> > > an Enum type. The purpose of the  @discriminator is to identify which
> > > @variant type is being used.
> > > 
> > > Not that @discriminator's enum might have more values than the union's
> > > data struct. This is fine. The union does not need to handle all cases
> > > of the enum, but it should accept them without error. For this
> > > specific case, we keep the @discriminator field in every union type.
> > 
> > I still tend think the @discriminator field should not be
> > present in the union structs. It feels like we're just trying
> > to directly copy the C code in Go and so smells wrong from a
> > Go POV.
> > 
> > For most of the unions the @discriminator field will be entirely
> > redundant, becasue the commonm case is that a @variant field
> > exists for every possible @discriminator value.
> 
> You are correct.
> 
> > To take one example
> > 
> >   type SocketAddress struct {
> >         Type SocketAddressType `json:"type"`
> > 
> >         // Variants fields
> >         Inet  *InetSocketAddress  `json:"-"`
> >         Unix  *UnixSocketAddress  `json:"-"`
> >         Vsock *VsockSocketAddress `json:"-"`
> >         Fd    *String             `json:"-"`
> >   }
> > 
> > If one was just writing Go code without the pre-existing knowledge
> > of the QAPI C code, 'Type' is not something a Go programmer would
> > be inclined add IMHO.
> 
> You don't need previous knowledge in the QAPI C code to see that
> having optional field members and a discriminator field feels
> very very suspicious. I wasn't too happy to add it.
> 
> > And yet you are right that we need a way to represent a
> > @discriminator value that has no corresponding @variant, since
> > QAPI allows for that scenario.
> 
> Thank Markus for that, really nice catch :)
> 
> 
> > To deal with that I would suggest we just use an empty
> > interface type. eg
> > 
> >   type SocketAddress struct {
> >         Type SocketAddressType `json:"type"`
> > 
> >         // Variants fields
> >         Inet  *InetSocketAddress  `json:"-"`
> >         Unix  *UnixSocketAddress  `json:"-"`
> >         Vsock *VsockSocketAddress `json:"-"`
> >         Fd    *String             `json:"-"`
> >     Fish  *interface{}        `json:"-"`
> >     Food  *interface()        `json:"-"`
> >   }
> > 
> > the pointer value for 'Fish' and 'Food' fields here merely needs to
> > be non-NULL, it doesn't matter what the actual thing assigned is.
> 
> I like this idea. What happens if Fish becomes a handled in the
> future?
> 
> Before:
> 
>     type SocketAddress struct {
>         // Variants fields
>         Inet  *InetSocketAddress  `json:"-"`
>         Unix  *UnixSocketAddress  `json:"-"`
>         Vsock *VsockSocketAddress `json:"-"`
>         Fd    *String             `json:"-"`
> 
>         // Unhandled enum branches
>         Fish  *interface{}        `json:"-"`
>         Food  *interface{}        `json:"-"`
>     }
> 
> to
> 
>     type SocketAddress struct {
>         // Variants fields
>         Inet  *InetSocketAddress  `json:"-"`
>         Unix  *UnixSocketAddress  `json:"-"`
>         Vsock *VsockSocketAddress `json:"-"`
>         Fd    *String             `json:"-"`
>         Fish  *FishSocketAddress  `json:"-"`
> 
>         // Unhandled enum branches
>         Food  *interface{}        `json:"-"`
>     }
> 
> An application that hat s.Fish = &something, will now error on
> compile due something type not being FishSocketAddress. I think
> this is acceptable. Very corner case scenario and the user
> probably want to use the right struct now.
> 
> If you agree with above, I'd instead like to try a boolean
> instead of *interface{}. s.Fish = true seems better and false is
> simply ignored.

I was just double checking that the Union's value for each enum
branch needs to be a Struct. So I think it is fine to use boolean
for unhandled enum branches. I'll be doing that in the next
iteration.

docs/devel/qapi-code-gen.rst: 350
    The BRANCH's value defines the branch's properties, in particular its
    type.  The type must a struct type.  The form TYPE-REF_ is shorthand
    for :code:`{ 'type': TYPE-REF }`.

Cheers,
Victor

Attachment: signature.asc
Description: PGP signature

Reply via email to