113 lines
4.2 KiB
JavaScript
113 lines
4.2 KiB
JavaScript
/* The default serializer for encoding and decoding messages */
|
|
import {
|
|
CHANNEL_EVENTS
|
|
} from "./constants"
|
|
|
|
export default {
|
|
HEADER_LENGTH: 1,
|
|
META_LENGTH: 4,
|
|
KINDS: {push: 0, reply: 1, broadcast: 2},
|
|
|
|
encode(msg, callback){
|
|
if(msg.payload.constructor === ArrayBuffer){
|
|
return callback(this.binaryEncode(msg))
|
|
} else {
|
|
let payload = [msg.join_ref, msg.ref, msg.topic, msg.event, msg.payload]
|
|
return callback(JSON.stringify(payload))
|
|
}
|
|
},
|
|
|
|
decode(rawPayload, callback){
|
|
if(rawPayload.constructor === ArrayBuffer){
|
|
return callback(this.binaryDecode(rawPayload))
|
|
} else {
|
|
let [join_ref, ref, topic, event, payload] = JSON.parse(rawPayload)
|
|
return callback({join_ref, ref, topic, event, payload})
|
|
}
|
|
},
|
|
|
|
// private
|
|
|
|
binaryEncode(message){
|
|
let {join_ref, ref, event, topic, payload} = message
|
|
let metaLength = this.META_LENGTH + join_ref.length + ref.length + topic.length + event.length
|
|
let header = new ArrayBuffer(this.HEADER_LENGTH + metaLength)
|
|
let view = new DataView(header)
|
|
let offset = 0
|
|
|
|
view.setUint8(offset++, this.KINDS.push) // kind
|
|
view.setUint8(offset++, join_ref.length)
|
|
view.setUint8(offset++, ref.length)
|
|
view.setUint8(offset++, topic.length)
|
|
view.setUint8(offset++, event.length)
|
|
Array.from(join_ref, char => view.setUint8(offset++, char.charCodeAt(0)))
|
|
Array.from(ref, char => view.setUint8(offset++, char.charCodeAt(0)))
|
|
Array.from(topic, char => view.setUint8(offset++, char.charCodeAt(0)))
|
|
Array.from(event, char => view.setUint8(offset++, char.charCodeAt(0)))
|
|
|
|
var combined = new Uint8Array(header.byteLength + payload.byteLength)
|
|
combined.set(new Uint8Array(header), 0)
|
|
combined.set(new Uint8Array(payload), header.byteLength)
|
|
|
|
return combined.buffer
|
|
},
|
|
|
|
binaryDecode(buffer){
|
|
let view = new DataView(buffer)
|
|
let kind = view.getUint8(0)
|
|
let decoder = new TextDecoder()
|
|
switch(kind){
|
|
case this.KINDS.push: return this.decodePush(buffer, view, decoder)
|
|
case this.KINDS.reply: return this.decodeReply(buffer, view, decoder)
|
|
case this.KINDS.broadcast: return this.decodeBroadcast(buffer, view, decoder)
|
|
}
|
|
},
|
|
|
|
decodePush(buffer, view, decoder){
|
|
let joinRefSize = view.getUint8(1)
|
|
let topicSize = view.getUint8(2)
|
|
let eventSize = view.getUint8(3)
|
|
let offset = this.HEADER_LENGTH + this.META_LENGTH - 1 // pushes have no ref
|
|
let joinRef = decoder.decode(buffer.slice(offset, offset + joinRefSize))
|
|
offset = offset + joinRefSize
|
|
let topic = decoder.decode(buffer.slice(offset, offset + topicSize))
|
|
offset = offset + topicSize
|
|
let event = decoder.decode(buffer.slice(offset, offset + eventSize))
|
|
offset = offset + eventSize
|
|
let data = buffer.slice(offset, buffer.byteLength)
|
|
return {join_ref: joinRef, ref: null, topic: topic, event: event, payload: data}
|
|
},
|
|
|
|
decodeReply(buffer, view, decoder){
|
|
let joinRefSize = view.getUint8(1)
|
|
let refSize = view.getUint8(2)
|
|
let topicSize = view.getUint8(3)
|
|
let eventSize = view.getUint8(4)
|
|
let offset = this.HEADER_LENGTH + this.META_LENGTH
|
|
let joinRef = decoder.decode(buffer.slice(offset, offset + joinRefSize))
|
|
offset = offset + joinRefSize
|
|
let ref = decoder.decode(buffer.slice(offset, offset + refSize))
|
|
offset = offset + refSize
|
|
let topic = decoder.decode(buffer.slice(offset, offset + topicSize))
|
|
offset = offset + topicSize
|
|
let event = decoder.decode(buffer.slice(offset, offset + eventSize))
|
|
offset = offset + eventSize
|
|
let data = buffer.slice(offset, buffer.byteLength)
|
|
let payload = {status: event, response: data}
|
|
return {join_ref: joinRef, ref: ref, topic: topic, event: CHANNEL_EVENTS.reply, payload: payload}
|
|
},
|
|
|
|
decodeBroadcast(buffer, view, decoder){
|
|
let topicSize = view.getUint8(1)
|
|
let eventSize = view.getUint8(2)
|
|
let offset = this.HEADER_LENGTH + 2
|
|
let topic = decoder.decode(buffer.slice(offset, offset + topicSize))
|
|
offset = offset + topicSize
|
|
let event = decoder.decode(buffer.slice(offset, offset + eventSize))
|
|
offset = offset + eventSize
|
|
let data = buffer.slice(offset, buffer.byteLength)
|
|
|
|
return {join_ref: null, ref: null, topic: topic, event: event, payload: data}
|
|
}
|
|
}
|