• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

benrr101 / node-taglib-sharp / 47997490

10 Sep 2023 05:11AM UTC coverage: 91.944% (-0.05%) from 91.99%
47997490

push

appveyor

benrr101
Child factories have been outlawed

3268 of 4226 branches covered (0.0%)

Branch coverage included in aggregate %.

8 of 8 new or added lines in 3 files covered. (100.0%)

26658 of 28322 relevant lines covered (94.12%)

411.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

41.67
/src/mpeg4/mpeg4BoxHeader.ts
1
import Mpeg4Box from "./boxes/mpeg4Box";
2
import Mpeg4BoxType from "./mpeg4BoxType";
1✔
3
import { ByteVector, StringType } from "../byteVector";
1✔
4
import { File } from "../file";
5
import {Guards, NumberUtils} from "../utils";
1✔
6

7
/**
8
 *  Provides support for reading and writing headers for ISO/IEC 14496-12 boxes.
9
 */
10
export default class Mpeg4BoxHeader {
1✔
11
    /**
12
     *  Contains the box size.
13
     */
14
    private _boxSize: number;
15

16
    /**
17
     * The type of box represented by the current instance.
18
     */
19
    private _boxType: ByteVector;
20

21
    /**
22
     * The extended type of the box represented by the current instance.
23
     */
24
    private _extendedType: ByteVector;
25

26
    /**
27
     *  Contains the header size.
28
     */
29
    private _headerSize: number;
30

31
    /**
32
     *  Contains the position of the header.
33
     */
34
    private _position: number;
35

36
    /**
37
     * Indicates that the header was read from a file.
38
     */
39
    private _fromDisk: boolean;
40

41
    // #region Constructors
42

43
    private constructor() { /* Private to enforce construction via static methods */ }
44

45
    /**
46
     * Constructs and initializes a new instance of {@link Mpeg4BoxHeader} that is empty.
47
     * @returns A new instance of {@link Mpeg4BoxHeader} that is empty.
48
     */
49
    public static fromEmpty(): Mpeg4BoxHeader {
50
        return Mpeg4BoxHeader.fromType(ByteVector.fromString("xxxx", StringType.UTF8));
5✔
51
    }
52

53
    /**
54
     * Constructs and initializes a new instance of {@link Mpeg4BoxHeader} by reading it from a
55
     * specified seek position in a specified file.
56
     * @param file A {@link File} object to read the new instance from.
57
     * @param position A value specifying the seek position in File at which to start reading.
58
     * @returns A new instance of {@link Mpeg4BoxHeader} by reading it from a specified seek position
59
     *     in a specified file.
60
     */
61
    public static fromFileAndPosition(file: File, position: number): Mpeg4BoxHeader {
62
        Guards.notNullOrUndefined(file, "file");
60✔
63

64
        const header = new Mpeg4BoxHeader();
60✔
65
        header._fromDisk = true;
60✔
66
        header._position = position;
60✔
67
        file.seek(position);
60✔
68

69
        const data = file.readBlock(32);
60✔
70
        let offset = 0;
60✔
71

72
        if (data.length < 8 + offset) {
60!
73
            throw new Error("Not enough data in box header.");
×
74
        }
75

76
        header._headerSize = 8;
60✔
77
        header._boxSize = data.subarray(offset, 4).toUint();
60✔
78
        header._boxType = data.subarray(offset + 4, 4);
60✔
79

80
        // If the size is 1, that just tells us we have a massive ULONG size waiting for us in the next 8 bytes.
81
        if (header._boxSize === 1) {
60!
82
            if (data.length < 8 + offset) {
×
83
                throw new Error("Not enough data in box header.");
×
84
            }
85

86
            header._headerSize += 8;
×
87
            offset += 8;
×
88
            header._boxSize = Number(data.subarray(offset, 8).toUlong());
×
89
        }
90

91
        // UUID has a special header with 16 extra bytes.
92
        if (ByteVector.equals(header.boxType, Mpeg4BoxType.UUID)) {
60!
93
            if (data.length < 16 + offset) {
×
94
                throw new Error("Not enough data in box header.");
×
95
            }
96

97
            header._headerSize += 16;
×
98
            header._extendedType = data.subarray(offset, 16);
×
99
        } else {
100
            header._extendedType = undefined;
60✔
101

102
            if (header._boxSize > file.length - position) {
60!
103
                throw new Error(
×
104
                    `Box header specified a size of ${header._boxSize} bytes ` +
105
                    `but only ${file.length - position} bytes left in the file`
106
                );
107
            }
108
        }
109

110
        return header;
60✔
111
    }
112

113
    /**
114
     * Constructs and initializes a new instance of {@link Mpeg4BoxHeader} with a specified box type.
115
     * @param type A ByteVector object containing the four byte box type.
116
     * @returns A new instance of Mpeg4BoxHeader with a specified box type.
117
     */
118
    public static fromType(type: ByteVector): Mpeg4BoxHeader {
119
        return Mpeg4BoxHeader.fromTypeAndExtendedType(type, undefined);
241✔
120
    }
121

122
    /**
123
     * Constructs and initializes a new instance of {@link Mpeg4BoxHeader} with a specified box type
124
     * and optionally extended type.
125
     * @param type A {@link ByteVector} object containing the four byte box type.
126
     * @param extendedType A {@link ByteVector} object containing the four byte box type.
127
     * @returns A new instance of {@link Mpeg4BoxHeader} with a specified box type and optionally extended type.
128
     */
129
    public static fromTypeAndExtendedType(type: ByteVector, extendedType: ByteVector): Mpeg4BoxHeader {
130
        Guards.notNullOrUndefined(type, "type");
241✔
131
        Guards.equals(type.length, 4, "type.length");
241✔
132

133
        const header = new Mpeg4BoxHeader();
241✔
134
        header._position = -1;
241✔
135
        header._fromDisk = false;
241✔
136
        header._boxType = type;
241✔
137
        header._boxSize = 8;
241✔
138
        header._headerSize = 8;
241✔
139

140
        if (!ByteVector.equals(type, Mpeg4BoxType.UUID)) {
241!
141
            if (extendedType) {
241!
142
                throw new Error("Extended type only permitted for 'uuid'.");
×
143
            }
144

145
            header._extendedType = extendedType;
241✔
146
            return header;
241✔
147
        }
148

149
        Guards.notNullOrUndefined(extendedType, "extendedType");
×
150
        Guards.equals(extendedType.length, 16, "extendedType.length");
×
151

152
        header._boxSize = 24;
×
153
        header._headerSize = 24;
×
154
        header._extendedType = extendedType;
×
155

156
        return header;
×
157
    }
158

159
    // #endregion
160

161
    // #region Properties
162

163
    /**
164
     * Gets the type of box represented by the current instance.
165
     */
166
    public get boxType(): ByteVector { return this._boxType; }
582✔
167

168
    /**
169
     * Gets the extended type of the box represented by the current instance.
170
     */
171
    public get extendedType(): ByteVector { return this._extendedType; }
×
172

173
    /**
174
     * Gets the size of the header represented by the current instance.
175
     */
176
    public get headerSize(): number { return this._headerSize; }
266✔
177

178
    /**
179
     * Gets the size of the data in the box described by the current instance.
180
     */
181
    public get dataSize(): number { return this._boxSize - this._headerSize; }
×
182
    /**
183
     * Gets the size of the data in the box described by the current instance.
184
     */
185
    public set dataSize(v: number) { this._boxSize = v + this._headerSize; }
×
186

187
    /**
188
     * Gets the total size of the box described by the current instance.
189
     */
190
    public get totalBoxSize(): number { return this._boxSize; }
120✔
191

192
    /**
193
     * Gets the position box represented by the current instance in the file it comes from.
194
     */
195
    public get position(): number { return this._fromDisk ? this._position : -1; }
236!
196

197
    // #endregion
198

199
    /**
200
     *  Overwrites the header on disk, updating it to include a change in the size of the box.
201
     * @param file  A {@link File} object containing the file from which the box originates.
202
     * @param sizeChange A value indicating the change in the size of the box described by the
203
     *     current instance.
204
     * @returns  The size change encountered by the box that parents the box described the current
205
     *     instance, equal to the size change of the box plus any size change that should happen in
206
     *     the header.
207
     */
208
    public overwrite(file: File, sizeChange: number): number {
209
        Guards.notNullOrUndefined(file, "file");
×
210

211
        if (!this._fromDisk) {
×
212
            throw new Error("Cannot overwrite headers not on disk.");
×
213
        }
214

215
        const oldHeaderSize = this._headerSize;
×
216
        this.dataSize += sizeChange;
×
217
        file.insert(this.render(), this._position, oldHeaderSize);
×
218

219
        return sizeChange + this.headerSize - oldHeaderSize;
×
220
    }
221

222
    /**
223
     * Renders the header represented by the current instance.
224
     * @returns A {@link ByteVector} object containing the rendered version of the current instance.
225
     */
226
    public render(): ByteVector {
227
        // Enlarge for size if necessary.
228
        if ((this._headerSize === 8 || this._headerSize === 24) && this._boxSize > NumberUtils.MAX_UINT) {
×
229
            this._headerSize += 8;
×
230
            this._boxSize += 8;
×
231
        }
232

233
        // Calculate what needs to be rendered
234
        const boxSizeValue = (this._headerSize === 8 || this._headerSize === 24)
×
235
            ? this._boxSize
×
236
            : 1;
237
        const extendedSize = (this._headerSize === 16 || this._headerSize === 32)
×
238
            ? ByteVector.fromUlong(this._boxSize)
×
239
            : undefined;
240
        const extendedType = this.headerSize > 24
×
241
            ? this._extendedType
×
242
            : undefined;
243

244
        // Put it all together
245
        return ByteVector.concatenate(
×
246
            ByteVector.fromUint(boxSizeValue), // Box size of 1 if extended
247
            this._boxType,
248
            extendedSize,                      // Extended size or undefined if box is regular sized
249
            extendedType                       // Extended type or undefined if box is regular sized
250
        )
251
    }
252
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc