From f5b485d546a20a6bac0bafd124a8cc0e393ca4b1 Mon Sep 17 00:00:00 2001 From: SEK1RO Date: Tue, 5 Aug 2025 10:09:53 +0300 Subject: [PATCH] feat(Int) --- src/Int.js | 87 ++++++++++++++++++++++++++++++++++++++++++++++++ src/index.js | 3 +- test/Int.test.js | 29 ++++++++++++++++ types/Int.d.ts | 3 ++ types/index.d.ts | 3 +- 5 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 src/Int.js create mode 100644 test/Int.test.js create mode 100644 types/Int.d.ts diff --git a/src/Int.js b/src/Int.js new file mode 100644 index 0000000..669c4e3 --- /dev/null +++ b/src/Int.js @@ -0,0 +1,87 @@ +import { Type, limits } from '.' + +export function Int(bits, sign) { + const obj = { _size: bits / 8 } + Object.setPrototypeOf(obj, Int.prototype) + obj.new(Int, arguments) + + switch (sign) { + case 'signed': + switch (bits) { + case 8: + obj._dv_set = DataView.prototype.setInt8 + obj._dv_get = DataView.prototype.getInt8 + obj._limits = limits.i8 + break + + case 16: + obj._dv_set = DataView.prototype.setInt16 + obj._dv_get = DataView.prototype.getInt16 + obj._limits = limits.i16 + break + + case 32: + obj._dv_set = DataView.prototype.setInt32 + obj._dv_get = DataView.prototype.getInt32 + obj._limits = limits.i32 + break + + default: + throw new Error('incorrect bits ' + bits) + } + break + + case 'unsigned': + switch (bits) { + case 8: + obj._dv_set = DataView.prototype.setUint8 + obj._dv_get = DataView.prototype.getUint8 + obj._limits = limits.u8 + break + + case 16: + obj._dv_set = DataView.prototype.setUint16 + obj._dv_get = DataView.prototype.getUint16 + obj._limits = limits.u16 + break + + case 32: + obj._dv_set = DataView.prototype.setUint32 + obj._dv_get = DataView.prototype.getUint32 + obj._limits = limits.u32 + break + + default: + throw new Error('incorrect bits ' + bits) + } + break + + default: + throw new Error('incorrect sign ' + sign) + } + + return obj +} +Int.prototype.serialize = function (dv, src) { + if (dv.byteLength < this._size) { + throw new Error('buffer is too small') + } + if (src > this._limits.MAX_VALUE) { + throw new Error(`number should be less or equal than ` + this._limits.MAX_VALUE) + } + if (src < this._limits.MIN_VALUE) { + throw new Error(`number should be more or equal than ` + this._limits.MIN_VALUE) + } + this._dv_set.call(dv, 0, src) +} +Int.prototype.parse = function (dv) { + return this._dv_get.call(dv, 0) +} +Int.prototype.isHeadless = function () { + return false +} +Int.prototype.sizeof = function () { + return this._size +} +Object.setPrototypeOf(Int.prototype, Type.prototype) +Object.freeze(Int.prototype) diff --git a/src/index.js b/src/index.js index 416a5c7..db82769 100644 --- a/src/index.js +++ b/src/index.js @@ -1,12 +1,13 @@ import { limits } from "./limits" import { memcpy } from "./mem" import { Type } from "./Type" +import { Int } from "./Int" import { ConstString } from './ConstString' import { ConstArray } from "./ConstArray" import { ConstDataView } from './ConstDataView' import { Struct } from './Struct' -export { limits, memcpy, Type, ConstString, ConstArray, ConstDataView, Struct } +export { limits, memcpy, Type, Int, ConstString, ConstArray, ConstDataView, Struct } export function serialize(dv, src, ...types) { const [type, ...inner_types] = types diff --git a/test/Int.test.js b/test/Int.test.js new file mode 100644 index 0000000..50c348c --- /dev/null +++ b/test/Int.test.js @@ -0,0 +1,29 @@ +import { describe, expect, test } from "vitest"; +import { expectDataViewEqual, filledDataView, sizedDataView } from '.'; +import { Int, parse, serialize, sizeof } from "../src"; + +describe(Int.name, () => { + + const Type = Int(32, 'unsigned') + const type = 512 + const type_dv = filledDataView([0x00, 0x00, 0x02, 0x00]) + + test('serialize', () => { + let actual = sizedDataView(3); + expect(() => serialize(actual, type, Type)).toThrow() + + actual = sizedDataView(sizeof(Type)) + serialize(actual, type, Type) + + expectDataViewEqual(actual, type_dv) + }) + + test('parse', () => { + expect(parse(type_dv, Type)).toEqual(type) + }) + + test('serialize, overflow', () => { + expect(() => serialize(sizedDataView(1), 128, Int(8, 'signed'))).toThrow() + expect(() => serialize(sizedDataView(1), -129, Int(8, 'signed'))).toThrow() + }) +}) diff --git a/types/Int.d.ts b/types/Int.d.ts new file mode 100644 index 0000000..8880b3b --- /dev/null +++ b/types/Int.d.ts @@ -0,0 +1,3 @@ +import { Type } from "."; + +export function Int(bits: 8 | 16 | 32, sign: 'signed' | 'unsigned'): Type; diff --git a/types/index.d.ts b/types/index.d.ts index 8cb2205..e0fbae4 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1,12 +1,13 @@ import { memcpy } from "./mem"; import { limits } from "./limits"; import { Type } from "./Type" +import { Int } from "./Int" import { ConstString } from "./ConstString" import { ConstArray } from "./ConstArray"; import { ConstDataView } from "./ConstDataView"; import { Struct } from "./Struct"; -export { memcpy, limits, Type, ConstString, ConstArray, ConstDataView, Struct } +export { memcpy, limits, Type, Int, ConstString, ConstArray, ConstDataView, Struct } export type SerializableType = NumberConstructor | StringConstructor | ArrayConstructor | DataViewConstructor | Type export type Serializable = unknown