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

frames-reader.ts ➔ getFramesFromTagBody   B

Complexity

Conditions 5

Size

Total Lines 28
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 22
dl 0
loc 28
rs 8.8853
c 0
b 0
f 0
cc 5
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