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

Help implementing Extension for RFC8949 Tag 24 - Data Item #83

Open
jfromaniello opened this issue Aug 28, 2023 · 2 comments
Open

Help implementing Extension for RFC8949 Tag 24 - Data Item #83

jfromaniello opened this issue Aug 28, 2023 · 2 comments

Comments

@jfromaniello
Copy link

I am trying to implement an extension for "DataItems" Tag 24 as described in RFC8949:

https://www.rfc-editor.org/rfc/rfc8949.html#name-encoded-cbor-data-item

Sometimes it is beneficial to carry an embedded CBOR data item that is not meant to be decoded immediately at the time the enclosing data item is being decoded. Tag number 24 (CBOR data item) can be used to tag the embedded byte string as a single data item encoded in CBOR format.

Let's assume for now that we want to encode/decode immediately.

I've tried different versions of the following encoding function but I can't make it work

const { Encoder, addExtension } = require('cbor-x');

//this is an example cbor which seems to be properly using tag 24:
const encoded = Buffer.from('d8184bb9000163666f6f6362617a', 'hex');

const encoderDefaults = {
  tagUint8Array: false,
  useRecords: false,
  mapsAsObjects: true
};

const encoder = new Encoder(encoderDefaults);

class DataItem {
  constructor(data) {
    this.data = data;
  }
}

addExtension({
  Class: DataItem,
  tag: 24,
  encode: (obj, enc) => {
    //here we need to encode the obj.data into a cbor
    //and then call the encode callback with the buffer
    const encodedByteString = encoder.encode(obj.data);
    console.log(`enc byte string: ${encodedByteString.toString('hex')}`);
    enc(encodedByteString);
  },
  decode: (data) => {
    //we get a buffer here and we have to decode it.
    const decoded = encoder.decode(data);
    return new DataItem(decoded);
  },
});

console.log('data item: %o', encoder.decode(encoded));

const encodedByCBORX = encoder.encode(new DataItem({ foo: 'baz' }));
console.log(`example: ${encoded.toString('hex')}`);
console.log(`encoded: ${encodedByCBORX.toString('hex')}`);

This example shows the following output:

data item: DataItem { data: { foo: 'baz' } }
enc byte string: b9000163666f6f6362617a
example: d8184bb9000163666f6f6362617a
encoded: b9000163666f6f6362617a4bb9000163666f6f6362617a

Decoding works just fine, the issue seems to be in the encoding function of the extension. The encoded result is much larger than it should and fails to decode in most of the cbor tooling.

Thank you in advance!

@jfromaniello
Copy link
Author

A weird thing is that if I just hard code the value shown in the encode function, it does produces the expected result:

  encode: (obj, enc) => {
    // const encodedByteString = encoder.encode(obj.data);
    // console.log(`enc byte string: ${encodedByteString.toString('hex')}`);
    const buffer = Buffer.from('b9000163666f6f6362617a', 'hex');
    enc(buffer);
  },

outputs;

encoded: d8184bb9000163666f6f6362617a

So, it seems like the problem is calling an extra encode inside the encode function. I've also tried creating a new instance of the encoder inside the encode function of the extension but it didn't work.

@jfromaniello
Copy link
Author

I think I figure a way, is not nice... but the issue seems to be related to the module scoped state:
https://github.com/kriszyp/cbor-x/blob/master/encode.js#L15

const importFresh = require('import-fresh');
const { Encoder: Encoder2 } = importFresh('cbor-x');
...

then in the extension encode function:

  encode: (obj, enc) => {
    const tmpEncoder = new Encoder2(encoderDefaults);
    const encodedByteString = tmpEncoder.encode(obj.data);
    enc(encodedByteString);
  },

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

1 participant