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