@rotu/structview 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/deno.yml +32 -0
- package/.github/workflows/publish.yml +20 -0
- package/.vscode/settings.json +4 -0
- package/README.md +86 -0
- package/_dist/bigendian.d.ts +32 -0
- package/_dist/bigendian.d.ts.map +1 -0
- package/_dist/mod.d.ts +135 -0
- package/_dist/mod.d.ts.map +1 -0
- package/bigendian.js +122 -0
- package/bigendian.js.map +1 -0
- package/bigendian.ts +136 -0
- package/bigendian_test.ts +70 -0
- package/deno.json +18 -0
- package/deno.lock +23 -0
- package/mod.js +336 -0
- package/mod.js.map +1 -0
- package/mod.ts +487 -0
- package/mod_bench.ts +98 -0
- package/mod_test.ts +319 -0
- package/package.json +18 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Deno
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: ["main"]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: ["main"]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- name: Setup repo
|
|
18
|
+
uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Setup Deno
|
|
21
|
+
uses: denoland/setup-deno@v2
|
|
22
|
+
with:
|
|
23
|
+
deno-version: vx.x.x
|
|
24
|
+
|
|
25
|
+
- name: Verify formatting
|
|
26
|
+
run: deno fmt --check
|
|
27
|
+
|
|
28
|
+
- name: Run linter
|
|
29
|
+
run: deno lint
|
|
30
|
+
|
|
31
|
+
- name: Run tests
|
|
32
|
+
run: deno test -A
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches:
|
|
5
|
+
- main
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
publish:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
id-token: write
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
- name: Setup Deno
|
|
16
|
+
uses: denoland/setup-deno@v2
|
|
17
|
+
with:
|
|
18
|
+
deno-version: vx.x.x
|
|
19
|
+
- name: Publish package
|
|
20
|
+
run: deno publish
|
package/README.md
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# structview
|
|
2
|
+
|
|
3
|
+
The point of this package is provide the ability to manipulate binary structured
|
|
4
|
+
data in a typesafe, declarative, object-oriented way.
|
|
5
|
+
|
|
6
|
+
1. Read and write binary-structured data with the same declaration
|
|
7
|
+
2. Single source of truth - changes to logical view are immediately reflected in
|
|
8
|
+
the underlying binary structure and vice versa.
|
|
9
|
+
3. Written in TypeScript, written FOR JavaScript. Declaring a struct allows full
|
|
10
|
+
type inference; no separate type declaration required!
|
|
11
|
+
4. Clean object format. No risk of your struct field names colliding with
|
|
12
|
+
implementation details. Type inference won't show excessive properties.
|
|
13
|
+
|
|
14
|
+
[](https://jsr.io/@rotu/structview)
|
|
15
|
+
|
|
16
|
+
# example
|
|
17
|
+
|
|
18
|
+
This example is pure JavaScript, but note that all property access is fully
|
|
19
|
+
typechecked.
|
|
20
|
+
|
|
21
|
+
```js
|
|
22
|
+
import {
|
|
23
|
+
defineArray,
|
|
24
|
+
defineStruct,
|
|
25
|
+
f32,
|
|
26
|
+
string,
|
|
27
|
+
substruct,
|
|
28
|
+
u8,
|
|
29
|
+
} from "@rotu/structview"
|
|
30
|
+
|
|
31
|
+
// defineStruct returns a new class, which can be extended with custom getters, setters, and methods
|
|
32
|
+
// it's recommended to always extend even if you have no additional members, so you can benefit from declaration hoisting.
|
|
33
|
+
class Version extends defineStruct({
|
|
34
|
+
major: u8(0),
|
|
35
|
+
minor: u8(1),
|
|
36
|
+
patch: u8(2),
|
|
37
|
+
}) {
|
|
38
|
+
asString() {
|
|
39
|
+
// Struct fields are exposed as properties. They can be destructured like any other js object
|
|
40
|
+
const { major, minor, patch } = this
|
|
41
|
+
return `${major}.${minor}.${patch}`
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
class ProductInfo extends defineStruct({
|
|
46
|
+
version: substruct(Version, 0, 3),
|
|
47
|
+
product: string(4, 12),
|
|
48
|
+
}) {}
|
|
49
|
+
|
|
50
|
+
const bytes = new Uint8Array(16)
|
|
51
|
+
const info = new ProductInfo(bytes)
|
|
52
|
+
|
|
53
|
+
info.product = "Widget"
|
|
54
|
+
// Basic object assignment and destructuring just works
|
|
55
|
+
Object.assign(info.version, { major: 1, minor: 42, patch: 1 })
|
|
56
|
+
|
|
57
|
+
// Object writes are saved in the underlying buffer
|
|
58
|
+
console.log(
|
|
59
|
+
"encoded hex:",
|
|
60
|
+
bytes.toHex(),
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
console.log(`${info.product} v${info.version.asString()}`)
|
|
64
|
+
|
|
65
|
+
// You can compose structs into arrays
|
|
66
|
+
class Dish extends defineStruct({
|
|
67
|
+
price: f32(0),
|
|
68
|
+
name: string(4, 12),
|
|
69
|
+
}) {}
|
|
70
|
+
|
|
71
|
+
class Menu extends defineArray({
|
|
72
|
+
struct: Dish,
|
|
73
|
+
byteStride: 16,
|
|
74
|
+
length: 3,
|
|
75
|
+
}) {}
|
|
76
|
+
|
|
77
|
+
const myMenu = new Menu({ byteLength: 48 })
|
|
78
|
+
Object.assign(myMenu.element(0), { name: "garden salad", price: 4 })
|
|
79
|
+
Object.assign(myMenu.element(1), { name: "soup du jour", price: 2.5 })
|
|
80
|
+
Object.assign(myMenu.element(2), { name: "fries", price: 2.25 })
|
|
81
|
+
|
|
82
|
+
// and arrays are iterable
|
|
83
|
+
for (const dish of myMenu) {
|
|
84
|
+
console.log(`${dish.name} costs \$${dish.price}`)
|
|
85
|
+
}
|
|
86
|
+
```
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Property descriptor factories for big-endian numbers
|
|
3
|
+
* @module
|
|
4
|
+
*/ import { type StructPropertyDescriptor } from "./mod.js";
|
|
5
|
+
/**
|
|
6
|
+
* Field for a big-endian 16-bit unsigned integer
|
|
7
|
+
*/ export declare function u16be(fieldOffset: number): StructPropertyDescriptor<number>;
|
|
8
|
+
/**
|
|
9
|
+
* Field for a big-endian 32-bit unsigned integer
|
|
10
|
+
*/ export declare function u32be(fieldOffset: number): StructPropertyDescriptor<number>;
|
|
11
|
+
/**
|
|
12
|
+
* Field for a big-endian 64-bit unsigned integer
|
|
13
|
+
*/ export declare function u64be(fieldOffset: number): StructPropertyDescriptor<bigint>;
|
|
14
|
+
/**
|
|
15
|
+
* Field for a big-endian 16-bit signed integer
|
|
16
|
+
*/ export declare function i16be(fieldOffset: number): StructPropertyDescriptor<number>;
|
|
17
|
+
/**
|
|
18
|
+
* Field for a big-endian 32-bit signed integer
|
|
19
|
+
*/ export declare function i32be(fieldOffset: number): StructPropertyDescriptor<number>;
|
|
20
|
+
/**
|
|
21
|
+
* Field for a big-endian 64-bit signed integer
|
|
22
|
+
*/ export declare function i64be(fieldOffset: number): StructPropertyDescriptor<bigint>;
|
|
23
|
+
/**
|
|
24
|
+
* Field for a big-endian 16-bit binary float (float16_t)
|
|
25
|
+
*/ export declare function f16be(fieldOffset: number): StructPropertyDescriptor<number>;
|
|
26
|
+
/**
|
|
27
|
+
* Field for a big-endian 32-bit binary float (float32_t)
|
|
28
|
+
*/ export declare function f32be(fieldOffset: number): StructPropertyDescriptor<number>;
|
|
29
|
+
/**
|
|
30
|
+
* Field for a big-endian 64-bit binary float (float64_t)
|
|
31
|
+
*/ export declare function f64be(fieldOffset: number): StructPropertyDescriptor<number>;
|
|
32
|
+
//# sourceMappingURL=bigendian.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bigendian.d.ts","sources":["../bigendian.ts"],"names":[],"mappings":"AAAA;;;CAGC,GAED,SAAyB,KAAK,wBAAwB,mBAAkB;AAExE;;CAEC,GACD,OAAO,iBAAS,MAAM,aAAa,MAAM,GAAG,yBAAyB,MAAM;AAW3E;;CAEC,GACD,OAAO,iBAAS,MAAM,aAAa,MAAM,GAAG,yBAAyB,MAAM;AAW3E;;CAEC,GACD,OAAO,iBAAS,MAAM,aAAa,MAAM,GAAG,yBAAyB,MAAM;AAW3E;;CAEC,GACD,OAAO,iBAAS,MAAM,aAAa,MAAM,GAAG,yBAAyB,MAAM;AAW3E;;CAEC,GACD,OAAO,iBAAS,MAAM,aAAa,MAAM,GAAG,yBAAyB,MAAM;AAW3E;;CAEC,GACD,OAAO,iBAAS,MAAM,aAAa,MAAM,GAAG,yBAAyB,MAAM;AAY3E;;CAEC,GACD,OAAO,iBAAS,MAAM,aAAa,MAAM,GAAG,yBAAyB,MAAM;AAY3E;;CAEC,GACD,OAAO,iBAAS,MAAM,aAAa,MAAM,GAAG,yBAAyB,MAAM;AAY3E;;CAEC,GACD,OAAO,iBAAS,MAAM,aAAa,MAAM,GAAG,yBAAyB,MAAM"}
|
package/_dist/mod.d.ts
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strongly typed classes for accessing binary data in a structured way
|
|
3
|
+
* @module
|
|
4
|
+
*/ declare const dataViewSymbol: unique symbol;
|
|
5
|
+
type AnyStruct = {
|
|
6
|
+
get [dataViewSymbol](): DataView;
|
|
7
|
+
};
|
|
8
|
+
type Constructor<T> = {
|
|
9
|
+
new(...args: any[]): T;
|
|
10
|
+
};
|
|
11
|
+
type SubclassWithProperties<Ctor extends Constructor<object>, Mixin> = {
|
|
12
|
+
[K in keyof Ctor]: Ctor[K];
|
|
13
|
+
} & {
|
|
14
|
+
new(...args: ConstructorParameters<Ctor>): InstanceType<Ctor> & {
|
|
15
|
+
-readonly [K in keyof Mixin]: Mixin[K];
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
type TPropertyDescriptor<T> = {
|
|
19
|
+
enumerable?: boolean;
|
|
20
|
+
configurable?: boolean;
|
|
21
|
+
get?(): T;
|
|
22
|
+
set?(t: T): undefined;
|
|
23
|
+
value?: T;
|
|
24
|
+
writable?: boolean;
|
|
25
|
+
};
|
|
26
|
+
type MixinFromProps<Props extends object> = {
|
|
27
|
+
[K in keyof Props]: Props[K] extends TPropertyDescriptor<infer V> ? V : unknown;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Get the underlying DataView of a struct
|
|
31
|
+
* @param struct
|
|
32
|
+
* @returns
|
|
33
|
+
*/ export declare function structDataView(struct: AnyStruct): DataView;
|
|
34
|
+
/**
|
|
35
|
+
* Type of a property descriptor for a struct
|
|
36
|
+
*/ export type StructPropertyDescriptor<T> = ThisType<AnyStruct> & TPropertyDescriptor<T>;
|
|
37
|
+
/**
|
|
38
|
+
* Define a descriptor based on a dataview of the struct
|
|
39
|
+
* @param fieldGetter function which, given a dataview, returns
|
|
40
|
+
* @returns
|
|
41
|
+
*/ export declare function fromDataView<Fn extends (dv: DataView) => unknown>(fieldGetter: Fn): StructPropertyDescriptor<ReturnType<Fn>>;
|
|
42
|
+
/**
|
|
43
|
+
* Field for a 8-bit unsigned integer
|
|
44
|
+
*/ export declare function u8(fieldOffset: number): StructPropertyDescriptor<number>;
|
|
45
|
+
/**
|
|
46
|
+
* Field for a little-endian 16-bit unsigned integer
|
|
47
|
+
*/ export declare function u16(fieldOffset: number): StructPropertyDescriptor<number>;
|
|
48
|
+
/**
|
|
49
|
+
* Field for a little-endian 32-bit unsigned integer
|
|
50
|
+
*/ export declare function u32(fieldOffset: number): StructPropertyDescriptor<number>;
|
|
51
|
+
/**
|
|
52
|
+
* Field for a little-endian 64-bit unsigned integer
|
|
53
|
+
*/ export declare function u64(fieldOffset: number): StructPropertyDescriptor<bigint>;
|
|
54
|
+
/**
|
|
55
|
+
* Field for a little-endian 8-bit signed integer
|
|
56
|
+
*/ export declare function i8(fieldOffset: number): StructPropertyDescriptor<number>;
|
|
57
|
+
/**
|
|
58
|
+
* Field for a little-endian 16-bit signed integer
|
|
59
|
+
*/ export declare function i16(fieldOffset: number): StructPropertyDescriptor<number>;
|
|
60
|
+
/**
|
|
61
|
+
* Field for a little-endian 32-bit signed integer
|
|
62
|
+
*/ export declare function i32(fieldOffset: number): StructPropertyDescriptor<number>;
|
|
63
|
+
/**
|
|
64
|
+
* Field for a little-endian 64-bit signed integer
|
|
65
|
+
*/ export declare function i64(fieldOffset: number): StructPropertyDescriptor<bigint>;
|
|
66
|
+
/**
|
|
67
|
+
* Field for a little-endian 16-bit binary float (float16_t)
|
|
68
|
+
*/ export declare function f16(fieldOffset: number): StructPropertyDescriptor<number>;
|
|
69
|
+
/**
|
|
70
|
+
* Field for a little-endian 32-bit binary float (float32_t)
|
|
71
|
+
*/ export declare function f32(fieldOffset: number): StructPropertyDescriptor<number>;
|
|
72
|
+
/**
|
|
73
|
+
* Field for a little-endian 64-bit binary float (float64_t)
|
|
74
|
+
*/ export declare function f64(fieldOffset: number): StructPropertyDescriptor<number>;
|
|
75
|
+
/**
|
|
76
|
+
* Field for a UTF-8 fixed-length string
|
|
77
|
+
*/ export declare function string(fieldOffset: number, byteLength: number): StructPropertyDescriptor<string>;
|
|
78
|
+
/**
|
|
79
|
+
* Field for a boolean stored in a byte (0 = false, nonzero = true)
|
|
80
|
+
* True will be stored as 1
|
|
81
|
+
*/ export declare function bool(fieldOffset: number): StructPropertyDescriptor<boolean>;
|
|
82
|
+
type StructConstructor<T extends object> = {
|
|
83
|
+
new(arg: {
|
|
84
|
+
buffer: ArrayBufferLike;
|
|
85
|
+
byteOffset?: number;
|
|
86
|
+
byteLength?: number;
|
|
87
|
+
}): T;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Field for an embedded struct
|
|
91
|
+
* @param ctor constructor for the inner struct
|
|
92
|
+
* @param byteOffset where the inner struct starts relative to the outer struct
|
|
93
|
+
* @param bytelength the length in bytes of the inner struct
|
|
94
|
+
* @returns property descriptor for a struct
|
|
95
|
+
*/ export declare function substruct<T extends object>(ctor: StructConstructor<T>, byteOffset?: number, bytelength?: number): StructPropertyDescriptor<T>;
|
|
96
|
+
/**
|
|
97
|
+
* Base class for a structured binary object
|
|
98
|
+
* Note there are no predeclared string-keyed properties - all property names are reserved for user-defined fields
|
|
99
|
+
*/ export declare class Struct {
|
|
100
|
+
[dataViewSymbol]: DataView;
|
|
101
|
+
static toDataView(o: Struct): DataView;
|
|
102
|
+
/**
|
|
103
|
+
* Create a new Struct
|
|
104
|
+
* @param arg options for creating the struct.
|
|
105
|
+
* If options has a `.buffer` property, we will use that as the backing memory (e.g. any TypedArray or DataView).
|
|
106
|
+
* If options has no `.buffer` property but has a `.byteLength`, we will allocate a new buffer for the object.
|
|
107
|
+
*/ constructor(arg: {
|
|
108
|
+
buffer: ArrayBufferLike;
|
|
109
|
+
byteOffset?: number;
|
|
110
|
+
byteLength?: number;
|
|
111
|
+
} | {
|
|
112
|
+
buffer?: undefined;
|
|
113
|
+
byteOffset?: number;
|
|
114
|
+
byteLength: number;
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Subclass struct by adding the given property descriptors
|
|
119
|
+
* @param propertyDescriptors properties to add to subclass instances
|
|
120
|
+
* @returns A new class, inheriting from `Struct`, with the new property descriptors added
|
|
121
|
+
*/ export declare function defineStruct<const Props extends PropertyDescriptorMap>(propertyDescriptors: Props): SubclassWithProperties<typeof Struct, MixinFromProps<Props>>;
|
|
122
|
+
/**
|
|
123
|
+
* Create a new struct subclass for an array of structs
|
|
124
|
+
* @param arrayOptions
|
|
125
|
+
* @returns A new class, inheriting from `Struct` whose elements are statically typed structs
|
|
126
|
+
*/ export declare function defineArray<Ctor extends StructConstructor<object>>(arrayOptions: {
|
|
127
|
+
/** Constructor for an object view of each element*/ struct: Ctor;
|
|
128
|
+
/** Number of bytes between the start of consecutive elements */ byteStride: number;
|
|
129
|
+
/** Total number of elements in the array (not bytes). If omitted, the array length will depend on the size of its underlying buffer */ length?: number;
|
|
130
|
+
}): StructConstructor<{
|
|
131
|
+
get length(): number;
|
|
132
|
+
element(i: number): InstanceType<Ctor>;
|
|
133
|
+
[i: number]: InstanceType<Ctor>;
|
|
134
|
+
} & Iterable<InstanceType<Ctor>>>;
|
|
135
|
+
//# sourceMappingURL=mod.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sources":["../mod.ts"],"names":[],"mappings":"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"}
|
package/bigendian.js
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Property descriptor factories for big-endian numbers
|
|
3
|
+
* @module
|
|
4
|
+
*/ import { structDataView } from "./mod.js";
|
|
5
|
+
/**
|
|
6
|
+
* Field for a big-endian 16-bit unsigned integer
|
|
7
|
+
*/ export function u16be(fieldOffset) {
|
|
8
|
+
return {
|
|
9
|
+
enumerable: true,
|
|
10
|
+
get () {
|
|
11
|
+
return structDataView(this).getUint16(fieldOffset, false);
|
|
12
|
+
},
|
|
13
|
+
set (value) {
|
|
14
|
+
structDataView(this).setUint16(fieldOffset, value, false);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Field for a big-endian 32-bit unsigned integer
|
|
20
|
+
*/ export function u32be(fieldOffset) {
|
|
21
|
+
return {
|
|
22
|
+
enumerable: true,
|
|
23
|
+
get () {
|
|
24
|
+
return structDataView(this).getUint32(fieldOffset, false);
|
|
25
|
+
},
|
|
26
|
+
set (value) {
|
|
27
|
+
structDataView(this).setUint32(fieldOffset, value, false);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Field for a big-endian 64-bit unsigned integer
|
|
33
|
+
*/ export function u64be(fieldOffset) {
|
|
34
|
+
return {
|
|
35
|
+
enumerable: true,
|
|
36
|
+
get () {
|
|
37
|
+
return structDataView(this).getBigUint64(fieldOffset, false);
|
|
38
|
+
},
|
|
39
|
+
set (value) {
|
|
40
|
+
structDataView(this).setBigUint64(fieldOffset, value, false);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Field for a big-endian 16-bit signed integer
|
|
46
|
+
*/ export function i16be(fieldOffset) {
|
|
47
|
+
return {
|
|
48
|
+
enumerable: true,
|
|
49
|
+
get () {
|
|
50
|
+
return structDataView(this).getInt16(fieldOffset, false);
|
|
51
|
+
},
|
|
52
|
+
set (value) {
|
|
53
|
+
structDataView(this).setInt16(fieldOffset, value, false);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Field for a big-endian 32-bit signed integer
|
|
59
|
+
*/ export function i32be(fieldOffset) {
|
|
60
|
+
return {
|
|
61
|
+
enumerable: true,
|
|
62
|
+
get () {
|
|
63
|
+
return structDataView(this).getInt32(fieldOffset, false);
|
|
64
|
+
},
|
|
65
|
+
set (value) {
|
|
66
|
+
structDataView(this).setInt32(fieldOffset, value, false);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Field for a big-endian 64-bit signed integer
|
|
72
|
+
*/ export function i64be(fieldOffset) {
|
|
73
|
+
return {
|
|
74
|
+
enumerable: true,
|
|
75
|
+
get () {
|
|
76
|
+
return structDataView(this).getBigInt64(fieldOffset, false);
|
|
77
|
+
},
|
|
78
|
+
set (value) {
|
|
79
|
+
structDataView(this).setBigInt64(fieldOffset, value, false);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Field for a big-endian 16-bit binary float (float16_t)
|
|
85
|
+
*/ export function f16be(fieldOffset) {
|
|
86
|
+
return {
|
|
87
|
+
enumerable: true,
|
|
88
|
+
get () {
|
|
89
|
+
return structDataView(this).getFloat16(fieldOffset, false);
|
|
90
|
+
},
|
|
91
|
+
set (value) {
|
|
92
|
+
structDataView(this).setFloat16(fieldOffset, value, false);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Field for a big-endian 32-bit binary float (float32_t)
|
|
98
|
+
*/ export function f32be(fieldOffset) {
|
|
99
|
+
return {
|
|
100
|
+
enumerable: true,
|
|
101
|
+
get () {
|
|
102
|
+
return structDataView(this).getFloat32(fieldOffset, false);
|
|
103
|
+
},
|
|
104
|
+
set (value) {
|
|
105
|
+
structDataView(this).setFloat32(fieldOffset, value, false);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Field for a big-endian 64-bit binary float (float64_t)
|
|
111
|
+
*/ export function f64be(fieldOffset) {
|
|
112
|
+
return {
|
|
113
|
+
enumerable: true,
|
|
114
|
+
get () {
|
|
115
|
+
return structDataView(this).getFloat64(fieldOffset, false);
|
|
116
|
+
},
|
|
117
|
+
set (value) {
|
|
118
|
+
structDataView(this).setFloat64(fieldOffset, value, false);
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=bigendian.js.map
|
package/bigendian.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bigendian.js","sources":["./bigendian.ts"],"names":[],"mappings":"AAAA;;;CAGC,GAED,SAAS,cAAc,mBAAiD;AAExE;;CAEC,GACD,OAAO,SAAS,MAAM,WAAmB;EACvC,OAAO;IACL,YAAY;IACZ;MACE,OAAO,eAAe,IAAI,EAAE,SAAS,CAAC,aAAa;IACrD;IACA,KAAI,KAAK;MACP,eAAe,IAAI,EAAE,SAAS,CAAC,aAAa,OAAO;IACrD;EACF;AACF;AACA;;CAEC,GACD,OAAO,SAAS,MAAM,WAAmB;EACvC,OAAO;IACL,YAAY;IACZ;MACE,OAAO,eAAe,IAAI,EAAE,SAAS,CAAC,aAAa;IACrD;IACA,KAAI,KAAK;MACP,eAAe,IAAI,EAAE,SAAS,CAAC,aAAa,OAAO;IACrD;EACF;AACF;AACA;;CAEC,GACD,OAAO,SAAS,MAAM,WAAmB;EACvC,OAAO;IACL,YAAY;IACZ;MACE,OAAO,eAAe,IAAI,EAAE,YAAY,CAAC,aAAa;IACxD;IACA,KAAI,KAAK;MACP,eAAe,IAAI,EAAE,YAAY,CAAC,aAAa,OAAO;IACxD;EACF;AACF;AACA;;CAEC,GACD,OAAO,SAAS,MAAM,WAAmB;EACvC,OAAO;IACL,YAAY;IACZ;MACE,OAAO,eAAe,IAAI,EAAE,QAAQ,CAAC,aAAa;IACpD;IACA,KAAI,KAAK;MACP,eAAe,IAAI,EAAE,QAAQ,CAAC,aAAa,OAAO;IACpD;EACF;AACF;AACA;;CAEC,GACD,OAAO,SAAS,MAAM,WAAmB;EACvC,OAAO;IACL,YAAY;IACZ;MACE,OAAO,eAAe,IAAI,EAAE,QAAQ,CAAC,aAAa;IACpD;IACA,KAAI,KAAK;MACP,eAAe,IAAI,EAAE,QAAQ,CAAC,aAAa,OAAO;IACpD;EACF;AACF;AACA;;CAEC,GACD,OAAO,SAAS,MAAM,WAAmB;EACvC,OAAO;IACL,YAAY;IACZ;MACE,OAAO,eAAe,IAAI,EAAE,WAAW,CAAC,aAAa;IACvD;IACA,KAAI,KAAK;MACP,eAAe,IAAI,EAAE,WAAW,CAAC,aAAa,OAAO;IACvD;EACF;AACF;AAEA;;CAEC,GACD,OAAO,SAAS,MAAM,WAAmB;EACvC,OAAO;IACL,YAAY;IACZ;MACE,OAAO,eAAe,IAAI,EAAE,UAAU,CAAC,aAAa;IACtD;IACA,KAAI,KAAK;MACP,eAAe,IAAI,EAAE,UAAU,CAAC,aAAa,OAAO;IACtD;EACF;AACF;AAEA;;CAEC,GACD,OAAO,SAAS,MAAM,WAAmB;EACvC,OAAO;IACL,YAAY;IACZ;MACE,OAAO,eAAe,IAAI,EAAE,UAAU,CAAC,aAAa;IACtD;IACA,KAAI,KAAK;MACP,eAAe,IAAI,EAAE,UAAU,CAAC,aAAa,OAAO;IACtD;EACF;AACF;AAEA;;CAEC,GACD,OAAO,SAAS,MAAM,WAAmB;EACvC,OAAO;IACL,YAAY;IACZ;MACE,OAAO,eAAe,IAAI,EAAE,UAAU,CAAC,aAAa;IACtD;IACA,KAAI,KAAK;MACP,eAAe,IAAI,EAAE,UAAU,CAAC,aAAa,OAAO;IACtD;EACF;AACF"}
|
package/bigendian.ts
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Property descriptor factories for big-endian numbers
|
|
3
|
+
* @module
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { structDataView, type StructPropertyDescriptor } from "./mod.js"
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Field for a big-endian 16-bit unsigned integer
|
|
10
|
+
*/
|
|
11
|
+
export function u16be(fieldOffset: number): StructPropertyDescriptor<number> {
|
|
12
|
+
return {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get() {
|
|
15
|
+
return structDataView(this).getUint16(fieldOffset, false)
|
|
16
|
+
},
|
|
17
|
+
set(value) {
|
|
18
|
+
structDataView(this).setUint16(fieldOffset, value, false)
|
|
19
|
+
},
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Field for a big-endian 32-bit unsigned integer
|
|
24
|
+
*/
|
|
25
|
+
export function u32be(fieldOffset: number): StructPropertyDescriptor<number> {
|
|
26
|
+
return {
|
|
27
|
+
enumerable: true,
|
|
28
|
+
get() {
|
|
29
|
+
return structDataView(this).getUint32(fieldOffset, false)
|
|
30
|
+
},
|
|
31
|
+
set(value) {
|
|
32
|
+
structDataView(this).setUint32(fieldOffset, value, false)
|
|
33
|
+
},
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Field for a big-endian 64-bit unsigned integer
|
|
38
|
+
*/
|
|
39
|
+
export function u64be(fieldOffset: number): StructPropertyDescriptor<bigint> {
|
|
40
|
+
return {
|
|
41
|
+
enumerable: true,
|
|
42
|
+
get() {
|
|
43
|
+
return structDataView(this).getBigUint64(fieldOffset, false)
|
|
44
|
+
},
|
|
45
|
+
set(value) {
|
|
46
|
+
structDataView(this).setBigUint64(fieldOffset, value, false)
|
|
47
|
+
},
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Field for a big-endian 16-bit signed integer
|
|
52
|
+
*/
|
|
53
|
+
export function i16be(fieldOffset: number): StructPropertyDescriptor<number> {
|
|
54
|
+
return {
|
|
55
|
+
enumerable: true,
|
|
56
|
+
get() {
|
|
57
|
+
return structDataView(this).getInt16(fieldOffset, false)
|
|
58
|
+
},
|
|
59
|
+
set(value) {
|
|
60
|
+
structDataView(this).setInt16(fieldOffset, value, false)
|
|
61
|
+
},
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Field for a big-endian 32-bit signed integer
|
|
66
|
+
*/
|
|
67
|
+
export function i32be(fieldOffset: number): StructPropertyDescriptor<number> {
|
|
68
|
+
return {
|
|
69
|
+
enumerable: true,
|
|
70
|
+
get() {
|
|
71
|
+
return structDataView(this).getInt32(fieldOffset, false)
|
|
72
|
+
},
|
|
73
|
+
set(value) {
|
|
74
|
+
structDataView(this).setInt32(fieldOffset, value, false)
|
|
75
|
+
},
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Field for a big-endian 64-bit signed integer
|
|
80
|
+
*/
|
|
81
|
+
export function i64be(fieldOffset: number): StructPropertyDescriptor<bigint> {
|
|
82
|
+
return {
|
|
83
|
+
enumerable: true,
|
|
84
|
+
get() {
|
|
85
|
+
return structDataView(this).getBigInt64(fieldOffset, false)
|
|
86
|
+
},
|
|
87
|
+
set(value) {
|
|
88
|
+
structDataView(this).setBigInt64(fieldOffset, value, false)
|
|
89
|
+
},
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Field for a big-endian 16-bit binary float (float16_t)
|
|
95
|
+
*/
|
|
96
|
+
export function f16be(fieldOffset: number): StructPropertyDescriptor<number> {
|
|
97
|
+
return {
|
|
98
|
+
enumerable: true,
|
|
99
|
+
get() {
|
|
100
|
+
return structDataView(this).getFloat16(fieldOffset, false)
|
|
101
|
+
},
|
|
102
|
+
set(value) {
|
|
103
|
+
structDataView(this).setFloat16(fieldOffset, value, false)
|
|
104
|
+
},
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Field for a big-endian 32-bit binary float (float32_t)
|
|
110
|
+
*/
|
|
111
|
+
export function f32be(fieldOffset: number): StructPropertyDescriptor<number> {
|
|
112
|
+
return {
|
|
113
|
+
enumerable: true,
|
|
114
|
+
get() {
|
|
115
|
+
return structDataView(this).getFloat32(fieldOffset, false)
|
|
116
|
+
},
|
|
117
|
+
set(value) {
|
|
118
|
+
structDataView(this).setFloat32(fieldOffset, value, false)
|
|
119
|
+
},
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Field for a big-endian 64-bit binary float (float64_t)
|
|
125
|
+
*/
|
|
126
|
+
export function f64be(fieldOffset: number): StructPropertyDescriptor<number> {
|
|
127
|
+
return {
|
|
128
|
+
enumerable: true,
|
|
129
|
+
get() {
|
|
130
|
+
return structDataView(this).getFloat64(fieldOffset, false)
|
|
131
|
+
},
|
|
132
|
+
set(value) {
|
|
133
|
+
structDataView(this).setFloat64(fieldOffset, value, false)
|
|
134
|
+
},
|
|
135
|
+
}
|
|
136
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import {
|
|
2
|
+
f16be,
|
|
3
|
+
f32be,
|
|
4
|
+
f64be,
|
|
5
|
+
i16be,
|
|
6
|
+
i32be,
|
|
7
|
+
i64be,
|
|
8
|
+
u16be,
|
|
9
|
+
u32be,
|
|
10
|
+
u64be,
|
|
11
|
+
} from "./bigendian.ts"
|
|
12
|
+
import { defineStruct, i16, i32, i64, u16, u32, u64 } from "./mod.ts"
|
|
13
|
+
|
|
14
|
+
import { assertEquals } from "jsr:@std/assert@1"
|
|
15
|
+
|
|
16
|
+
Deno.test("integers", () => {
|
|
17
|
+
const buf = new Uint8Array(16)
|
|
18
|
+
const Integers = defineStruct({
|
|
19
|
+
as_i16: i16(1),
|
|
20
|
+
as_i32: i32(1),
|
|
21
|
+
as_i64: i64(1),
|
|
22
|
+
as_u16: u16(1),
|
|
23
|
+
as_u32: u32(1),
|
|
24
|
+
as_u64: u64(1),
|
|
25
|
+
|
|
26
|
+
as_i16be: i16be(1),
|
|
27
|
+
as_i32be: i32be(1),
|
|
28
|
+
as_i64be: i64be(1),
|
|
29
|
+
as_u16be: u16be(1),
|
|
30
|
+
as_u32be: u32be(1),
|
|
31
|
+
as_u64be: u64be(1),
|
|
32
|
+
})
|
|
33
|
+
const b = new Integers(buf)
|
|
34
|
+
b.as_i16be = 0x0102
|
|
35
|
+
assertEquals(b.as_i16be, 0x0102)
|
|
36
|
+
assertEquals(b.as_i16, 0x0201)
|
|
37
|
+
assertEquals(b.as_u16be, 0x0102)
|
|
38
|
+
assertEquals(b.as_u16, 0x0201)
|
|
39
|
+
|
|
40
|
+
b.as_i32be = 0x01020304
|
|
41
|
+
assertEquals(b.as_i32be, 0x01020304)
|
|
42
|
+
assertEquals(b.as_i32, 0x04030201)
|
|
43
|
+
assertEquals(b.as_u32be, 0x01020304)
|
|
44
|
+
assertEquals(b.as_u32, 0x04030201)
|
|
45
|
+
|
|
46
|
+
b.as_i64be = 0x0102030405060708n
|
|
47
|
+
assertEquals(b.as_i64be, 0x0102030405060708n)
|
|
48
|
+
assertEquals(b.as_i64, 0x0807060504030201n)
|
|
49
|
+
assertEquals(b.as_u64be, 0x0102030405060708n)
|
|
50
|
+
assertEquals(b.as_u64, 0x0807060504030201n)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
Deno.test("floats", () => {
|
|
54
|
+
const Floats = defineStruct({
|
|
55
|
+
f16: f16be(0),
|
|
56
|
+
f32: f32be(4),
|
|
57
|
+
f64: f64be(8),
|
|
58
|
+
})
|
|
59
|
+
const bytes = new Uint8Array(16)
|
|
60
|
+
const v = new Floats(bytes)
|
|
61
|
+
assertEquals(v.f16, 0)
|
|
62
|
+
assertEquals(v.f32, 0)
|
|
63
|
+
assertEquals(v.f64, 0)
|
|
64
|
+
v.f16 = 1 / 3
|
|
65
|
+
v.f32 = 1 / 3
|
|
66
|
+
v.f64 = 1 / 3
|
|
67
|
+
assertEquals(v.f16, Math.f16round(1 / 3))
|
|
68
|
+
assertEquals(v.f32, Math.fround(1 / 3))
|
|
69
|
+
assertEquals(v.f64, 1 / 3)
|
|
70
|
+
})
|
package/deno.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rotu/structview",
|
|
3
|
+
"version": "0.6.1",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"tasks": {
|
|
6
|
+
"dev": "deno test --watch"
|
|
7
|
+
},
|
|
8
|
+
"fmt": {
|
|
9
|
+
"semiColons": false
|
|
10
|
+
},
|
|
11
|
+
"imports": {
|
|
12
|
+
"@std/assert": "jsr:@std/assert@1"
|
|
13
|
+
},
|
|
14
|
+
"exports": {
|
|
15
|
+
".": "./mod.ts",
|
|
16
|
+
"./bigendian": "./bigendian.ts"
|
|
17
|
+
}
|
|
18
|
+
}
|