obj2u8arr.mjs

import each from 'lodash-es/each.js'
import isearr from './isearr.mjs'
import iseobj from './iseobj.mjs'
import getBufferSize from './getBufferSize.mjs'
import obj2stru8arr from './obj2stru8arr.mjs'
import str2u8arr from './str2u8arr.mjs'
import bufWriteDbl from './bufWriteDbl.mjs'


// function concatU8arr(a, b) { //處理大檔時Nodejs記憶體會不足
//     return Uint8Array.from([...a, ...b])
// }
function concatU8arr(a, b) {
    let ia = getBufferSize(a)
    let ib = getBufferSize(b)
    let tmp = new Uint8Array(ia + ib)
    tmp.set(new Uint8Array(a), 0)
    tmp.set(new Uint8Array(b), ia)
    return tmp
}


/**
 * 物件或陣列資料轉Uint8Array
 *
 * Unit Test: {@link https://github.com/yuda-lyu/wsemi/blob/master/test/obj2u8arr.test.mjs Github}
 * @memberOf wsemi
 * @param {Object|Array} data 輸入物件或陣列資料,物件內可支援Uint8Array、Uint16Array、ArrayBuffer,注意因ArrayBuffer無法直接操作(非View,只有TypedArray與DataView可操作)故預設會轉Uint8Array進行處理
 * @returns {Uint8Array} 回傳Uint8Array
 * @example
 *
 * let data = {
 *     a: [123, 45.67, 'test中文'],
 *     b: {
 *         c: new Uint8Array([66, 97, 115]),
 *     },
 * }
 * let u8a = obj2u8arr(data)
 * console.log(u8a)
 * // => Uint8Array [
 * //     64,  24,   0,   0,   0,  0,  0,   0,  91,  53,  56,  44,
 * //     51,  93, 123,  34,  97, 34, 58,  91,  49,  50,  51,  44,
 * //     52,  53,  46,  54,  55, 44, 34, 116, 101, 115, 116, 228,
 * //    184, 173, 230, 150, 135, 34, 93,  44,  34,  98,  34,  58,
 * //    123,  34,  99,  34,  58, 34, 91,  85, 105, 110, 116,  56,
 * //     65, 114, 114,  97, 121, 93, 58,  58,  48,  34, 125, 125,
 * //     66,  97, 115
 * // ]
 *
 */
function obj2u8arr(data) {
    let bs = []
    let r = []

    //check
    if (!isearr(data) && !iseobj(data)) {
        return null
    }

    //addBin
    let pkLens = []
    let pkBins = []
    function addBin(b) {
        pkLens.push(getBufferSize(b))
        pkBins.push(b)
    }

    try {

        //obj2stru8arr
        let sb = obj2stru8arr(data) //序列化數據, 分別為無Uint8Array序列化字串(results), 以及各Uint8Array數據(binarys)
        //console.log('sb', sb)

        //sb.results
        let bMain = str2u8arr(sb.results) //無Uint8Array序列化字串轉二進位數據(Uint8Array)
        addBin(bMain) //加入無Uint8Array序列化字串二進位數據(Uint8Array)

        //sb.binarys
        each(sb.binarys, (b) => {
            addBin(b) //加入各分塊二進位數據(Uint8Array)
        })

        //bPks
        let vPks = pkLens //各分塊長度資訊
        let bPks = str2u8arr(JSON.stringify(vPks)) //各分塊長度資訊序列化成字串, 再轉二進位數據(Uint8Array)

        //push head
        let ibHead = 8 //預設用開頭8 bytes來儲存分塊資訊之長度
        let bHead = new Uint8Array(ibHead) //宣告
        bufWriteDbl(getBufferSize(bPks), bHead) //寫入分塊資訊之長度
        bs.push(bHead) //推入開頭儲存分塊資訊之長度

        //push
        bs.push(bPks) //推入各分塊資訊長度陣列

        //push
        each(pkBins, (b) => {
            bs.push(b) //推入各分塊資訊
        })

        //flatten
        each(bs, (b) => {
            r = concatU8arr(r, b) //合併各二進位數據
        })

    }
    catch (err) {
        return null
    }

    return r
}


export default obj2u8arr