modules/multipart/multipartx.js

import MPSingle from './mpsingle'

import { FLODATA_MAX_LEN } from '../flo/FLOTransaction'
export const CHOP_MAX_LEN = 837
/**
 * An OIP Multipart Converter (X); converts large data into OIP Multiparts and vice versa
 * @param {string|Array.<MPSingle>} input - String data or OIP Multiparts (MPSingle)s (hint: can pass in an JSON object)
 * @class
 */
class MultipartX {
  constructor (input) {
    this.multiparts = []

    if (typeof input === 'string') {
      if (input.length < FLODATA_MAX_LEN) {
        return { success: false, error: 'Data does not exceed max floData length of 1040 bytes. MPX not needed.' }
      }
      this.fromString(input)
    } else if (Array.isArray(input)) {
      this.fromMultiparts(input)
    } else if (typeof input === 'object' && input !== null) {
      this.fromJSON(input)
    } else {
      return { success: false, error: 'Invalid input type. Must provide string, object, or array of multiparts' }
    }
  }

  /**
   * Splits the jsonString input into multiparts
   * @param {string} jsonString - string data that is too long to fit onto one FLO transaction
   */
  fromString (jsonString) {
    let chunks = []
    // ToDo:: FLODATA_MAX_LEN vs CHOP_MAX_LEN
    while (jsonString.length > CHOP_MAX_LEN) {
      chunks.push(jsonString.slice(0, CHOP_MAX_LEN))
      jsonString = jsonString.slice(CHOP_MAX_LEN)
    }
    chunks.push(jsonString)

    let max = chunks.length - 1

    // We can do part, max, and data here | ref, sig, and addr are done in publisher
    let multiparts = []
    for (let i = 0; i < chunks.length; i++) {
      let tmpObj = {}
      tmpObj.part = i
      tmpObj.max = max
      tmpObj.data = chunks[i]
      let mps = new MPSingle(tmpObj)
      multiparts.push(mps)
    }

    this.multiparts = multiparts
  }

  /**
   * Returns the assembled data from the multiparts
   * @return {string} assembled
   */
  toString () {
    if (!this.getMultiparts()) {
      return { success: false, error: `No mulitparts found.` }
    }
    let datastring = ''
    for (let mp of this.multiparts) {
      datastring += mp.getData()
    }
    return datastring
  }

  fromJSON (json) {
    this.fromString(JSON.stringify(json))
  }

  /**
   * Takes in an array of {MPSingle} for later method use
   * @param {Array.<MPSingle>} MPSingles - an array of multiparts {MPSingle}
   */
  fromMultiparts (MPSingles) {
    for (let mp of MPSingles) {
      if (!(mp instanceof MPSingle)) { throw new Error('Input must be instanceof MPSingle') }
    }
    MPSingles.sort((a, b) => a.getPart() - b.getPart())
    this.multiparts = MPSingles
  }

  /**
   * Return Multiparts array
   * @return {Array.<MPSingle>} multiparts
   */
  getMultiparts () {
    return this.multiparts || []
  }
}

export default MultipartX