Passed
Pull Request — master (#160)
by
unknown
01:45
created

src/frames-reader.ts   A

Complexity

Total Complexity 15
Complexity/F 3

Size

Lines of Code 96
Function Count 5

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 15
eloc 76
mnd 10
bc 10
fnc 5
dl 0
loc 96
rs 10
bpm 2
cpm 3
noi 0
c 0
b 0
f 0

5 Functions

Rating   Name   Duplication   Size   Complexity  
B frames-reader.ts ➔ getFramesFromTagBody 0 28 5
A frames-reader.ts ➔ getTagsFromTagBody 0 10 1
A frames-reader.ts ➔ getTagsFromBuffer 0 7 2
B frames-reader.ts ➔ getTagsFromFrames 0 30 5
A frames-reader.ts ➔ isFrameDiscarded 0 6 2
1
import { Frame } from './Frame'
2
import { getFrameSize } from './FrameHeader'
3
import { Options } from "./types/Options"
4
import { Tags, TagIdentifiers } from './types/Tags'
5
import { isBuffer } from "./util"
6
import { convertRawTagsToTagAliases } from "./TagsConverters"
7
import { getId3TagBody } from './id3-tag'
8
import { getFrameOptions } from './util-frame-options'
9
10
export function getTagsFromBuffer(buffer: Buffer, options: Options) {
11
    const tagBody = getId3TagBody(buffer)
12
    if (tagBody === undefined) {
13
        return getTagsFromFrames([], 3, options)
14
    }
15
    return getTagsFromTagBody(tagBody.body, tagBody.version, options)
16
}
17
18
export function getTagsFromTagBody(
19
    body: Buffer,
20
    version = 3,
21
    options: Options = {}
22
) {
23
    return getTagsFromFrames(
24
        getFramesFromTagBody(body, version, options),
25
        version,
26
        options
27
    )
28
}
29
30
function isFrameDiscarded(frameId: string, options: Options) {
31
    if (Array.isArray(options.exclude) && options.exclude.includes(frameId)) {
32
        return true
33
    }
34
    return Array.isArray(options.include) && !options.include.includes(frameId)
35
}
36
37
function getFramesFromTagBody(
38
    tagBody: Buffer,
39
    version: number,
40
    options: Options = {}
41
) {
42
    if (!isBuffer(tagBody)) {
43
        return []
44
    }
45
46
    const frames = []
47
    while(tagBody.length && tagBody[0] !== 0x00) {
48
        const frameSize = getFrameSize(tagBody, version)
49
50
        // Prevent errors due to broken data.
51
        if (frameSize > tagBody.length) {
52
            break
53
        }
54
55
        const frameBuffer = tagBody.subarray(0, frameSize)
56
        const frame = Frame.createFromBuffer(frameBuffer, version)
57
        if (frame && !isFrameDiscarded(frame.identifier, options)) {
58
            frames.push(frame)
59
        }
60
61
        tagBody = tagBody.subarray(frameSize)
62
    }
63
    return frames
64
}
65
66
function getTagsFromFrames(
67
    frames: Frame[],
68
    _version: number,
69
    options: Options = {}
70
): Tags | TagIdentifiers {
71
    const pushValue = (dest: unknown, value: unknown) => {
72
        const destArray = Array.isArray(dest) ? dest : []
73
        destArray.push(value)
74
        return destArray
75
    }
76
    const getValue = (_dest: unknown, value: unknown) => value
77
78
    const rawTags = frames.reduce<TagIdentifiers>((tags, frame) => {
79
        const frameId = frame.identifier as keyof TagIdentifiers
80
        const isMultiple = getFrameOptions(frameId).multiple
81
        const makeValue = isMultiple ? pushValue : getValue
82
        tags[frameId] = makeValue(tags[frameId], frame.getValue()) as never
83
        return tags
84
    }, {})
85
86
    if (options.onlyRaw) {
87
        return rawTags
88
    }
89
90
    const tags = convertRawTagsToTagAliases(rawTags)
91
    if (options.noRaw) {
92
        return tags
93
    }
94
    return { ...tags, raw: rawTags }
95
}
96