codec.js

/*
 * Copyright 2017-2019 Tom Swindell
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */

// CONSTANTS
const ARNETWORK_FRAME_HEADER_SIZE = 7
const ARNETWORK_COMMAND_HEADER_SIZE = 4

/**
 * 
 * ARNet protocol network frame serializing and deserializing functions.
 * 
 * @module Frame
 * @public
 * 
 */
const Frame = {
  /**
   * Pack an ARNet network frame using provided parameters.
   * 
   * @function module:Frame.pack
   * @public
   * 
   * @param {uint8} type 
   * @param {uint8} id 
   * @param {uint8} seq 
   * @param {Buffer} data
   * 
   * @returns {Buffer}
   */
  pack (type, id, seq, data) {
    const buffer = Buffer.alloc(ARNETWORK_FRAME_HEADER_SIZE + data.length)

    let offset = buffer.writeUInt8(type)
    offset = buffer.writeUInt8(id, offset)
    offset = buffer.writeUInt8(seq, offset)
    offset = buffer.writeUInt32LE(ARNETWORK_FRAME_HEADER_SIZE + data.length, offset)
  
    data.copy(buffer, offset)
    return buffer  
  },

  /**
   * Unpack an ARNet network frame packet.
   * 
   * @function module:Frame.upack
   * @public
   * 
   * @param {Buffer} buffer - ARNetwork frame to unpack
   * 
   * @returns {Object}
   */
  unpack (buffer) {
    if (buffer.length < ARNETWORK_FRAME_HEADER_SIZE) {
      throw 'ARNET_INVALID_FRAME_SIZE'
    }

    const frame = {
      type: buffer.readUInt8(0),
      id: buffer.readUInt8(1),
      seq: buffer.readUInt8(2),
      payload: buffer.slice(ARNETWORK_FRAME_HEADER_SIZE)
    }
    return frame  
  }
}

/**
 * 
 * ARNetwork protocol messaging serializing and deserializing functions.
 * 
 * @module Message
 * @public
 */
const Message = {
  /**
   * Pack ARNet message header and args using provided arguments
   * 
   * @function module:Message.pack
   * @public
   * 
   * @param {uint8} featureId 
   * @param {uint8} classId
   * @param {uint16} messageId 
   * @param {Buffer} args
   * 
   * @returns {Buffer}
   */
  pack (featureId, classId, messageId, args) {
    args = args || Buffer.alloc(0)
    const buffer = Buffer.alloc(ARNETWORK_COMMAND_HEADER_SIZE + args.length)
  
    let offset = buffer.writeUInt8(featureId)
    offset = buffer.writeUInt8(classId, offset)
    offset = buffer.writeUInt16LE(messageId, offset)
  
    args.copy(buffer, offset)
    return buffer  
  },

  /**
   * Unpack ARNet message header and args from Buffer.
   * 
   * @function module:Message.unpack
   * @public
   * 
   * @param {Buffer} buffer 
   * 
   * @returns {Object}
   */
  unpack (buffer) {
    const command = {
      featureId: buffer.readUInt8(0),
      classId: buffer.readUInt8(1),
      messageId: buffer.readUInt16LE(2),
      args: buffer.slice(ARNETWORK_COMMAND_HEADER_SIZE),
    }
    return command  
  }
}

module.exports = { Frame, Message }