Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support unpacking object variants #38

Closed
dchem opened this issue Nov 9, 2019 · 2 comments
Closed

Support unpacking object variants #38

dchem opened this issue Nov 9, 2019 · 2 comments

Comments

@dchem
Copy link

dchem commented Nov 9, 2019

Version: 0.2.9

Commit: 9c4bc6e66d5d193692be0e7c5605166dc61756dc

Observed:
Object variants using standard idiom (with case) packs correctly, but fails to unpack.

Expected:
Object variants with zero-initialized variables should unpack correctly

Steps to Replicate:

import streams, msgpack4nim

type MsgType* = enum
  MSG_FOO,
  MSG_BAR

type Foo* = object
  name: string

type Bar* = object
  price: int

type FooBarMsg* = object
  case msgType*: MsgType
  of MSG_FOO:
    foo*: Foo
  of MSG_BAR:
    bar*: Bar

when isMainModule:
  var fooOriginal = Foo(name: "Baz")
  var barOriginal = Bar(price: 11)
  var outboundMsgFoo = FooBarMsg(
  msgType: MSG_FOO,
  foo: fooOriginal
  )
  var outboundMsgBar = FooBarMsg(
  msgType: MSG_BAR,
  bar: barOriginal
  )

  var sFoo = MsgStream.init()
  sFoo.pack(outboundMsgFoo)

  var sBar = MsgStream.init()
  sBar.pack(outboundMsgBar)

  var incomingFoo: FooBarMsg
  var sFooReception = MsgStream.init(sFoo.data)
  try:
    sFooReception.unpack(incomingFoo)
  except:
    echo "unpack error for foo"

  var incomingBar: FooBarMsg
  var sBarReception = MsgStream.init(sBar.data)
  try:
    sBarReception.unpack(incomingBar)
  except:
    echo "unpack error for bar"
@jangko
Copy link
Owner

jangko commented Nov 10, 2019

thank you for reporting this. case object/object variants is always an interesting subject for serializer library. it is tricky to do it properly automatically.

work-around: you can provide a custom deserializer for your special object, e.g:

proc unpack_type*[ByteStream](s: ByteStream, x: var FooBarMsg) =
    let numFields = s.unpack_array() # or unpack_map if you use OBJ_TO_MAP version
    let kind = MsgType(s.unpack_imp_int64())
    x = FooBarMsg(kind: kind)
    case kind:
    of MSG_FOO : s.unpack(x.foo)
    of MSG_BAR : s.unpack(x.bar)

EDIT: you can use stringify to debug the msgpack binary data.

@dchem
Copy link
Author

dchem commented Nov 15, 2019

@jangko thank you very much for the workaround suggestion. That works.

I agree that object variant handling is tough to implement correctly and generally, so please feel free to close the issue if you feel that it makes sense to do so.

@jangko jangko closed this as completed Dec 12, 2019
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

No branches or pull requests

2 participants