abuiles/json-xdr

Add deserialization support (jsonToXDR)

abuiles opened this issue · 1 comments

Given the following definition:

const types = XDR.config((xdr) => {
  xdr.typedef("Hash", xdr.opaque(2));
  xdr.typedef('Int32', xdr.int());

  xdr.struct("Price", [
    ["n", xdr.lookup("Int32")],
    ["d", xdr.lookup("Int32")],
  ]);

  xdr.enum("MemoType", {
      memoNone: 0,
      memoText: 1,
      memoId: 2,
      memoHash: 3,
      memoReturn: 4,
  });

  xdr.union("Memo", {
    switchOn: xdr.lookup("MemoType"),
    switchName: "type",
    switches: [
      ["memoNone", xdr.void()],
      ["memoText", "text"],
      ["memoId", "id"]
    ],
    arms: {
      text: xdr.string(28),
      id: xdr.lookup("Int32")
    },
  });

  xdr.typedef('CounterInt', xdr.option(xdr.int()));

  xdr.struct('Event', [
    ["attendees", xdr.int()],
    ["eventName", xdr.string(50)],
    ["secretSpeakers", xdr.array(xdr.lookup("Hash"), 2)],
    ["speakers", xdr.varArray(xdr.string())],
    ["price", xdr.lookup("Price")],
    ["memo", xdr.lookup("Memo")],
    ['meta', xdr.lookup('TransactionMeta')],
    ['counter', xdr.lookup("CounterInt")]
  ])

  xdr.enum("TransactionMetaType", {
    none: 0,
    paid: 1
  });

  xdr.union("TransactionMeta", {
    switchOn: xdr.lookup("TransactionMetaType"),
    switches: [
      ["none", xdr.void()],
      ["paid", "price"]
    ],
    arms: {
      price: xdr.lookup("Price")
    },
    defaultArm: xdr.void()
  });
})

You should be able to use the following JSON to create an Event struct:

{
  "attendees": 5,
  "eventName": "Lumenauts get together",
  "secretSpeakers": [
    "AAA=",
    "AAE="
  ],
  "speakers": [
    "Jed",
    "Tom",
    "Zac"
  ],
  "price": {
    "n": 2,
    "d": 1
  },
  "memo": {
    "_type": "memoText",
    "text": "foo"
  },
  "meta": {
    "_type": "paid",
    "price": {
      "n": 2,
      "d": 1
    }
  },
  "counter": 2
}

The call to such function will look like jsonToXDR(types.Event, json) -- and the result would be the equivalent of doing:

let event = new types.Event({
  attendees: 5,
  eventName: "Lumenauts get together",
  secretSpeakers: [Buffer.from([0, 0]), Buffer.from([0, 1])],
  speakers: ['Jed', 'Tom', 'Zac'],
  price: new types.Price({
    n: 2,
    d: 1
  }),
  memo: types.Memo.memoText("foo"),
  meta: types.TransactionMeta.paid(new types.Price({
    n: 2,
    d: 1
  })),
  counter: 2
})

This is pretty much done since

describe("#toXDR", () => {

We have some edge cases to test out.