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

src/FrameHeader.ts   A

Complexity

Total Complexity 14
Complexity/F 2.33

Size

Lines of Code 111
Function Count 6

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 90
dl 0
loc 111
rs 10
c 0
b 0
f 0
wmc 14
mnd 8
bc 8
fnc 6
bpm 1.3333
cpm 2.3333
noi 0

6 Functions

Rating   Name   Duplication   Size   Complexity  
A FrameHeader.getBuffer 0 6 1
A FrameHeader.ts ➔ extractFlags 0 30 3
A FrameHeader.ts ➔ getHeaderSize 0 3 2
A FrameHeader.ts ➔ createFromBuffer 0 18 4
A FrameHeader.ts ➔ getBodySize 0 12 3
A FrameHeader.ts ➔ getFrameSize 0 3 1
1
import * as ID3Util from './ID3Util'
2
import {
3
    FRAME_IDENTIFIERS,
4
    FRAME_ALIASES }
5
from "./definitions/FrameIdentifiers"
6
7
export type Flags = {
8
    tagAlterPreservation?: boolean
9
    fileAlterPreservation?: boolean
10
    readOnly?: boolean
11
    compression?: boolean
12
    encryption?: boolean
13
    groupingIdentity?: boolean
14
    dataLengthIndicator?: boolean
15
    // Not initialised anywhere right now?
16
    unsynchronisation?: boolean
17
}
18
19
export class FrameHeader {
20
    identifier: string
21
    bodySize: number
22
    flags: Flags
23
24
    constructor(identifier: string, bodySize: number, flags: Flags = {}) {
25
        this.identifier = identifier
26
        this.bodySize = bodySize
27
        this.flags = flags
28
    }
29
30
    static createFromBuffer = createFromBuffer
31
32
    getBuffer() {
33
        const buffer = Buffer.alloc(10)
34
        buffer.write(this.identifier, 0)
35
        buffer.writeUInt32BE(this.bodySize, 4)
36
        return buffer
37
    }
38
39
}
40
41
function createFromBuffer(headerBuffer: Buffer, version: number) {
42
    const identifierSize = version === 2 ? 3 : 4
43
    let identifier = headerBuffer.toString('utf8', 0, identifierSize)
44
    const frameSize = getBodySize(headerBuffer, version)
45
    const flags = extractFlags(headerBuffer[8], headerBuffer[9], version)
46
47
    // Try to convert identifier for older versions
48
    if (version === 2) {
49
        const aliasesV2: Record<string, string> = FRAME_ALIASES.v2
50
        const alias = aliasesV2[identifier]
51
        if (alias) {
52
            const identifiers: Record<string, string> = FRAME_IDENTIFIERS.v34
53
            identifier = identifiers[alias]
54
        }
55
    }
56
57
    return new FrameHeader(identifier, frameSize, flags)
58
}
59
60
function extractFlags(
61
    statusFlag: number,
62
    encodingFlag: number,
63
    version: number
64
) {
65
    if (version === 3) {
66
        return {
67
            tagAlterPreservation: !!(statusFlag & 128),
68
            fileAlterPreservation: !!(statusFlag & 64),
69
            readOnly: !!(statusFlag & 32),
70
            compression: !!(encodingFlag & 128),
71
            encryption: !!(encodingFlag & 64),
72
            groupingIdentity: !!(encodingFlag & 32),
73
            dataLengthIndicator: !!(encodingFlag & 128)
74
        }
75
    }
76
    if (version === 4) {
77
        return {
78
            tagAlterPreservation: !!(statusFlag & 64),
79
            fileAlterPreservation: !!(statusFlag & 32),
80
            readOnly: !!(statusFlag & 16),
81
            groupingIdentity: !!(encodingFlag & 64),
82
            compression: !!(encodingFlag & 8),
83
            encryption: !!(encodingFlag & 4),
84
            unsynchronisation: !!(encodingFlag & 2),
85
            dataLengthIndicator: !!(encodingFlag & 1)
86
        }
87
    }
88
    return {}
89
}
90
91
export function getHeaderSize(version: number) {
92
    return version === 2 ? 6 : 10
93
}
94
95
function getBodySize(headerBuffer: Buffer, version: number) {
96
    const isEncoded = version === 4
97
98
    const bytes = version === 2 ?
99
        [headerBuffer[3], headerBuffer[4], headerBuffer[5]] :
100
        [headerBuffer[4], headerBuffer[5], headerBuffer[6], headerBuffer[7]]
101
102
    if (isEncoded) {
103
        return ID3Util.decodeSize(Buffer.from(bytes))
104
    }
105
    return Buffer.from(bytes).readUIntBE(0, bytes.length)
106
}
107
108
export function getFrameSize(buffer: Buffer, version: number) {
109
    return getHeaderSize(version) + getBodySize(buffer, version)
110
}
111