• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16const decoder = new TextDecoder();
17export const toUTF8String = (
18    input: Uint8Array,
19    start = 0,
20    end = input.length
21): string => decoder.decode(input.slice(start, end));
22
23export const toHexString = (
24    input: Uint8Array,
25    start = 0,
26    end = input.length
27): string => input.slice(start, end).reduce((memo, i) => memo + `0${i.toString(16)}`.slice(-2), '');
28
29const getView = (
30    input: Uint8Array,
31    offset: number
32): DataView => new DataView(input.buffer, input.byteOffset + offset);
33
34export const readInt16LE = (input: Uint8Array, offset = 0): number =>
35    getView(input, offset).getInt16(0, true);
36
37export const readUInt16BE = (input: Uint8Array, offset = 0): number =>
38    getView(input, offset).getUint16(0, false);
39
40export const readUInt16LE = (input: Uint8Array, offset = 0): number =>
41    getView(input, offset).getUint16(0, true);
42
43export const readUInt24LE = (input: Uint8Array, offset = 0): number => {
44    const view = getView(input, offset);
45    return view.getUint16(0, true) + (view.getUint8(2) << 16);
46};
47
48export const readInt32LE = (input: Uint8Array, offset = 0): number =>
49    getView(input, offset).getInt32(0, true);
50
51export const readUInt32BE = (input: Uint8Array, offset = 0): number =>
52    getView(input, offset).getUint32(0, false);
53
54export const readUInt32LE = (input: Uint8Array, offset = 0): number =>
55    getView(input, offset).getUint32(0, true);
56
57export const readUInt64 = (
58    input: Uint8Array,
59    offset: number,
60    isBigEndian: boolean
61): bigint => getView(input, offset).getBigUint64(0, !isBigEndian);
62
63const methods = {
64    readUInt16BE,
65    readUInt16LE,
66    readUInt32BE,
67    readUInt32LE
68} as const;
69
70type MethodName = keyof typeof methods;
71
72export function readUInt(
73    input: Uint8Array,
74    bits: 16 | 32,
75    offset = 0,
76    isBigEndian = false
77): number {
78    const endian = isBigEndian ? 'BE' : 'LE';
79    const methodName = `readUInt${bits}${endian}` as MethodName;
80    return methods[methodName](input, offset);
81}
82
83const INCH_CM = 2.54;
84
85const units: Record<string, number> = {
86    in: 96,
87    cm: 96 / INCH_CM,
88    em: 16,
89    ex: 8,
90    m: (96 / INCH_CM) * 100,
91    mm: 96 / INCH_CM / 10,
92    pc: 96 / 72 / 12,
93    pt: 96 / 72,
94    px: 1,
95};
96const unitsReg = new RegExp(`^([0-9.]+(?:e\\d+)?)(${Object.keys(units).join('|')})?$`,);
97
98export function getLength(len: string): number | undefined {
99    const m = unitsReg.exec(len);
100    if (!m) {
101        return undefined;
102    }
103    return Math.round(Number(m[1]) * (units[m[2]] || 1));
104}
105