hildjj / node-cbor

Encode and decode CBOR documents, with both easy mode, streaming mode, and SAX-style evented mode.
MIT License
357 stars 73 forks source link

How do I encode and decode data as per .cddl file #103

Closed ashisherc closed 4 years ago

ashisherc commented 4 years ago

I have a cbor spec defined in a .cddl file, is it possible to encode data as per the schema defined in it.

Sample file

; Ping−Pong Protocol
pingPongMessage = msgPing / msgPong / pingPongMsgDone
msgPing = 0
msgPong = 1
pingPongMsgDone = 2
hildjj commented 4 years ago

How automatic do you want it to be? cbor.encode(0) will give you a valid msgPing.

ashisherc commented 4 years ago

I have to send this encoded msg to another server. Which also accepts a lot other commands over unix socket.

cbor.encode(0) is not enough I guess because there are other commands which will also then look like cbor.encode(0)

Do I need to somehow specify like,

cbor.encode("pingPongMessage 0")

Unfortunately I have only the spec I have mentioned above. Does the spec specify how should I send a proper pingPongMessage?

Im not sure if this is to do anything with this cbor library, but I appreciate your response.

Edit

I tried cbor.encode(0), but it does not work. Because may be as I mentioned above, there are many other commands which would also then look like cbor.encode(0) only, and does not specify which command I am sending to the unix socket.

ashisherc commented 4 years ago

I got a response from the server author mentioning the encoding in Haskell looks like,

CBOR.encodeWord 0

He suggested seeing what is equivalent to that in this node package?

My guess is 0 is a string, and hence, it could be equivalent to cbor.encode("0") ? Though this still doesn't make communication go through and I am going through additional specs.

hildjj commented 4 years ago

In that CDDL 0 is an unsigned integer. It is encoded as the single byte 0. cbor.encode(0) returns <Buffer 00> which should be the same as your Haskell.

To encode less-trival examples, build up an equivalent javascript object, then call cbor.encode() on that object. If you give me a pointer to the CDDL in question, or paste a more complicated section here, I can help with a more complete example.

ashisherc commented 4 years ago

Hi Joe, here's a more complex CDDL example which I would want to encode and decode

handshakeMessage = msgProposeVersions / msgAcceptVersion / msgRefuse
msgProposeVersions = [ 0 , versionTable ]
msgAcceptVersion = [ 1 , versionNumber , extraParams ]
msgRe fuse = [ 2 , refuseReason ]
versionNumber = 0 / 1 / 2

params = any
extraParams = any
versionTable = 
{
  ? 0 => params
, ? 1 => params
, ? 2 => params
}

refuseReason
= refuseReasonVersionMismatch
/ refuseReasonHandshakeDecodeError
/ refuseReasonRefused
refuseReasonVersionMismatch = [ 0 , [  versionNumber ] ]
refuseReasonHandshakeDecodeError = [ 1 , versionNumber , tstr ]
refuseReasonRefused = [ 2 , versionNumber , tstr ]

Also, I am trying to decode one cbor encoded object from the Haskell server, but I am getting below error message randomly for the exact same encoded object.

Result type 1
value = Symbol(not found)
error = unexpected end of input

Result type 2
value = Symbol(not found)
error = TypeError [ERR_ENCODING_ENVALID_ENCODED_DATA]: The encoded data was not valid for encoding utf-8

Result type 3
value = Symbol(not found)
error = Additional info not implemented: 28 or 29 or 30 random numbers

Please note that above results are from the exact same encoded object from a Haskell server.

Am I getting into a cross-language encoding issue? As per the specs, I should be able to encode and decode objects for and from the Haskell server for communication.

hildjj commented 4 years ago

Did you get this to work @ashisherc ? If you post hex-encoded or base64-encoded bytes that you're getting from the server here, I'll look into the decode issue. It looks like either the server sent a string that was invalid UTF8, or you used some other processing step between what the server sent and what you gave to the cbor library.

On the encode side, something like this:

const versionTable = new Map([
  [1, {v1param: true}],
  [2, {v2param: false}]
])
const msgProposeVersions = [0, versionTable]
const handshakeMessage = msgProposeVersions
const buf = cbor.encode(handshakeMessage)
ashisherc commented 4 years ago

Yes, you are correct. The msgs I was decoding were encapsulated in packets with header and timestamp. It was nothing to do with the decoder.

I also found out that there is no such parser thing required to map cddl to cbor output. As it is possible to encode json like objects itself with cbor, I was looking for the parser because the msgs I am dealing with arent formatted well. But that is also nothing to do with this library.

Im implementing a pipelining protocol mux and demux using cbor encoding, I have created an issue regarding the same here

https://github.com/hildjj/node-cbor/issues/104