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

Implement MessagePack timestamp extension #87

Open
dchenk opened this issue Apr 15, 2018 · 4 comments
Open

Implement MessagePack timestamp extension #87

dchenk opened this issue Apr 15, 2018 · 4 comments

Comments

@dchenk
Copy link

dchenk commented Apr 15, 2018

The MessagePack has for a while now had a built-in timestamp extension: https://github.com/msgpack/msgpack/blob/master/spec.md#timestamp-extension-type

Are there any plans to implement the timestamp format? I'd be especially excited about the 0xc7 version.

@kawanet
Copy link
Owner

kawanet commented Apr 24, 2018

Yes, I've been working for it. I'll retry to merge it in this month.

@ygoe
Copy link

ygoe commented May 9, 2018

I've just stumbled across this as well, in my very first experiments with this. It doesn't seem easy to decode that 30/34 bit structure in JavaScript without putting almost every bit manually where it belongs. Do you have any code public to have a look at it while I'm writing a workaround?

Update: This seems to work for 8-byte-values: (I have only checked it down to the seconds)

if (time.type === 255 && time.buffer.length === 8) {
    var ns = (message.data.time.buffer[0] << 22) +
        (message.data.time.buffer[1] << 14) +
        (message.data.time.buffer[2] << 6) +
        (message.data.time.buffer[3] >> 2);
    var sec = ((message.data.time.buffer[3] & 0x3) << 32) +
        (message.data.time.buffer[4] << 24) +
        (message.data.time.buffer[5] << 16) +
        (message.data.time.buffer[6] << 8) +
        message.data.time.buffer[7];
    time = new Date(sec * 1000 + ns / 1000000);
}

@ygoe
Copy link

ygoe commented Jun 11, 2018

Revisited this. Here's my code that should be able to decode all three timestamp formats. It only handles a single value deserialised from MessagePack. It needs to be integrated into the deserialiser to work transparently on all data.

JavaScript can be a beast when it comes to numeric data. Hence all the funny extra bitwise operators and DWORD pairs in there. Learned a thing or two today.

I'm currently writing my own little MessagePack codec in JavaScript. The encoder is complete as of today (incl. timestamp support) and has only 250 loc. The whole thing should reach 1/10th of the size of this library. I can't say anything about its performance yet though.

var data = msgpack.decode(array);
if (data.type === 255) {
    switch (data.buffer.length) {
        case 4:
            let sec = ((data.buffer[0] << 24) >>> 0) +
                ((data.buffer[1] << 16) >>> 0) +
                ((data.buffer[2] << 8) >>> 0) +
                data.buffer[3];
            console.log("sec", sec);
            data = new Date(sec * 1000);
            break;
        case 8:
            let ns = ((data.buffer[0] << 22) >>> 0) +
                ((data.buffer[1] << 14) >>> 0) +
                ((data.buffer[2] << 6) >>> 0) +
                (data.buffer[3] >>> 2);
            let pow32 = 0x100000000;   // 2^32
            let sec = ((data.buffer[3] & 0x3) * pow32) +
                ((data.buffer[4] << 24) >>> 0) +
                ((data.buffer[5] << 16) >>> 0) +
                ((data.buffer[6] << 8) >>> 0) +
                data.buffer[7];
            console.log("sec", sec, "ns", ns);
            data = new Date(sec * 1000 + ns / 1000000);
            break;
        case 12:
            let ns = ((data.buffer[0] << 24) >>> 0) +
                ((data.buffer[1] << 16) >>> 0) +
                ((data.buffer[2] << 8) >>> 0) +
                data.buffer[3];
            let pow32 = 0x100000000;   // 2^32
            let hi = ((data.buffer[4] << 24) >>> 0) +
                ((data.buffer[5] << 16) >>> 0) +
                ((data.buffer[6] << 8) >>> 0) +
                data.buffer[7];
            let lo = ((data.buffer[8] << 24) >>> 0) +
                ((data.buffer[9] << 16) >>> 0) +
                ((data.buffer[10] << 8) >>> 0) +
                data.buffer[11];
            let sec = hi * pow32 + lo;
            console.log("sec", sec, "ns", ns);
            data = new Date(sec * 1000 + ns / 1000000);
            break;
        default:
            throw "Unsupported timestamp data length.";
    }
}

(Warning: I have rearranged this code for showing it here. This exact code is untested.)

@ygoe
Copy link

ygoe commented Jul 23, 2018

Just for information and maybe a reference implementation, I have now published my MessagePack codec for JavaScript: https://github.com/ygoe/msgpack.js

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

3 participants