unpack = function(view, cursor) {
            var i = 0,
                endianness = BIG_ENDIAN,
                start = cursor;
            var type, length, byte_length, value, elem;

            // Retrieve "type"
            type = view.getUint8(cursor, endianness);
            cursor += TYPE_LENGTH;

            if (debug) {
                console.info('Unpacking', type, TypeNames[type]);
            }

            // Retrieve "length"
            if (type === Types.ARRAY || type === Types.OBJECT) {
                length = view.getUint16(cursor, endianness);
                cursor += LENGTH_LENGTH;

                if (debug) {
                    console.info('Content Length', length);
                }
            }

            // Retrieve "byte_length"
            byte_length = view.getUint32(cursor, endianness);
            cursor += BYTES_LENGTH;

            if (debug) {
                console.info('Byte Length', byte_length, 'bytes');
            }

            var type_name = Length[type];
            var unit = type_name === null ? 0 : root[type_name + 'Array'].BYTES_PER_ELEMENT;

            switch (type) {
                case Types.NULL:
                case Types.UNDEFINED:
                    if (debug) {
                        binary_dump(view, start, cursor - start);
                    }
                    // NULL and UNDEFINED doesn't have any octet
                    value = null;
                    break;

                case Types.STRING:
                    length = byte_length / unit;
                    var string = [];
                    for (i = 0; i < length; i++) {
                        var code = view.getUint16(cursor, endianness);
                        cursor += unit;
                        string.push(String.fromCharCode(code));
                    }
                    value = string.join('');
                    if (debug) {
                        console.info('Actual Content %c"' + value + '"', 'font-weight:bold;');
                        binary_dump(view, start, cursor - start);
                    }
                    break;

                case Types.NUMBER:
                    value = view.getFloat64(cursor, endianness);
                    cursor += unit;
                    if (debug) {
                        console.info('Actual Content %c"' + value.toString() + '"', 'font-weight:bold;');
                        binary_dump(view, start, cursor - start);
                    }
                    break;

                case Types.BOOLEAN:
                    value = view.getUint8(cursor, endianness) === 1 ? true : false;
                    cursor += unit;
                    if (debug) {
                        console.info('Actual Content %c"' + value.toString() + '"', 'font-weight:bold;');
                        binary_dump(view, start, cursor - start);
                    }
                    break;

                case Types.INT8ARRAY:
                case Types.INT16ARRAY:
                case Types.INT32ARRAY:
                case Types.UINT8ARRAY:
                case Types.UINT16ARRAY:
                case Types.UINT32ARRAY:
                case Types.FLOAT32ARRAY:
                case Types.FLOAT64ARRAY:
                case Types.ARRAYBUFFER:
                    elem = view.buffer.slice(cursor, cursor + byte_length);
                    cursor += byte_length;

                    // If ArrayBuffer
                    if (type === Types.ARRAYBUFFER) {
                        value = elem;

                        // If other TypedArray
                    } else {
                        value = new root[type_name + 'Array'](elem);
                    }

                    if (debug) {
                        binary_dump(view, start, cursor - start);
                    }
                    break;

                case Types.BLOB:
                    if (debug) {
                        binary_dump(view, start, cursor - start);
                    }
                    // If Blob is available (on browser)
                    if (root.Blob) {
                        var mime = unpack(view, cursor);
                        var buffer = unpack(view, mime.cursor);
                        cursor = buffer.cursor;
                        value = new Blob([buffer.value], {
                            type: mime.value
                        });
                    } else {
                        // node.js implementation goes here
                        elem = view.buffer.slice(cursor, cursor + byte_length);
                        cursor += byte_length;
                        // node.js implementatino uses Buffer to help Blob
                        value = new Buffer(elem);
                    }
                    break;

                case Types.ARRAY:
                    if (debug) {
                        binary_dump(view, start, cursor - start);
                    }
                    value = [];
                    for (i = 0; i < length; i++) {
                        // Retrieve array element
                        elem = unpack(view, cursor);
                        cursor = elem.cursor;
                        value.push(elem.value);
                    }
                    break;

                case Types.OBJECT:
                    if (debug) {
                        binary_dump(view, start, cursor - start);
                    }
                    value = {};
                    for (i = 0; i < length; i++) {
                        // Retrieve object key and value in sequence
                        var key = unpack(view, cursor);
                        var val = unpack(view, key.cursor);
                        cursor = val.cursor;
                        value[key.value] = val.value;
                    }
                    break;

                default:
                    throw 'TypeError: Type not supported.';
            }
            return {
                value: value,
                cursor: cursor
            };
        }
Unpack binary data into an object with value and cursor
@param  {DataView} view [description]
@param  {Number} cursor [description]
@return {Object}