Passed
Pull Request — master (#136)
by
unknown
01:51
created

FrameReader.ts ➔ convertValue   B

Complexity

Conditions 6

Size

Total Lines 22
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 16
dl 0
loc 22
rs 8.6666
c 0
b 0
f 0
cc 6
1
import { SplitBuffer, } from "./ID3Util"
2
import * as ID3Util from "./ID3Util"
3
4
type DataType = "string" | "number"
5
6
export class FrameReader {
7
    private _encoding: number
8
    private _splitBuffer: SplitBuffer
9
10
    constructor(
11
        buffer: Buffer,
12
        encodingBytePosition: number,
13
        consumeEncodingByte = true
14
    ) {
15
        if (!buffer || !(buffer instanceof Buffer)) {
16
            buffer = Buffer.alloc(0)
17
        }
18
        if (Number.isInteger(encodingBytePosition)) {
19
            this._encoding = buffer[encodingBytePosition] ? buffer[encodingBytePosition] : 0x00
20
            if (consumeEncodingByte) {
21
                buffer = encodingBytePosition === 0 ?
22
                    buffer.subarray(1) :
23
                    Buffer.concat([
24
                        buffer.subarray(0, encodingBytePosition),
25
                        buffer.subarray(encodingBytePosition)
26
                    ])
27
            }
28
        } else {
29
            this._encoding = 0x00
30
        }
31
        this._splitBuffer = new SplitBuffer(null, buffer.subarray(0))
32
    }
33
34
    consumeStaticValue(
35
        dataType: DataType,
36
        size: number,
37
        encoding = this._encoding
38
    ) {
39
        return this._consumeByFunction(
40
            // TODO check if this._splitBuffer.remainder can be null!
41
            // eslint-disable-next-line
42
            () => staticValueFromBuffer(this._splitBuffer.remainder!, size),
43
            dataType,
44
            encoding
45
        )
46
    }
47
48
    consumeNullTerminatedValue(
49
        dataType: DataType,
50
        encoding = this._encoding
51
    ) {
52
        return this._consumeByFunction(
53
            // TODO check if this._splitBuffer.remainder can be null!
54
            // eslint-disable-next-line
55
            () => nullTerminatedValueFromBuffer(this._splitBuffer.remainder!, encoding),
56
            dataType,
57
            encoding
58
        )
59
    }
60
61
    private _consumeByFunction(
62
        fn: () => SplitBuffer,
63
        dataType: DataType,
64
        encoding: number
65
    ) {
66
        if (
67
            !this._splitBuffer.remainder ||
68
            this._splitBuffer.remainder.length === 0
69
        ) {
70
            return undefined
71
        }
72
        this._splitBuffer = fn()
73
        if (dataType) {
74
            return convertValue(this._splitBuffer.value, dataType, encoding)
75
        }
76
        return this._splitBuffer.value
77
    }
78
}
79
80
function convertValue(
81
    buffer: Buffer | number | string | null,
82
    dataType: DataType,
83
    encoding = 0x00
84
) {
85
    if (!buffer) {
86
        return undefined
87
    }
88
    if (!(buffer instanceof Buffer)) {
89
        return buffer
90
    }
91
    if (buffer.length === 0) {
92
        return undefined
93
    }
94
    if (dataType === "number") {
95
        return parseInt(buffer.toString('hex'), 16)
96
    }
97
    if (dataType === "string") {
98
        return ID3Util.bufferToDecodedString(buffer, encoding)
99
    }
100
    return buffer
101
}
102
103
function staticValueFromBuffer(
104
    buffer: Buffer,
105
    size: number
106
): SplitBuffer {
107
    size = size ?? buffer.length
108
    if (buffer.length > size) {
109
        return new SplitBuffer(
110
            buffer.subarray(0, size), buffer.subarray(size)
111
        )
112
    }
113
    return new SplitBuffer(buffer.subarray(0), null)
114
}
115
116
function nullTerminatedValueFromBuffer(
117
    buffer: Buffer,
118
    encoding = 0x00
119
): SplitBuffer {
120
    return ID3Util.splitNullTerminatedBuffer(buffer, encoding)
121
}
122