@project-chip/matter.js 0.0.0 → 0.0.2
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/README.md +11 -0
- package/dist/matter.d.ts +22 -0
- package/dist/matter.js +22 -0
- package/dist/schema/BitmapSchema.d.ts +42 -16
- package/dist/schema/BitmapSchema.js +32 -12
- package/dist/schema/Schema.d.ts +10 -1
- package/dist/schema/Schema.js +11 -6
- package/dist/spec/Specifications.d.ts +14 -0
- package/dist/spec/Specifications.js +6 -0
- package/dist/tlv/TlvAny.d.ts +13 -0
- package/dist/tlv/TlvAny.js +67 -0
- package/dist/tlv/TlvArray.d.ts +29 -0
- package/dist/tlv/TlvArray.js +47 -0
- package/dist/tlv/TlvBoolean.d.ts +18 -0
- package/dist/tlv/TlvBoolean.js +23 -0
- package/dist/tlv/TlvCodec.d.ts +98 -0
- package/dist/tlv/TlvCodec.js +244 -0
- package/dist/tlv/TlvNullable.d.ts +20 -0
- package/dist/tlv/TlvNullable.js +32 -0
- package/dist/tlv/TlvNumber.d.ts +46 -0
- package/dist/tlv/TlvNumber.js +76 -0
- package/dist/tlv/TlvObject.d.ts +56 -0
- package/dist/tlv/TlvObject.js +73 -0
- package/dist/tlv/TlvSchema.d.ts +67 -0
- package/dist/tlv/TlvSchema.js +84 -0
- package/dist/tlv/TlvString.d.ts +38 -0
- package/dist/tlv/TlvString.js +52 -0
- package/dist/tlv/TlvVoid.d.ts +17 -0
- package/dist/tlv/TlvVoid.js +22 -0
- package/dist/tlv/TlvWrapper.d.ts +16 -0
- package/dist/tlv/TlvWrapper.js +23 -0
- package/dist/util/ByteArray.d.ts +30 -0
- package/dist/util/ByteArray.js +45 -0
- package/dist/util/DataReader.d.ts +29 -0
- package/dist/util/DataReader.js +65 -0
- package/dist/util/DataWriter.d.ts +26 -0
- package/dist/util/DataWriter.js +98 -0
- package/dist/util/Number.d.ts +23 -0
- package/dist/util/Number.js +39 -0
- package/dist/util/Type.d.ts +9 -0
- package/dist/util/Type.js +6 -0
- package/dist-cjs/matter.js +38 -0
- package/dist-cjs/schema/BitmapSchema.js +55 -0
- package/dist-cjs/schema/Schema.js +26 -0
- package/dist-cjs/spec/Specifications.js +7 -0
- package/dist-cjs/tlv/TlvAny.js +71 -0
- package/dist-cjs/tlv/TlvArray.js +52 -0
- package/dist-cjs/tlv/TlvBoolean.js +27 -0
- package/dist-cjs/tlv/TlvCodec.js +248 -0
- package/dist-cjs/tlv/TlvNullable.js +37 -0
- package/dist-cjs/tlv/TlvNumber.js +83 -0
- package/dist-cjs/tlv/TlvObject.js +81 -0
- package/dist-cjs/tlv/TlvSchema.js +92 -0
- package/dist-cjs/tlv/TlvString.js +56 -0
- package/dist-cjs/tlv/TlvVoid.js +26 -0
- package/dist-cjs/tlv/TlvWrapper.js +27 -0
- package/dist-cjs/util/ByteArray.js +48 -0
- package/dist-cjs/util/DataReader.js +69 -0
- package/dist-cjs/util/DataWriter.js +102 -0
- package/dist-cjs/util/Number.js +46 -0
- package/dist-cjs/util/Type.js +7 -0
- package/package.json +19 -13
- package/dist/index.d.ts +0 -0
- package/dist/index.js +0 -1
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022 Project CHIP Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { INT16_MAX, INT16_MIN, INT32_MAX, INT32_MIN, INT8_MAX, INT8_MIN, UINT16_MAX, UINT32_MAX, UINT8_MAX } from "../util/Number.js";
|
|
7
|
+
import { BitmapSchema, BitFieldEnum, BitField } from "../schema/BitmapSchema.js";
|
|
8
|
+
/**
|
|
9
|
+
* Schema of the ControlByte.
|
|
10
|
+
*
|
|
11
|
+
* @see {@link MatterCoreSpecificationV1_0} § A.7.2
|
|
12
|
+
*/
|
|
13
|
+
const ControlByteSchema = BitmapSchema({
|
|
14
|
+
typeLength: BitField(0, 5),
|
|
15
|
+
tagControl: BitFieldEnum(5, 3),
|
|
16
|
+
});
|
|
17
|
+
/** {@link MatterCoreSpecificationV1_0} § 2.5.2 and § A.8.3 */
|
|
18
|
+
const MATTER_COMMON_PROFILE = 0x00000000;
|
|
19
|
+
export class TlvCodec {
|
|
20
|
+
static getUIntTlvLength(value) {
|
|
21
|
+
if (value <= UINT8_MAX) {
|
|
22
|
+
return 0 /* TlvLength.OneByte */;
|
|
23
|
+
}
|
|
24
|
+
else if (value <= UINT16_MAX) {
|
|
25
|
+
return 1 /* TlvLength.TwoBytes */;
|
|
26
|
+
}
|
|
27
|
+
else if (value <= UINT32_MAX) {
|
|
28
|
+
return 2 /* TlvLength.FourBytes */;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
return 3 /* TlvLength.EightBytes */;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
static getIntTlvLength(value) {
|
|
35
|
+
if (value > 0) {
|
|
36
|
+
if (value <= INT8_MAX) {
|
|
37
|
+
return 0 /* TlvLength.OneByte */;
|
|
38
|
+
}
|
|
39
|
+
else if (value <= INT16_MAX) {
|
|
40
|
+
return 1 /* TlvLength.TwoBytes */;
|
|
41
|
+
}
|
|
42
|
+
else if (value <= INT32_MAX) {
|
|
43
|
+
return 2 /* TlvLength.FourBytes */;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
return 3 /* TlvLength.EightBytes */;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
if (value >= INT8_MIN) {
|
|
51
|
+
return 0 /* TlvLength.OneByte */;
|
|
52
|
+
}
|
|
53
|
+
else if (value >= INT16_MIN) {
|
|
54
|
+
return 1 /* TlvLength.TwoBytes */;
|
|
55
|
+
}
|
|
56
|
+
else if (value >= INT32_MIN) {
|
|
57
|
+
return 2 /* TlvLength.FourBytes */;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
return 3 /* TlvLength.EightBytes */;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/** @see {@link MatterCoreSpecificationV1_0} § A.7 */
|
|
65
|
+
static readTagType(reader) {
|
|
66
|
+
const { tagControl, typeLength } = ControlByteSchema.decode(reader.readUInt8());
|
|
67
|
+
return { tag: this.readTag(reader, tagControl), typeLength: this.parseTypeLength(typeLength) };
|
|
68
|
+
}
|
|
69
|
+
static readTag(reader, tagControl) {
|
|
70
|
+
switch (tagControl) {
|
|
71
|
+
case 0 /* TagControl.Anonymous */:
|
|
72
|
+
return undefined;
|
|
73
|
+
case 1 /* TagControl.ContextSpecific */:
|
|
74
|
+
return { id: reader.readUInt8() };
|
|
75
|
+
case 2 /* TagControl.CommonProfile16 */:
|
|
76
|
+
return { profile: MATTER_COMMON_PROFILE, id: reader.readUInt16() };
|
|
77
|
+
case 3 /* TagControl.CommonProfile32 */:
|
|
78
|
+
return { profile: MATTER_COMMON_PROFILE, id: reader.readUInt32() };
|
|
79
|
+
case 4 /* TagControl.ImplicitProfile16 */:
|
|
80
|
+
case 5 /* TagControl.ImplicitProfile32 */:
|
|
81
|
+
throw new Error(`Unsupported implicit profile ${tagControl}`);
|
|
82
|
+
case 6 /* TagControl.FullyQualified48 */:
|
|
83
|
+
return { profile: reader.readUInt32(), id: reader.readUInt16() };
|
|
84
|
+
case 6 /* TagControl.FullyQualified48 */:
|
|
85
|
+
return { profile: reader.readUInt32(), id: reader.readUInt32() };
|
|
86
|
+
default:
|
|
87
|
+
throw new Error(`Unexpected tagControl ${tagControl}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
static parseTypeLength(typeLength) {
|
|
91
|
+
const length = (typeLength & 0x03);
|
|
92
|
+
const type = typeLength & 0xFC;
|
|
93
|
+
switch (type) {
|
|
94
|
+
case 12 /* TlvType.Utf8String */:
|
|
95
|
+
case 16 /* TlvType.ByteString */:
|
|
96
|
+
case 0 /* TlvType.SignedInt */:
|
|
97
|
+
case 4 /* TlvType.UnsignedInt */:
|
|
98
|
+
return { type, length };
|
|
99
|
+
case 8 /* TlvType.Boolean */:
|
|
100
|
+
switch (length) {
|
|
101
|
+
case 0 /* TlvLength.OneByte */: return { type, value: false };
|
|
102
|
+
case 1 /* TlvLength.TwoBytes */: return { type, value: true };
|
|
103
|
+
case 2 /* TlvLength.FourBytes */: return { type: 10 /* TlvType.Float */, length };
|
|
104
|
+
case 3 /* TlvLength.EightBytes */: return { type: 10 /* TlvType.Float */, length };
|
|
105
|
+
}
|
|
106
|
+
default:
|
|
107
|
+
return { type: typeLength };
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
static readPrimitive(reader, typeLength) {
|
|
111
|
+
switch (typeLength.type) {
|
|
112
|
+
case 0 /* TlvType.SignedInt */:
|
|
113
|
+
switch (typeLength.length) {
|
|
114
|
+
case 0 /* TlvLength.OneByte */: return reader.readInt8();
|
|
115
|
+
case 1 /* TlvLength.TwoBytes */: return reader.readInt16();
|
|
116
|
+
case 2 /* TlvLength.FourBytes */: return reader.readInt32();
|
|
117
|
+
case 3 /* TlvLength.EightBytes */: return reader.readInt64();
|
|
118
|
+
}
|
|
119
|
+
case 4 /* TlvType.UnsignedInt */:
|
|
120
|
+
switch (typeLength.length) {
|
|
121
|
+
case 0 /* TlvLength.OneByte */: return reader.readUInt8();
|
|
122
|
+
case 1 /* TlvLength.TwoBytes */: return reader.readUInt16();
|
|
123
|
+
case 2 /* TlvLength.FourBytes */: return reader.readUInt32();
|
|
124
|
+
case 3 /* TlvLength.EightBytes */: return reader.readUInt64();
|
|
125
|
+
}
|
|
126
|
+
case 10 /* TlvType.Float */:
|
|
127
|
+
switch (typeLength.length) {
|
|
128
|
+
case 2 /* TlvLength.FourBytes */: return reader.readFloat();
|
|
129
|
+
case 3 /* TlvLength.EightBytes */: return reader.readDouble();
|
|
130
|
+
}
|
|
131
|
+
case 12 /* TlvType.Utf8String */:
|
|
132
|
+
switch (typeLength.length) {
|
|
133
|
+
case 0 /* TlvLength.OneByte */: return reader.readUtf8String(reader.readUInt8());
|
|
134
|
+
case 1 /* TlvLength.TwoBytes */: return reader.readUtf8String(reader.readUInt16());
|
|
135
|
+
case 2 /* TlvLength.FourBytes */: return reader.readUtf8String(reader.readUInt32());
|
|
136
|
+
case 3 /* TlvLength.EightBytes */: return reader.readUtf8String(Number(reader.readUInt64()));
|
|
137
|
+
}
|
|
138
|
+
case 16 /* TlvType.ByteString */:
|
|
139
|
+
switch (typeLength.length) {
|
|
140
|
+
case 0 /* TlvLength.OneByte */: return reader.readByteArray(reader.readUInt8());
|
|
141
|
+
case 1 /* TlvLength.TwoBytes */: return reader.readByteArray(reader.readUInt16());
|
|
142
|
+
case 2 /* TlvLength.FourBytes */: return reader.readByteArray(reader.readUInt32());
|
|
143
|
+
case 3 /* TlvLength.EightBytes */: return reader.readByteArray(Number(reader.readUInt64()));
|
|
144
|
+
}
|
|
145
|
+
case 8 /* TlvType.Boolean */:
|
|
146
|
+
return typeLength.value;
|
|
147
|
+
case 20 /* TlvType.Null */:
|
|
148
|
+
return null;
|
|
149
|
+
default:
|
|
150
|
+
throw new Error(`Unexpected TLV type ${typeLength.type}`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/** @see {@link MatterCoreSpecificationV1_0} § A.7 & A.8 */
|
|
154
|
+
static writeTag(writer, typeLengthValue, { profile, id } = {}) {
|
|
155
|
+
let typeLength;
|
|
156
|
+
switch (typeLengthValue.type) {
|
|
157
|
+
case 12 /* TlvType.Utf8String */:
|
|
158
|
+
case 16 /* TlvType.ByteString */:
|
|
159
|
+
case 0 /* TlvType.SignedInt */:
|
|
160
|
+
case 4 /* TlvType.UnsignedInt */:
|
|
161
|
+
case 10 /* TlvType.Float */:
|
|
162
|
+
typeLength = typeLengthValue.type | typeLengthValue.length;
|
|
163
|
+
break;
|
|
164
|
+
case 8 /* TlvType.Boolean */:
|
|
165
|
+
typeLength = typeLengthValue.type + (typeLengthValue.value ? 1 : 0);
|
|
166
|
+
break;
|
|
167
|
+
default:
|
|
168
|
+
typeLength = typeLengthValue.type;
|
|
169
|
+
}
|
|
170
|
+
if (profile === undefined && id === undefined) {
|
|
171
|
+
writer.writeUInt8(ControlByteSchema.encode({ tagControl: 0 /* TagControl.Anonymous */, typeLength }));
|
|
172
|
+
}
|
|
173
|
+
else if (profile === undefined) {
|
|
174
|
+
if (id === undefined)
|
|
175
|
+
throw new Error("Invalid TLV tag: id should be defined for a context specific tag.");
|
|
176
|
+
writer.writeUInt8(ControlByteSchema.encode({ tagControl: 1 /* TagControl.ContextSpecific */, typeLength }));
|
|
177
|
+
writer.writeUInt8(id);
|
|
178
|
+
}
|
|
179
|
+
else if (profile === MATTER_COMMON_PROFILE) {
|
|
180
|
+
if (id === undefined)
|
|
181
|
+
throw new Error("Invalid TLV tag: id should be defined for a common profile.");
|
|
182
|
+
if ((id & 0xFFFF0000) === 0) {
|
|
183
|
+
writer.writeUInt8(ControlByteSchema.encode({ tagControl: 2 /* TagControl.CommonProfile16 */, typeLength }));
|
|
184
|
+
writer.writeUInt16(id);
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
writer.writeUInt8(ControlByteSchema.encode({ tagControl: 3 /* TagControl.CommonProfile32 */, typeLength }));
|
|
188
|
+
writer.writeUInt32(id);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
if (id === undefined)
|
|
193
|
+
throw new Error("Invalid TLV tag: id should be defined for a custom profile.");
|
|
194
|
+
if ((id & 0xFFFF0000) === 0) {
|
|
195
|
+
writer.writeUInt8(ControlByteSchema.encode({ tagControl: 6 /* TagControl.FullyQualified48 */, typeLength }));
|
|
196
|
+
writer.writeUInt32(profile);
|
|
197
|
+
writer.writeUInt16(id);
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
writer.writeUInt8(ControlByteSchema.encode({ tagControl: 7 /* TagControl.FullyQualified64 */, typeLength }));
|
|
201
|
+
writer.writeUInt32(profile);
|
|
202
|
+
writer.writeUInt32(id);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
static writePrimitive(writer, typeLength, value) {
|
|
207
|
+
switch (typeLength.type) {
|
|
208
|
+
case 0 /* TlvType.SignedInt */:
|
|
209
|
+
return this.writeUInt(writer, typeLength.length, value);
|
|
210
|
+
case 4 /* TlvType.UnsignedInt */:
|
|
211
|
+
switch (typeLength.length) {
|
|
212
|
+
case 0 /* TlvLength.OneByte */: return writer.writeUInt8(value);
|
|
213
|
+
case 1 /* TlvLength.TwoBytes */: return writer.writeUInt16(value);
|
|
214
|
+
case 2 /* TlvLength.FourBytes */: return writer.writeUInt32(value);
|
|
215
|
+
case 3 /* TlvLength.EightBytes */: return writer.writeUInt64(value);
|
|
216
|
+
}
|
|
217
|
+
case 10 /* TlvType.Float */:
|
|
218
|
+
switch (typeLength.length) {
|
|
219
|
+
case 2 /* TlvLength.FourBytes */: return writer.writeFloat(value);
|
|
220
|
+
case 3 /* TlvLength.EightBytes */: return writer.writeDouble(value);
|
|
221
|
+
}
|
|
222
|
+
case 12 /* TlvType.Utf8String */:
|
|
223
|
+
const string = value;
|
|
224
|
+
this.writeUInt(writer, typeLength.length, string.length);
|
|
225
|
+
return writer.writeUtf8String(string);
|
|
226
|
+
case 16 /* TlvType.ByteString */:
|
|
227
|
+
const byteArray = value;
|
|
228
|
+
this.writeUInt(writer, typeLength.length, byteArray.length);
|
|
229
|
+
return writer.writeByteArray(byteArray);
|
|
230
|
+
case 8 /* TlvType.Boolean */:
|
|
231
|
+
return;
|
|
232
|
+
default:
|
|
233
|
+
throw new Error(`Unexpected TLV type ${typeLength.type}`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
static writeUInt(writer, length, value) {
|
|
237
|
+
switch (length) {
|
|
238
|
+
case 0 /* TlvLength.OneByte */: return writer.writeInt8(value);
|
|
239
|
+
case 1 /* TlvLength.TwoBytes */: return writer.writeInt16(value);
|
|
240
|
+
case 2 /* TlvLength.FourBytes */: return writer.writeInt32(value);
|
|
241
|
+
case 3 /* TlvLength.EightBytes */: return writer.writeInt64(value);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022 Project CHIP Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { TlvTag, TlvTypeLength } from "./TlvCodec.js";
|
|
7
|
+
import { TlvReader, TlvSchema, TlvWriter } from "./TlvSchema.js";
|
|
8
|
+
/**
|
|
9
|
+
* Schema to encode a nulable value in TLV.
|
|
10
|
+
*
|
|
11
|
+
* @see {@link MatterCoreSpecificationV1_0} § A.11.6
|
|
12
|
+
*/
|
|
13
|
+
export declare class NullableSchema<T> extends TlvSchema<T | null> {
|
|
14
|
+
private readonly schema;
|
|
15
|
+
constructor(schema: TlvSchema<T>);
|
|
16
|
+
encodeTlvInternal(writer: TlvWriter, value: T | null, tag?: TlvTag): void;
|
|
17
|
+
decodeTlvInternalValue(reader: TlvReader, typeLength: TlvTypeLength): T | null;
|
|
18
|
+
}
|
|
19
|
+
/** Nullable TLV schema. */
|
|
20
|
+
export declare const TlvNullable: <T>(schema: TlvSchema<T>) => NullableSchema<T>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022 Project CHIP Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { TlvSchema } from "./TlvSchema.js";
|
|
7
|
+
/**
|
|
8
|
+
* Schema to encode a nulable value in TLV.
|
|
9
|
+
*
|
|
10
|
+
* @see {@link MatterCoreSpecificationV1_0} § A.11.6
|
|
11
|
+
*/
|
|
12
|
+
export class NullableSchema extends TlvSchema {
|
|
13
|
+
constructor(schema) {
|
|
14
|
+
super();
|
|
15
|
+
this.schema = schema;
|
|
16
|
+
}
|
|
17
|
+
encodeTlvInternal(writer, value, tag = {}) {
|
|
18
|
+
if (value === null) {
|
|
19
|
+
writer.writeTag({ type: 20 /* TlvType.Null */ }, tag);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
this.schema.encodeTlvInternal(writer, value, tag);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
decodeTlvInternalValue(reader, typeLength) {
|
|
26
|
+
if (typeLength.type === 20 /* TlvType.Null */)
|
|
27
|
+
return null;
|
|
28
|
+
return this.schema.decodeTlvInternalValue(reader, typeLength);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/** Nullable TLV schema. */
|
|
32
|
+
export const TlvNullable = (schema) => new NullableSchema(schema);
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { TlvType, TlvTag, TlvTypeLength, TlvLength } from "./TlvCodec.js";
|
|
2
|
+
import { TlvReader, TlvSchema, TlvWriter } from "./TlvSchema.js";
|
|
3
|
+
import { TlvWrapper } from "./TlvWrapper.js";
|
|
4
|
+
import { BitSchema, TypeFromBitSchema } from "../schema/BitmapSchema.js";
|
|
5
|
+
/**
|
|
6
|
+
* Schema to encode an unsigned integer in TLV.
|
|
7
|
+
*
|
|
8
|
+
* @see {@link MatterCoreSpecificationV1_0} § A.11.1
|
|
9
|
+
*/
|
|
10
|
+
export declare class TlvNumericSchema<T extends bigint | number> extends TlvSchema<T> {
|
|
11
|
+
protected readonly type: TlvType.UnsignedInt | TlvType.SignedInt | TlvType.Float;
|
|
12
|
+
protected readonly lengthProvider: (value: T) => TlvLength;
|
|
13
|
+
protected readonly min?: T | undefined;
|
|
14
|
+
protected readonly max?: T | undefined;
|
|
15
|
+
constructor(type: TlvType.UnsignedInt | TlvType.SignedInt | TlvType.Float, lengthProvider: (value: T) => TlvLength, min?: T | undefined, max?: T | undefined);
|
|
16
|
+
encodeTlvInternal(writer: TlvWriter, value: T, tag?: TlvTag): void;
|
|
17
|
+
decodeTlvInternalValue(reader: TlvReader, typeLength: TlvTypeLength): T;
|
|
18
|
+
validate(value: T): void;
|
|
19
|
+
/** Restrict value range. */
|
|
20
|
+
bound({ min, max }: NumericConstraints<T>): TlvNumericSchema<T>;
|
|
21
|
+
}
|
|
22
|
+
export type NumericConstraints<T extends number | bigint = number | bigint> = {
|
|
23
|
+
min?: T;
|
|
24
|
+
max?: T;
|
|
25
|
+
};
|
|
26
|
+
export declare class TlvNumberSchema extends TlvNumericSchema<number> {
|
|
27
|
+
constructor(type: TlvType.UnsignedInt | TlvType.SignedInt | TlvType.Float, lengthProvider: (value: number) => TlvLength, min?: number, max?: number);
|
|
28
|
+
decodeTlvInternalValue(reader: TlvReader, typeLength: TlvTypeLength): number;
|
|
29
|
+
bound({ min, max }: NumericConstraints<number>): TlvNumericSchema<number>;
|
|
30
|
+
}
|
|
31
|
+
export declare const TlvLongNumberSchema: {
|
|
32
|
+
new (type: TlvType.UnsignedInt | TlvType.SignedInt | TlvType.Float, lengthProvider: (value: number | bigint) => TlvLength, min?: number | bigint | undefined, max?: number | bigint | undefined): TlvNumericSchema<number | bigint>;
|
|
33
|
+
};
|
|
34
|
+
/** Unsigned integer TLV schema. */
|
|
35
|
+
export declare const TlvFloat: TlvNumberSchema;
|
|
36
|
+
export declare const TlvDouble: TlvNumberSchema;
|
|
37
|
+
export declare const TlvInt8: TlvNumberSchema;
|
|
38
|
+
export declare const TlvInt16: TlvNumberSchema;
|
|
39
|
+
export declare const TlvInt32: TlvNumberSchema;
|
|
40
|
+
export declare const TlvInt64: TlvNumericSchema<number | bigint>;
|
|
41
|
+
export declare const TlvUInt8: TlvNumberSchema;
|
|
42
|
+
export declare const TlvUInt16: TlvNumberSchema;
|
|
43
|
+
export declare const TlvUInt32: TlvNumberSchema;
|
|
44
|
+
export declare const TlvUInt64: TlvNumericSchema<number | bigint>;
|
|
45
|
+
export declare const TlvEnum: <T>() => TlvSchema<T>;
|
|
46
|
+
export declare const TlvBitmap: <T extends BitSchema>(underlyingSchema: TlvNumberSchema, bitSchema: T) => TlvWrapper<TypeFromBitSchema<T>, number>;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022 Project CHIP Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { FLOAT32_MAX, FLOAT32_MIN, INT16_MAX, INT16_MIN, INT32_MAX, INT32_MIN, INT64_MAX, INT64_MIN, INT8_MAX, INT8_MIN, maxValue, minValue, UINT16_MAX, UINT32_MAX, UINT64_MAX, UINT8_MAX } from "../util/Number.js";
|
|
7
|
+
import { TlvCodec } from "./TlvCodec.js";
|
|
8
|
+
import { TlvSchema } from "./TlvSchema.js";
|
|
9
|
+
import { TlvWrapper } from "./TlvWrapper.js";
|
|
10
|
+
import { BitmapSchema } from "../schema/BitmapSchema.js";
|
|
11
|
+
/**
|
|
12
|
+
* Schema to encode an unsigned integer in TLV.
|
|
13
|
+
*
|
|
14
|
+
* @see {@link MatterCoreSpecificationV1_0} § A.11.1
|
|
15
|
+
*/
|
|
16
|
+
export class TlvNumericSchema extends TlvSchema {
|
|
17
|
+
constructor(type, lengthProvider, min, max) {
|
|
18
|
+
super();
|
|
19
|
+
this.type = type;
|
|
20
|
+
this.lengthProvider = lengthProvider;
|
|
21
|
+
this.min = min;
|
|
22
|
+
this.max = max;
|
|
23
|
+
}
|
|
24
|
+
encodeTlvInternal(writer, value, tag = {}) {
|
|
25
|
+
const typeLength = { type: this.type, length: this.lengthProvider(value) };
|
|
26
|
+
writer.writeTag(typeLength, tag);
|
|
27
|
+
writer.writePrimitive(typeLength, value);
|
|
28
|
+
}
|
|
29
|
+
decodeTlvInternalValue(reader, typeLength) {
|
|
30
|
+
if (typeLength.type !== this.type)
|
|
31
|
+
throw new Error(`Unexpected type ${typeLength.type}, was expecting ${this.type}.`);
|
|
32
|
+
const value = reader.readPrimitive(typeLength);
|
|
33
|
+
this.validate(value);
|
|
34
|
+
return value;
|
|
35
|
+
}
|
|
36
|
+
validate(value) {
|
|
37
|
+
super.validate(value);
|
|
38
|
+
if (this.min !== undefined && value < this.min)
|
|
39
|
+
throw new Error(`Invalid value: ${value} is below the minimum, ${this.min}.`);
|
|
40
|
+
if (this.max !== undefined && value > this.max)
|
|
41
|
+
throw new Error(`Invalid value: ${value} is above the maximum, ${this.max}.`);
|
|
42
|
+
}
|
|
43
|
+
/** Restrict value range. */
|
|
44
|
+
bound({ min, max }) {
|
|
45
|
+
return new TlvNumericSchema(this.type, this.lengthProvider, maxValue(min, this.min), minValue(max, this.max));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export class TlvNumberSchema extends TlvNumericSchema {
|
|
49
|
+
constructor(type, lengthProvider, min, max) {
|
|
50
|
+
super(type, lengthProvider, min, max);
|
|
51
|
+
}
|
|
52
|
+
decodeTlvInternalValue(reader, typeLength) {
|
|
53
|
+
const value = super.decodeTlvInternalValue(reader, typeLength);
|
|
54
|
+
return typeof value === "bigint" ? Number(value) : value;
|
|
55
|
+
}
|
|
56
|
+
bound({ min, max }) {
|
|
57
|
+
return new TlvNumberSchema(this.type, this.lengthProvider, maxValue(min, this.min), minValue(max, this.max));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
export const TlvLongNumberSchema = (TlvNumericSchema);
|
|
61
|
+
/** Unsigned integer TLV schema. */
|
|
62
|
+
export const TlvFloat = new TlvNumberSchema(10 /* TlvType.Float */, _value => 2 /* TlvLength.FourBytes */, FLOAT32_MIN, FLOAT32_MAX);
|
|
63
|
+
export const TlvDouble = new TlvNumberSchema(10 /* TlvType.Float */, _value => 3 /* TlvLength.EightBytes */);
|
|
64
|
+
export const TlvInt8 = new TlvNumberSchema(0 /* TlvType.SignedInt */, value => TlvCodec.getIntTlvLength(value), INT8_MIN, INT8_MAX);
|
|
65
|
+
export const TlvInt16 = new TlvNumberSchema(0 /* TlvType.SignedInt */, value => TlvCodec.getIntTlvLength(value), INT16_MIN, INT16_MAX);
|
|
66
|
+
export const TlvInt32 = new TlvNumberSchema(0 /* TlvType.SignedInt */, value => TlvCodec.getIntTlvLength(value), INT32_MIN, INT32_MAX);
|
|
67
|
+
export const TlvInt64 = new TlvLongNumberSchema(0 /* TlvType.SignedInt */, value => TlvCodec.getIntTlvLength(value), INT64_MIN, INT64_MAX);
|
|
68
|
+
export const TlvUInt8 = new TlvNumberSchema(4 /* TlvType.UnsignedInt */, value => TlvCodec.getUIntTlvLength(value), 0, UINT8_MAX);
|
|
69
|
+
export const TlvUInt16 = new TlvNumberSchema(4 /* TlvType.UnsignedInt */, value => TlvCodec.getUIntTlvLength(value), 0, UINT16_MAX);
|
|
70
|
+
export const TlvUInt32 = new TlvNumberSchema(4 /* TlvType.UnsignedInt */, value => TlvCodec.getUIntTlvLength(value), 0, UINT32_MAX);
|
|
71
|
+
export const TlvUInt64 = new TlvLongNumberSchema(4 /* TlvType.UnsignedInt */, value => TlvCodec.getUIntTlvLength(value), 0, UINT64_MAX);
|
|
72
|
+
export const TlvEnum = () => TlvUInt32;
|
|
73
|
+
export const TlvBitmap = (underlyingSchema, bitSchema) => {
|
|
74
|
+
const bitmapSchema = BitmapSchema(bitSchema);
|
|
75
|
+
return new TlvWrapper(underlyingSchema, (bitmapData) => bitmapSchema.encode(bitmapData), value => bitmapSchema.decode(value));
|
|
76
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022 Project CHIP Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { Merge } from "../util/Type.js";
|
|
7
|
+
import { TlvType, TlvTag, TlvTypeLength } from "./TlvCodec.js";
|
|
8
|
+
import { TlvReader, TlvSchema, TlvWriter } from "./TlvSchema.js";
|
|
9
|
+
export interface FieldType<T> {
|
|
10
|
+
id: number;
|
|
11
|
+
schema: TlvSchema<T>;
|
|
12
|
+
optional?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface OptionalFieldType<T> extends FieldType<T> {
|
|
15
|
+
optional: true;
|
|
16
|
+
}
|
|
17
|
+
export type TlvFields = {
|
|
18
|
+
[field: string]: FieldType<any>;
|
|
19
|
+
};
|
|
20
|
+
type MandatoryFieldNames<F extends TlvFields> = {
|
|
21
|
+
[K in keyof F]: F[K] extends OptionalFieldType<any> ? never : K;
|
|
22
|
+
}[keyof F];
|
|
23
|
+
type OptionalFieldNames<F extends TlvFields> = {
|
|
24
|
+
[K in keyof F]: F[K] extends OptionalFieldType<any> ? K : never;
|
|
25
|
+
}[keyof F];
|
|
26
|
+
type TypeFromField<F extends FieldType<any>> = F extends FieldType<infer T> ? T : never;
|
|
27
|
+
type TypeForMandatoryFields<F extends TlvFields, MF extends keyof F> = {
|
|
28
|
+
[K in MF]: TypeFromField<F[K]>;
|
|
29
|
+
};
|
|
30
|
+
type TypeForOptionalFields<F extends TlvFields, MF extends keyof F> = {
|
|
31
|
+
[K in MF]?: TypeFromField<F[K]>;
|
|
32
|
+
};
|
|
33
|
+
export type TypeFromFields<F extends TlvFields> = Merge<TypeForMandatoryFields<F, MandatoryFieldNames<F>>, TypeForOptionalFields<F, OptionalFieldNames<F>>>;
|
|
34
|
+
/**
|
|
35
|
+
* Schema to encode an object in TLV.
|
|
36
|
+
*
|
|
37
|
+
* @see {@link MatterCoreSpecificationV1_0} § A.5.1 and § A.11.4
|
|
38
|
+
*/
|
|
39
|
+
export declare class ObjectSchema<F extends TlvFields> extends TlvSchema<TypeFromFields<F>> {
|
|
40
|
+
private readonly fieldDefinitions;
|
|
41
|
+
private readonly type;
|
|
42
|
+
private readonly fieldById;
|
|
43
|
+
constructor(fieldDefinitions: F, type?: TlvType.Structure | TlvType.List);
|
|
44
|
+
encodeTlvInternal(writer: TlvWriter, value: TypeFromFields<F>, tag?: TlvTag): void;
|
|
45
|
+
decodeTlvInternalValue(reader: TlvReader, typeLength: TlvTypeLength): TypeFromFields<F>;
|
|
46
|
+
validate(value: TypeFromFields<F>): void;
|
|
47
|
+
}
|
|
48
|
+
/** Object TLV schema. */
|
|
49
|
+
export declare const TlvObject: <F extends TlvFields>(fields: F) => ObjectSchema<F>;
|
|
50
|
+
/** List TLV schema. */
|
|
51
|
+
export declare const TlvList: <F extends TlvFields>(fields: F) => ObjectSchema<F>;
|
|
52
|
+
/** Object TLV mandatory field. */
|
|
53
|
+
export declare const TlvField: <T>(id: number, schema: TlvSchema<T>) => FieldType<T>;
|
|
54
|
+
/** Object TLV optional field. */
|
|
55
|
+
export declare const TlvOptionalField: <T>(id: number, schema: TlvSchema<T>) => OptionalFieldType<T>;
|
|
56
|
+
export {};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022 Project CHIP Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { TlvSchema } from "./TlvSchema.js";
|
|
7
|
+
;
|
|
8
|
+
/**
|
|
9
|
+
* Schema to encode an object in TLV.
|
|
10
|
+
*
|
|
11
|
+
* @see {@link MatterCoreSpecificationV1_0} § A.5.1 and § A.11.4
|
|
12
|
+
*/
|
|
13
|
+
export class ObjectSchema extends TlvSchema {
|
|
14
|
+
constructor(fieldDefinitions, type = 21 /* TlvType.Structure */) {
|
|
15
|
+
super();
|
|
16
|
+
this.fieldDefinitions = fieldDefinitions;
|
|
17
|
+
this.type = type;
|
|
18
|
+
this.fieldById = new Array();
|
|
19
|
+
for (const name in this.fieldDefinitions) {
|
|
20
|
+
const field = this.fieldDefinitions[name];
|
|
21
|
+
this.fieldById[field.id] = { name, field };
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
encodeTlvInternal(writer, value, tag = {}) {
|
|
25
|
+
writer.writeTag({ type: this.type }, tag);
|
|
26
|
+
for (const name in this.fieldDefinitions) {
|
|
27
|
+
const { id, schema, optional: isOptional } = this.fieldDefinitions[name];
|
|
28
|
+
const fieldValue = value[name];
|
|
29
|
+
if (fieldValue === undefined) {
|
|
30
|
+
if (!isOptional)
|
|
31
|
+
throw new Error(`Missing mandatory field ${name}`);
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
schema.encodeTlvInternal(writer, fieldValue, { id });
|
|
35
|
+
}
|
|
36
|
+
writer.writeTag({ type: 24 /* TlvType.EndOfContainer */ });
|
|
37
|
+
}
|
|
38
|
+
decodeTlvInternalValue(reader, typeLength) {
|
|
39
|
+
if (typeLength.type !== this.type)
|
|
40
|
+
throw new Error(`Unexpected type ${typeLength.type}.`);
|
|
41
|
+
const result = {};
|
|
42
|
+
while (true) {
|
|
43
|
+
const { tag: { profile, id } = {}, typeLength: elementTypeLength } = reader.readTagType();
|
|
44
|
+
if (elementTypeLength.type === 24 /* TlvType.EndOfContainer */)
|
|
45
|
+
break;
|
|
46
|
+
if (profile !== undefined)
|
|
47
|
+
throw new Error("Structure element tags should be context-specific.");
|
|
48
|
+
if (id === undefined)
|
|
49
|
+
throw new Error("Structure element tags should have an id.");
|
|
50
|
+
const fieldName = this.fieldById[id];
|
|
51
|
+
if (fieldName === undefined)
|
|
52
|
+
throw new Error(`Unknown field ${id}`);
|
|
53
|
+
const { field, name } = fieldName;
|
|
54
|
+
result[name] = field.schema.decodeTlvInternalValue(reader, elementTypeLength);
|
|
55
|
+
}
|
|
56
|
+
this.validate(result);
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
validate(value) {
|
|
60
|
+
for (const name in this.fieldDefinitions) {
|
|
61
|
+
if (!this.fieldDefinitions[name].optional && value[name] === undefined)
|
|
62
|
+
throw new Error(`Missing mandatory field ${name}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/** Object TLV schema. */
|
|
67
|
+
export const TlvObject = (fields) => new ObjectSchema(fields, 21 /* TlvType.Structure */);
|
|
68
|
+
/** List TLV schema. */
|
|
69
|
+
export const TlvList = (fields) => new ObjectSchema(fields, 23 /* TlvType.List */);
|
|
70
|
+
/** Object TLV mandatory field. */
|
|
71
|
+
export const TlvField = (id, schema) => ({ id, schema, optional: false });
|
|
72
|
+
/** Object TLV optional field. */
|
|
73
|
+
export const TlvOptionalField = (id, schema) => ({ id, schema, optional: true });
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022 Project CHIP Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { ByteArray } from "../util/ByteArray.js";
|
|
7
|
+
import { Schema } from "../schema/Schema.js";
|
|
8
|
+
import { TlvTag, TlvToPrimitive, TlvTypeLength } from "./TlvCodec.js";
|
|
9
|
+
export declare abstract class TlvSchema<T> extends Schema<T, ByteArray> implements TlvSchema<T> {
|
|
10
|
+
decodeInternal(encoded: ByteArray): T;
|
|
11
|
+
encodeInternal(value: T): ByteArray;
|
|
12
|
+
encodeTlv(value: T): TlvStream;
|
|
13
|
+
decodeTlv(encoded: TlvStream): T;
|
|
14
|
+
decodeTlvInternal(reader: TlvReader): {
|
|
15
|
+
value: T;
|
|
16
|
+
tag?: TlvTag;
|
|
17
|
+
};
|
|
18
|
+
abstract decodeTlvInternalValue(reader: TlvReader, typeLength: TlvTypeLength): T;
|
|
19
|
+
abstract encodeTlvInternal(writer: TlvWriter, value: T, tag?: TlvTag): void;
|
|
20
|
+
}
|
|
21
|
+
export type TlvStream = TlvElement<any>[];
|
|
22
|
+
export type TlvElement<T extends TlvTypeLength> = {
|
|
23
|
+
tag?: TlvTag;
|
|
24
|
+
typeLength: T;
|
|
25
|
+
value?: TlvToPrimitive[T["type"]];
|
|
26
|
+
};
|
|
27
|
+
export declare class TlvArrayWriter implements TlvWriter {
|
|
28
|
+
private readonly tlvArray;
|
|
29
|
+
writeTag(typeLength: TlvTypeLength, tag?: TlvTag): void;
|
|
30
|
+
writePrimitive<T extends TlvTypeLength>(_typeLength: T, value: TlvToPrimitive[T["type"]]): void;
|
|
31
|
+
toTlvArray(): TlvElement<any>[];
|
|
32
|
+
}
|
|
33
|
+
export declare class TlvArrayReader implements TlvReader {
|
|
34
|
+
private readonly tlvElements;
|
|
35
|
+
private index;
|
|
36
|
+
constructor(tlvElements: TlvElement<any>[]);
|
|
37
|
+
readTagType(): TlvElement<any>;
|
|
38
|
+
readPrimitive<T extends TlvTypeLength, V = TlvToPrimitive[T["type"]]>(_typeLength: T): V;
|
|
39
|
+
}
|
|
40
|
+
/** Type defined by the TLV schema. */
|
|
41
|
+
export type TypeFromSchema<S extends TlvSchema<any>> = S extends TlvSchema<infer T> ? T : never;
|
|
42
|
+
export interface TlvReader {
|
|
43
|
+
readTagType(): {
|
|
44
|
+
tag?: TlvTag;
|
|
45
|
+
typeLength: TlvTypeLength;
|
|
46
|
+
};
|
|
47
|
+
readPrimitive<T extends TlvTypeLength, V = TlvToPrimitive[T["type"]]>(typeLength: T): V;
|
|
48
|
+
}
|
|
49
|
+
export interface TlvWriter {
|
|
50
|
+
writeTag(typeLength: TlvTypeLength, tag?: TlvTag): void;
|
|
51
|
+
writePrimitive<T extends TlvTypeLength>(typeLength: T, value: TlvToPrimitive[T["type"]]): void;
|
|
52
|
+
}
|
|
53
|
+
export declare class TlvByteArrayWriter implements TlvWriter {
|
|
54
|
+
private readonly writer;
|
|
55
|
+
writeTag(typeLength: TlvTypeLength, tag?: TlvTag): void;
|
|
56
|
+
writePrimitive<T extends TlvTypeLength>(typeLength: T, value: TlvToPrimitive[T["type"]]): void;
|
|
57
|
+
toByteArray(): Uint8Array;
|
|
58
|
+
}
|
|
59
|
+
export declare class TlvByteArrayReader implements TlvReader {
|
|
60
|
+
private readonly reader;
|
|
61
|
+
constructor(byteArray: ByteArray);
|
|
62
|
+
readTagType(): {
|
|
63
|
+
tag?: TlvTag | undefined;
|
|
64
|
+
typeLength: TlvTypeLength;
|
|
65
|
+
};
|
|
66
|
+
readPrimitive<T extends TlvTypeLength, V = TlvToPrimitive[T["type"]]>(typeLength: T): V;
|
|
67
|
+
}
|