From: Victor Toso <victortoso@redhat.com>
To: "Daniel P. Berrangé" <berrange@redhat.com>
Cc: Andrea Bolognani <abologna@redhat.com>,
qemu-devel@nongnu.org, Eric Blake <eblake@redhat.com>,
Markus Armbruster <armbru@redhat.com>,
John Snow <jsnow@redhat.com>
Subject: Re: [RFC PATCH v2 4/8] qapi: golang: Generate qapi's union types in Go
Date: Wed, 17 Aug 2022 18:25:56 +0200 [thread overview]
Message-ID: <20220817162556.fqjq74dtgi2uuyla@tapioca> (raw)
In-Reply-To: <YsVaVpXPE4YVjmVt@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 5638 bytes --]
On Wed, Jul 06, 2022 at 10:48:06AM +0100, Daniel P. Berrangé wrote:
> On Wed, Jul 06, 2022 at 10:37:54AM +0100, Daniel P. Berrangé wrote:
> > On Wed, Jul 06, 2022 at 04:28:16AM -0500, Andrea Bolognani wrote:
> > > You're right, that is undesirable. What about something like this?
> > >
> > > type GuestPanicInformation struct {
> > > HyperV *GuestPanicInformationHyperV
> > > S390 *GuestPanicInformationS390
> > > }
> > >
> > > type jsonGuestPanicInformation struct {
> > > Discriminator string `json:"type"`
> > > HyperV *GuestPanicInformationHyperV `json:"hyper-v"`
> > > S390 *GuestPanicInformationS390 `json:"s390"`
> > > }
> >
> > It can possibly be even simpler with just embedding the real
> > struct
> >
> > type jsonGuestPanicInformation struct {
> > Discriminator string
> > GuestPanicInformation
> > }
Similar to what I said in previous email (same thread) to Andrea,
this would not work because the end result does not match with
QAPI spec, where HyperV or S390 fields should be at the same
level as 'type'.
If we embed either HyperV or S390, then it should work, like:
tmp := struct {
GuestPanicInformationHyperV
Discriminator string "type"
}{}
But I intend to try the json.RawMessage too as with description
it seems like we can avoid looking the whole json data twice.
> > > func (s GuestPanicInformation) MarshalJSON() ([]byte, error) {
> > > if (s.HyperV != nil && s.S390 != nil) ||
> > > (s.HyperV == nil && s.S390 == nil) {
> > > // client hasn't filled in the struct properly
> > > return nil, errors.New("...")
> > > }
> > >
> > > tmp := jsonGuestPanicInformation{}
> > >
> > > if s.HyperV != nil {
> > > tmp.Discriminator = "hyper-v"
> > > tmp.HyperV = s.HyperV
> > > } else if s.S390 != nil {
> > > tmp.Discriminator = "s390"
> > > tmp.S390 = s.S390
> > > }
> > >
> > > return json.Marshal(tmp)
> > > }
> >
> > And...
> >
> > var discriminator string
> > if s.HyperV != nil {
> > discriminator = "hyper-v"
> > } else if s.S390 != nil {
> > discriminator = "s390"
> > }
> >
> > tmp := jsonGuestPanicInformation{ discriminator, s}
> > return json.Marshal(tmp)
> >
> > >
> > > func (s *GuestPanicInformation) UnmarshalJSON(data []byte) error {
> > > tmp := jsonGuestPanicInformation{}
> > >
> > > err := json.Unmarshal(data, &tmp)
> > > if err != nil {
> > > return err
> > > }
> > >
> > > switch tmp.Discriminator {
> > > case "hyper-v":
> > > if tmp.HyperV == nil {
> > > return errors.New("...")
> > > }
> > > s.HyperV = tmp.HyperV
> > > case "s390":
> > > if tmp.S390 == nil {
> > > return errors.New("...")
> > > }
> > > s.S390 = tmp.S390
> > > }
> >
> > I'm not actually sure this works, because the first json.Unmarshal
> > call won't know which branch to try unmarhsalling. So it might be
> > unavoidable to parse twice. With the XML parser this wouldn't be
> > a problem as it has separated the parse phase and then fills the
> > struct after.
>
> Right afer sending, I remember how this is supposed to be done. It
> involves use of 'json.RawMessage' eg examples at:
>
> https://pkg.go.dev/encoding/json#example-RawMessage-Unmarshal
>
> So it would look like:
>
> type GuestPanicInformation struct {
> HyperV *GuestPanicInformationHyperV
> S390 *GuestPanicInformationS390
> }
>
> type jsonGuestPanicInformation struct {
> Discriminator string `json:"type"`
> Payload *json.RawMessage
> }
>
>
> func (s GuestPanicInformation) MarshalJSON() ([]byte, error) {
> var p *json.RawMesage
> var err error
> if s.HyperV != nil {
> d = "hyper-v"
> p, err = json.Marshal(s.HyperV)
> } else if s.S390 != nil {
> d = "s390"
> p, err = json.Marshal(s.S390)
> } else {
> err = fmt.Errorf("No payload defined")
> }
> if err != nil {
> return []byte{}, err
> }
>
> return json.Marshal(jsonGuestPanicInformation{d, p}), nil
> }
>
>
>
> func (s *GuestPanicInformation) UnmarshalJSON(data []byte) error {
> tmp := jsonGuestPanicInformation{}
>
> err := json.Unmarshal(data, &tmp)
> if err != nil {
> return err
> }
>
> switch tmp.Discriminator {
> case "hyper-v":
> s.HyperV := GuestPanicInformationHyperV{}
> err := json.Unmarshal(tmp.Payload, s.HyperV)
> if err != nil {
> return err
> }
> case "s390":
> s.S390 := GuestPanicInformationS390{}
> err := json.Unmarshal(tmp.Payload, s.S390)
> if err != nil {
> return err
> }
> }
>
> return fmt.Errorf("Unknown type '%s'", tmp.Discriminator)
> }
>
> With regards,
> Daniel
> --
> |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
> |: https://libvirt.org -o- https://fstop138.berrange.com :|
> |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
Cheers,
Victor
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
next prev parent reply other threads:[~2022-08-17 16:46 UTC|newest]
Thread overview: 53+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-06-17 12:19 [RFC PATCH v2 0/8] qapi: add generator for Golang interface Victor Toso
2022-06-17 12:19 ` [RFC PATCH v2 1/8] qapi: golang: Generate qapi's enum types in Go Victor Toso
2022-06-17 12:19 ` [RFC PATCH v2 2/8] qapi: golang: Generate qapi's alternate " Victor Toso
2022-07-05 15:45 ` Andrea Bolognani
2022-08-17 14:04 ` Victor Toso
2022-08-19 16:27 ` Andrea Bolognani
2022-08-22 6:59 ` Victor Toso
2022-08-29 11:27 ` Markus Armbruster
2022-08-29 13:31 ` Victor Toso
2022-09-02 14:49 ` Victor Toso
2022-06-17 12:19 ` [RFC PATCH v2 3/8] qapi: golang: Generate qapi's struct " Victor Toso
2022-06-17 14:41 ` Daniel P. Berrangé
2022-06-17 15:23 ` Victor Toso
2022-06-17 12:19 ` [RFC PATCH v2 4/8] qapi: golang: Generate qapi's union " Victor Toso
2022-07-05 15:45 ` Andrea Bolognani
2022-07-05 16:35 ` Daniel P. Berrangé
2022-07-06 9:28 ` Andrea Bolognani
2022-07-06 9:37 ` Daniel P. Berrangé
2022-07-06 9:48 ` Daniel P. Berrangé
2022-07-06 12:20 ` Andrea Bolognani
2022-08-17 16:25 ` Victor Toso [this message]
2022-08-19 7:20 ` Victor Toso
2022-08-19 15:25 ` Andrea Bolognani
2022-08-22 6:33 ` Victor Toso
2022-08-17 16:06 ` Victor Toso
2022-06-17 12:19 ` [RFC PATCH v2 5/8] qapi: golang: Generate qapi's event " Victor Toso
2022-07-05 15:45 ` Andrea Bolognani
2022-07-05 16:47 ` Daniel P. Berrangé
2022-07-06 14:53 ` Andrea Bolognani
2022-07-06 15:07 ` Daniel P. Berrangé
2022-07-06 16:22 ` Andrea Bolognani
2022-08-18 7:55 ` Victor Toso
2022-08-18 7:47 ` Victor Toso
2022-06-17 12:19 ` [RFC PATCH v2 6/8] qapi: golang: Generate qapi's command " Victor Toso
2022-06-17 12:19 ` [RFC PATCH v2 7/8] qapi: golang: Add CommandResult type to Go Victor Toso
2022-07-05 15:46 ` Andrea Bolognani
2022-07-05 16:49 ` Daniel P. Berrangé
2022-08-17 15:00 ` Victor Toso
2022-06-17 12:19 ` [RFC PATCH v2 8/8] qapi: golang: document skip function visit_array_types Victor Toso
2022-06-27 7:15 ` [RFC PATCH v2 0/8] qapi: add generator for Golang interface Markus Armbruster
2022-06-27 12:48 ` Victor Toso
2022-06-27 15:29 ` Markus Armbruster
2022-08-18 8:04 ` Victor Toso
2022-07-05 15:46 ` Andrea Bolognani
2022-08-17 14:24 ` Victor Toso
2022-08-29 11:53 ` Markus Armbruster
2022-08-29 14:05 ` Victor Toso
2024-11-07 10:43 ` Daniel P. Berrangé
2024-11-07 12:36 ` Markus Armbruster
2024-11-07 13:06 ` Daniel P. Berrangé
2024-11-07 13:35 ` Daniel P. Berrangé
2024-11-07 14:18 ` Markus Armbruster
2024-11-08 9:43 ` Victor Toso
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220817162556.fqjq74dtgi2uuyla@tapioca \
--to=victortoso@redhat.com \
--cc=abologna@redhat.com \
--cc=armbru@redhat.com \
--cc=berrange@redhat.com \
--cc=eblake@redhat.com \
--cc=jsnow@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).