@tomgiee/tsdp 1.0.1 → 1.1.0
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 +0 -39
- package/dist/src/builder/media-builder.d.ts.map +1 -1
- package/dist/src/builder/media-builder.js +5 -12
- package/dist/src/builder/session-builder.d.ts.map +1 -1
- package/dist/src/builder/session-builder.js +4 -14
- package/dist/src/index.d.ts +6 -10
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +37 -49
- package/dist/src/parser/core.d.ts +366 -0
- package/dist/src/parser/core.d.ts.map +1 -0
- package/dist/src/parser/core.js +802 -0
- package/dist/src/parser/field-parser.d.ts +51 -8
- package/dist/src/parser/field-parser.d.ts.map +1 -1
- package/dist/src/parser/field-parser.js +91 -23
- package/dist/src/parser/media-parser.d.ts +1 -1
- package/dist/src/parser/media-parser.d.ts.map +1 -1
- package/dist/src/parser/media-parser.js +9 -15
- package/dist/src/parser/session-parser.d.ts.map +1 -1
- package/dist/src/parser/session-parser.js +16 -17
- package/dist/src/parser/time-parser.d.ts +1 -1
- package/dist/src/parser/time-parser.d.ts.map +1 -1
- package/dist/src/parser/time-parser.js +8 -8
- package/dist/src/serializer/fields.d.ts +167 -0
- package/dist/src/serializer/fields.d.ts.map +1 -0
- package/dist/src/serializer/fields.js +320 -0
- package/dist/src/serializer/media-serializer.js +6 -7
- package/dist/src/serializer/session-serializer.js +13 -15
- package/dist/src/types/attributes.d.ts.map +1 -1
- package/dist/src/types/fields.d.ts +5 -5
- package/dist/src/types/fields.d.ts.map +1 -1
- package/dist/src/types/fields.js +4 -4
- package/dist/src/types/media.d.ts +9 -10
- package/dist/src/types/media.d.ts.map +1 -1
- package/dist/src/types/media.js +2 -4
- package/dist/src/types/network.d.ts +15 -56
- package/dist/src/types/network.d.ts.map +1 -1
- package/dist/src/types/network.js +3 -34
- package/dist/src/types/primitives.d.ts +3 -147
- package/dist/src/types/primitives.d.ts.map +1 -1
- package/dist/src/types/primitives.js +2 -171
- package/dist/src/types/session.d.ts +14 -14
- package/dist/src/types/session.d.ts.map +1 -1
- package/dist/src/types/time.d.ts +4 -4
- package/dist/src/types/time.d.ts.map +1 -1
- package/dist/src/types/time.js +8 -6
- package/dist/src/utils/address-parser.d.ts +4 -4
- package/dist/src/utils/address-parser.d.ts.map +1 -1
- package/dist/src/utils/address-parser.js +9 -16
- package/dist/src/validator/validator.d.ts +94 -0
- package/dist/src/validator/validator.d.ts.map +1 -0
- package/dist/src/validator/validator.js +573 -0
- package/dist/tests/unit/parser/attribute-parser.test.js +106 -107
- package/dist/tests/unit/parser/field-parser.test.js +66 -66
- package/dist/tests/unit/parser/media-parser.test.js +38 -38
- package/dist/tests/unit/parser/primitive-parser.test.js +89 -90
- package/dist/tests/unit/parser/scanner.test.js +32 -32
- package/dist/tests/unit/parser/time-parser.test.js +22 -22
- package/dist/tests/unit/serializer/attribute-serializer.test.js +22 -22
- package/dist/tests/unit/serializer/field-serializer.test.js +57 -57
- package/dist/tests/unit/serializer/media-serializer.test.js +5 -6
- package/dist/tests/unit/serializer/session-serializer.test.js +24 -24
- package/dist/tests/unit/serializer/time-serializer.test.js +16 -16
- package/dist/tests/unit/types/network.test.js +21 -56
- package/dist/tests/unit/types/primitives.test.js +0 -39
- package/dist/tests/unit/validator/media-validator.test.js +34 -35
- package/dist/tests/unit/validator/semantic-validator.test.js +36 -37
- package/dist/tests/unit/validator/session-validator.test.js +54 -54
- package/package.json +1 -1
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Parsers for individual SDP field types (v=, o=, s=, i=, u=, e=, p=, c=, b=, k=)
|
|
5
5
|
*/
|
|
6
|
-
import { Scanner } from './
|
|
7
|
-
import { Version
|
|
6
|
+
import { Scanner } from './core';
|
|
7
|
+
import { Version } from '../types/primitives';
|
|
8
8
|
import { Origin, Connection, Bandwidth } from '../types/fields';
|
|
9
9
|
/**
|
|
10
10
|
* Parse version field
|
|
@@ -37,7 +37,7 @@ export declare function parseOriginField(scanner: Scanner): Origin;
|
|
|
37
37
|
* @returns SessionName
|
|
38
38
|
* @throws ParseError if empty
|
|
39
39
|
*/
|
|
40
|
-
export declare function parseSessionNameField(scanner: Scanner):
|
|
40
|
+
export declare function parseSessionNameField(scanner: Scanner): string;
|
|
41
41
|
/**
|
|
42
42
|
* Parse information field
|
|
43
43
|
*
|
|
@@ -46,7 +46,7 @@ export declare function parseSessionNameField(scanner: Scanner): SessionName;
|
|
|
46
46
|
* @param scanner - Scanner instance
|
|
47
47
|
* @returns Information string
|
|
48
48
|
*/
|
|
49
|
-
export declare function parseInformationField(scanner: Scanner):
|
|
49
|
+
export declare function parseInformationField(scanner: Scanner): string;
|
|
50
50
|
/**
|
|
51
51
|
* Parse URI field
|
|
52
52
|
*
|
|
@@ -55,7 +55,7 @@ export declare function parseInformationField(scanner: Scanner): Information;
|
|
|
55
55
|
* @param scanner - Scanner instance
|
|
56
56
|
* @returns URI string
|
|
57
57
|
*/
|
|
58
|
-
export declare function parseUriField(scanner: Scanner):
|
|
58
|
+
export declare function parseUriField(scanner: Scanner): string;
|
|
59
59
|
/**
|
|
60
60
|
* Parse email field
|
|
61
61
|
*
|
|
@@ -64,7 +64,7 @@ export declare function parseUriField(scanner: Scanner): URI;
|
|
|
64
64
|
* @param scanner - Scanner instance
|
|
65
65
|
* @returns Email string
|
|
66
66
|
*/
|
|
67
|
-
export declare function parseEmailField(scanner: Scanner):
|
|
67
|
+
export declare function parseEmailField(scanner: Scanner): string;
|
|
68
68
|
/**
|
|
69
69
|
* Parse phone field
|
|
70
70
|
*
|
|
@@ -73,7 +73,7 @@ export declare function parseEmailField(scanner: Scanner): Email;
|
|
|
73
73
|
* @param scanner - Scanner instance
|
|
74
74
|
* @returns Phone string
|
|
75
75
|
*/
|
|
76
|
-
export declare function parsePhoneField(scanner: Scanner):
|
|
76
|
+
export declare function parsePhoneField(scanner: Scanner): string;
|
|
77
77
|
/**
|
|
78
78
|
* Parse connection field
|
|
79
79
|
*
|
|
@@ -120,5 +120,48 @@ export declare function parseBandwidthField(scanner: Scanner): Bandwidth;
|
|
|
120
120
|
* @param scanner - Scanner instance
|
|
121
121
|
* @returns Key string
|
|
122
122
|
*/
|
|
123
|
-
export declare function parseKeyField(scanner: Scanner):
|
|
123
|
+
export declare function parseKeyField(scanner: Scanner): string;
|
|
124
|
+
/**
|
|
125
|
+
* Parse session name directly from pre-split line value
|
|
126
|
+
*
|
|
127
|
+
* @param value - The line value (everything after "s=")
|
|
128
|
+
* @returns SessionName
|
|
129
|
+
* @throws ParseError if empty
|
|
130
|
+
*/
|
|
131
|
+
export declare function parseSessionNameDirect(value: string): string;
|
|
132
|
+
/**
|
|
133
|
+
* Parse information directly from pre-split line value
|
|
134
|
+
*
|
|
135
|
+
* @param value - The line value (everything after "i=")
|
|
136
|
+
* @returns Information string
|
|
137
|
+
*/
|
|
138
|
+
export declare function parseInformationDirect(value: string): string;
|
|
139
|
+
/**
|
|
140
|
+
* Parse URI directly from pre-split line value
|
|
141
|
+
*
|
|
142
|
+
* @param value - The line value (everything after "u=")
|
|
143
|
+
* @returns URI string
|
|
144
|
+
*/
|
|
145
|
+
export declare function parseUriDirect(value: string): string;
|
|
146
|
+
/**
|
|
147
|
+
* Parse email directly from pre-split line value
|
|
148
|
+
*
|
|
149
|
+
* @param value - The line value (everything after "e=")
|
|
150
|
+
* @returns Email string
|
|
151
|
+
*/
|
|
152
|
+
export declare function parseEmailDirect(value: string): string;
|
|
153
|
+
/**
|
|
154
|
+
* Parse phone directly from pre-split line value
|
|
155
|
+
*
|
|
156
|
+
* @param value - The line value (everything after "p=")
|
|
157
|
+
* @returns Phone string
|
|
158
|
+
*/
|
|
159
|
+
export declare function parsePhoneDirect(value: string): string;
|
|
160
|
+
/**
|
|
161
|
+
* Parse key directly from pre-split line value
|
|
162
|
+
*
|
|
163
|
+
* @param value - The line value (everything after "k=")
|
|
164
|
+
* @returns Key string
|
|
165
|
+
*/
|
|
166
|
+
export declare function parseKeyDirect(value: string): string;
|
|
124
167
|
//# sourceMappingURL=field-parser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field-parser.d.ts","sourceRoot":"","sources":["../../../src/parser/field-parser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"field-parser.d.ts","sourceRoot":"","sources":["../../../src/parser/field-parser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,OAAO,EAUR,MAAM,QAAQ,CAAC;AAEhB,OAAO,EACL,OAAO,EAGR,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAmD,MAAM,iBAAiB,CAAC;AAmBjH;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAa3D;AAMD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAmCzD;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAe9D;AAMD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAG9D;AAMD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAEtD;AAMD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAExD;AAMD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAExD;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,UAAU,CAiBjE;AAyHD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,CAqB/D;AAMD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAGtD;AAQD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAK5D;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEpD"}
|
|
@@ -15,9 +15,14 @@ exports.parsePhoneField = parsePhoneField;
|
|
|
15
15
|
exports.parseConnectionField = parseConnectionField;
|
|
16
16
|
exports.parseBandwidthField = parseBandwidthField;
|
|
17
17
|
exports.parseKeyField = parseKeyField;
|
|
18
|
-
|
|
18
|
+
exports.parseSessionNameDirect = parseSessionNameDirect;
|
|
19
|
+
exports.parseInformationDirect = parseInformationDirect;
|
|
20
|
+
exports.parseUriDirect = parseUriDirect;
|
|
21
|
+
exports.parseEmailDirect = parseEmailDirect;
|
|
22
|
+
exports.parsePhoneDirect = parsePhoneDirect;
|
|
23
|
+
exports.parseKeyDirect = parseKeyDirect;
|
|
24
|
+
const core_1 = require("./core");
|
|
19
25
|
const errors_1 = require("../types/errors");
|
|
20
|
-
const primitives_1 = require("../types/primitives");
|
|
21
26
|
const fields_1 = require("../types/fields");
|
|
22
27
|
const network_1 = require("../types/network");
|
|
23
28
|
const address_parser_1 = require("../utils/address-parser");
|
|
@@ -36,11 +41,11 @@ const address_parser_2 = require("../utils/address-parser");
|
|
|
36
41
|
*/
|
|
37
42
|
function parseVersionField(scanner) {
|
|
38
43
|
const start = scanner.getPosition();
|
|
39
|
-
const version = (0,
|
|
44
|
+
const version = (0, core_1.parseInteger)(scanner);
|
|
40
45
|
if (version !== 0) {
|
|
41
46
|
throw new errors_1.ParseError(`Unsupported SDP version: ${version} (expected 0)`, start.line, start.column);
|
|
42
47
|
}
|
|
43
|
-
return
|
|
48
|
+
return 0;
|
|
44
49
|
}
|
|
45
50
|
// ============================================================================
|
|
46
51
|
// Origin Field Parser (o=)
|
|
@@ -57,19 +62,19 @@ function parseVersionField(scanner) {
|
|
|
57
62
|
function parseOriginField(scanner) {
|
|
58
63
|
const start = scanner.getPosition();
|
|
59
64
|
// Parse username (non-whitespace string)
|
|
60
|
-
const username = (0,
|
|
65
|
+
const username = (0, core_1.parseNonWSString)(scanner);
|
|
61
66
|
scanner.expectSpace();
|
|
62
67
|
// Parse session ID (non-whitespace string)
|
|
63
|
-
const sessId = (0,
|
|
68
|
+
const sessId = (0, core_1.parseNonWSString)(scanner);
|
|
64
69
|
scanner.expectSpace();
|
|
65
70
|
// Parse session version (non-whitespace string)
|
|
66
|
-
const sessVersion = (0,
|
|
71
|
+
const sessVersion = (0, core_1.parseNonWSString)(scanner);
|
|
67
72
|
scanner.expectSpace();
|
|
68
73
|
// Parse network type (token)
|
|
69
|
-
const netType = (0,
|
|
74
|
+
const netType = (0, core_1.parseToken)(scanner);
|
|
70
75
|
scanner.expectSpace();
|
|
71
76
|
// Parse address type (token)
|
|
72
|
-
const addrType = (0,
|
|
77
|
+
const addrType = (0, core_1.parseToken)(scanner);
|
|
73
78
|
scanner.expectSpace();
|
|
74
79
|
// Parse unicast address (depends on addrType)
|
|
75
80
|
const unicastAddress = (0, address_parser_1.parseUnicastAddress)(scanner.readUntil(/[\r\n]/), addrType);
|
|
@@ -125,7 +130,7 @@ function parseInformationField(scanner) {
|
|
|
125
130
|
* @returns URI string
|
|
126
131
|
*/
|
|
127
132
|
function parseUriField(scanner) {
|
|
128
|
-
return (0,
|
|
133
|
+
return (0, core_1.parseURI)(scanner);
|
|
129
134
|
}
|
|
130
135
|
// ============================================================================
|
|
131
136
|
// Email Field Parser (e=)
|
|
@@ -139,7 +144,7 @@ function parseUriField(scanner) {
|
|
|
139
144
|
* @returns Email string
|
|
140
145
|
*/
|
|
141
146
|
function parseEmailField(scanner) {
|
|
142
|
-
return (0,
|
|
147
|
+
return (0, core_1.parseEmail)(scanner);
|
|
143
148
|
}
|
|
144
149
|
// ============================================================================
|
|
145
150
|
// Phone Field Parser (p=)
|
|
@@ -153,7 +158,7 @@ function parseEmailField(scanner) {
|
|
|
153
158
|
* @returns Phone string
|
|
154
159
|
*/
|
|
155
160
|
function parsePhoneField(scanner) {
|
|
156
|
-
return (0,
|
|
161
|
+
return (0, core_1.parsePhone)(scanner);
|
|
157
162
|
}
|
|
158
163
|
// ============================================================================
|
|
159
164
|
// Connection Field Parser (c=)
|
|
@@ -174,10 +179,10 @@ function parsePhoneField(scanner) {
|
|
|
174
179
|
function parseConnectionField(scanner) {
|
|
175
180
|
const start = scanner.getPosition();
|
|
176
181
|
// Parse network type (token)
|
|
177
|
-
const netType = (0,
|
|
182
|
+
const netType = (0, core_1.parseToken)(scanner);
|
|
178
183
|
scanner.expectSpace();
|
|
179
184
|
// Parse address type (token)
|
|
180
|
-
const addrType = (0,
|
|
185
|
+
const addrType = (0, core_1.parseToken)(scanner);
|
|
181
186
|
scanner.expectSpace();
|
|
182
187
|
// Parse connection address
|
|
183
188
|
const connectionAddress = parseConnectionAddress(scanner, addrType);
|
|
@@ -212,13 +217,13 @@ function parseConnectionAddress(scanner, addrType) {
|
|
|
212
217
|
}
|
|
213
218
|
// Multicast address - parse TTL and/or number of addresses
|
|
214
219
|
scanner.advance(); // consume '/'
|
|
215
|
-
const firstParam = (0,
|
|
220
|
+
const firstParam = (0, core_1.parseInteger)(scanner);
|
|
216
221
|
let ttl;
|
|
217
222
|
let numAddresses;
|
|
218
223
|
// Check for second parameter
|
|
219
224
|
if (scanner.peek() === '/') {
|
|
220
225
|
scanner.advance(); // consume second '/'
|
|
221
|
-
const secondParam = (0,
|
|
226
|
+
const secondParam = (0, core_1.parseInteger)(scanner);
|
|
222
227
|
// For IPv4: first is TTL, second is numAddresses
|
|
223
228
|
// For FQDN: first is TTL, second is numAddresses
|
|
224
229
|
// For IPv6: TTL is forbidden, so first is numAddresses
|
|
@@ -252,11 +257,11 @@ function parseConnectionAddress(scanner, addrType) {
|
|
|
252
257
|
if (!(0, address_parser_2.isIP4MulticastAddress)(addressPart)) {
|
|
253
258
|
throw new errors_1.ParseError(`IPv4 address '${addressPart}' with TTL/numAddresses must be a multicast address (224.0.0.0 - 239.255.255.255)`, start.line, start.column);
|
|
254
259
|
}
|
|
255
|
-
return (0, network_1.createIP4MulticastAddress)(
|
|
260
|
+
return (0, network_1.createIP4MulticastAddress)(addressPart, ttl, numAddresses);
|
|
256
261
|
}
|
|
257
262
|
else {
|
|
258
263
|
// Assume FQDN - cannot validate multicast range for FQDNs
|
|
259
|
-
return (0, network_1.createFQDNMulticastAddress)(
|
|
264
|
+
return (0, network_1.createFQDNMulticastAddress)(addressPart, ttl, numAddresses);
|
|
260
265
|
}
|
|
261
266
|
}
|
|
262
267
|
else if (addrType === 'IP6') {
|
|
@@ -266,16 +271,16 @@ function parseConnectionAddress(scanner, addrType) {
|
|
|
266
271
|
if (!(0, address_parser_2.isIP6MulticastAddress)(addressPart)) {
|
|
267
272
|
throw new errors_1.ParseError(`IPv6 address '${addressPart}' with numAddresses must be a multicast address (must start with FF)`, start.line, start.column);
|
|
268
273
|
}
|
|
269
|
-
return (0, network_1.createIP6MulticastAddress)(
|
|
274
|
+
return (0, network_1.createIP6MulticastAddress)(addressPart, numAddresses);
|
|
270
275
|
}
|
|
271
276
|
else {
|
|
272
277
|
// Assume FQDN - cannot validate multicast range for FQDNs
|
|
273
|
-
return (0, network_1.createFQDNMulticastAddress)(
|
|
278
|
+
return (0, network_1.createFQDNMulticastAddress)(addressPart, ttl, numAddresses);
|
|
274
279
|
}
|
|
275
280
|
}
|
|
276
281
|
else {
|
|
277
282
|
// Extension address type
|
|
278
|
-
return (0, network_1.createFQDNMulticastAddress)(
|
|
283
|
+
return (0, network_1.createFQDNMulticastAddress)(addressPart, ttl, numAddresses);
|
|
279
284
|
}
|
|
280
285
|
}
|
|
281
286
|
// ============================================================================
|
|
@@ -300,7 +305,7 @@ function parseConnectionAddress(scanner, addrType) {
|
|
|
300
305
|
function parseBandwidthField(scanner) {
|
|
301
306
|
const start = scanner.getPosition();
|
|
302
307
|
// Parse bandwidth type (token before ':')
|
|
303
|
-
const bwtype = (0,
|
|
308
|
+
const bwtype = (0, core_1.parseToken)(scanner);
|
|
304
309
|
// Expect ':'
|
|
305
310
|
const ch = scanner.peek();
|
|
306
311
|
if (ch !== ':') {
|
|
@@ -308,7 +313,7 @@ function parseBandwidthField(scanner) {
|
|
|
308
313
|
}
|
|
309
314
|
scanner.advance();
|
|
310
315
|
// Parse bandwidth value (integer)
|
|
311
|
-
const bandwidth = (0,
|
|
316
|
+
const bandwidth = (0, core_1.parseInteger)(scanner);
|
|
312
317
|
return (0, fields_1.createBandwidth)(bwtype, bandwidth);
|
|
313
318
|
}
|
|
314
319
|
// ============================================================================
|
|
@@ -333,3 +338,66 @@ function parseKeyField(scanner) {
|
|
|
333
338
|
// Read entire line
|
|
334
339
|
return scanner.readUntil(/[\r\n]/);
|
|
335
340
|
}
|
|
341
|
+
// ============================================================================
|
|
342
|
+
// Simplified Direct Parsers (no Scanner overhead)
|
|
343
|
+
// ============================================================================
|
|
344
|
+
// These parsers accept already-split line values directly, avoiding Scanner
|
|
345
|
+
// instantiation overhead for trivial fields that just read to end-of-line.
|
|
346
|
+
/**
|
|
347
|
+
* Parse session name directly from pre-split line value
|
|
348
|
+
*
|
|
349
|
+
* @param value - The line value (everything after "s=")
|
|
350
|
+
* @returns SessionName
|
|
351
|
+
* @throws ParseError if empty
|
|
352
|
+
*/
|
|
353
|
+
function parseSessionNameDirect(value) {
|
|
354
|
+
if (value.length === 0) {
|
|
355
|
+
throw new errors_1.ParseError('Session name cannot be empty', 1, 1);
|
|
356
|
+
}
|
|
357
|
+
return value;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Parse information directly from pre-split line value
|
|
361
|
+
*
|
|
362
|
+
* @param value - The line value (everything after "i=")
|
|
363
|
+
* @returns Information string
|
|
364
|
+
*/
|
|
365
|
+
function parseInformationDirect(value) {
|
|
366
|
+
return value;
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Parse URI directly from pre-split line value
|
|
370
|
+
*
|
|
371
|
+
* @param value - The line value (everything after "u=")
|
|
372
|
+
* @returns URI string
|
|
373
|
+
*/
|
|
374
|
+
function parseUriDirect(value) {
|
|
375
|
+
return value;
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Parse email directly from pre-split line value
|
|
379
|
+
*
|
|
380
|
+
* @param value - The line value (everything after "e=")
|
|
381
|
+
* @returns Email string
|
|
382
|
+
*/
|
|
383
|
+
function parseEmailDirect(value) {
|
|
384
|
+
return value;
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Parse phone directly from pre-split line value
|
|
388
|
+
*
|
|
389
|
+
* @param value - The line value (everything after "p=")
|
|
390
|
+
* @returns Phone string
|
|
391
|
+
*/
|
|
392
|
+
function parsePhoneDirect(value) {
|
|
393
|
+
return value;
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Parse key directly from pre-split line value
|
|
397
|
+
*
|
|
398
|
+
* @param value - The line value (everything after "k=")
|
|
399
|
+
* @returns Key string
|
|
400
|
+
*/
|
|
401
|
+
function parseKeyDirect(value) {
|
|
402
|
+
return value;
|
|
403
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media-parser.d.ts","sourceRoot":"","sources":["../../../src/parser/media-parser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"media-parser.d.ts","sourceRoot":"","sources":["../../../src/parser/media-parser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAmC,MAAM,QAAQ,CAAC;AAGlE,OAAO,EACL,KAAK,EACL,gBAAgB,EAMjB,MAAM,gBAAgB,CAAC;AAUxB;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,KAAK,CA2FvD;AAMD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,qBAAqB,CACnC,iBAAiB,EAAE,OAAO,EAC1B,eAAe,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,GACjD,gBAAgB,CAiElB"}
|
|
@@ -7,13 +7,10 @@
|
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
8
|
exports.parseMediaField = parseMediaField;
|
|
9
9
|
exports.parseMediaDescription = parseMediaDescription;
|
|
10
|
-
const
|
|
11
|
-
const primitive_parser_1 = require("./primitive-parser");
|
|
10
|
+
const core_1 = require("./core");
|
|
12
11
|
const field_parser_1 = require("./field-parser");
|
|
13
|
-
const attribute_parser_1 = require("./attribute-parser");
|
|
14
12
|
const errors_1 = require("../types/errors");
|
|
15
13
|
const media_1 = require("../types/media");
|
|
16
|
-
const primitives_1 = require("../types/primitives");
|
|
17
14
|
// ============================================================================
|
|
18
15
|
// Media Field Parser (m=)
|
|
19
16
|
// ============================================================================
|
|
@@ -34,8 +31,7 @@ const primitives_1 = require("../types/primitives");
|
|
|
34
31
|
function parseMediaField(scanner) {
|
|
35
32
|
const start = scanner.getPosition();
|
|
36
33
|
// Parse media type (token)
|
|
37
|
-
const
|
|
38
|
-
const mediaType = (0, primitives_1.createMediaType)(mediaTypeStr);
|
|
34
|
+
const mediaType = (0, core_1.parseToken)(scanner);
|
|
39
35
|
// Parse port or port range
|
|
40
36
|
scanner.skipWhitespace();
|
|
41
37
|
const portStart = scanner.getPosition();
|
|
@@ -73,13 +69,12 @@ function parseMediaField(scanner) {
|
|
|
73
69
|
if (protoStr.length === 0) {
|
|
74
70
|
throw new errors_1.ParseError('Expected protocol', protoStart.line, protoStart.column);
|
|
75
71
|
}
|
|
76
|
-
const proto =
|
|
72
|
+
const proto = protoStr;
|
|
77
73
|
// Parse formats (one or more)
|
|
78
74
|
const formats = [];
|
|
79
75
|
scanner.skipWhitespace();
|
|
80
76
|
while (!scanner.isEOF() && scanner.peek() !== '\r' && scanner.peek() !== '\n') {
|
|
81
|
-
|
|
82
|
-
formats.push((0, primitives_1.createFormat)(formatStr));
|
|
77
|
+
formats.push((0, core_1.parseToken)(scanner));
|
|
83
78
|
scanner.skipWhitespace();
|
|
84
79
|
}
|
|
85
80
|
if (formats.length === 0) {
|
|
@@ -118,28 +113,27 @@ function parseMediaDescription(mediaFieldScanner, additionalLines) {
|
|
|
118
113
|
let key;
|
|
119
114
|
const attributes = [];
|
|
120
115
|
for (const line of additionalLines) {
|
|
121
|
-
const scanner = new scanner_1.Scanner(line.value);
|
|
122
116
|
switch (line.type) {
|
|
123
117
|
case 'i':
|
|
124
118
|
if (information !== undefined) {
|
|
125
119
|
throw new errors_1.ParseError('Duplicate information field in media description', 0, 0);
|
|
126
120
|
}
|
|
127
|
-
information = (0, field_parser_1.
|
|
121
|
+
information = (0, field_parser_1.parseInformationDirect)(line.value);
|
|
128
122
|
break;
|
|
129
123
|
case 'c':
|
|
130
|
-
connections.push((0, field_parser_1.parseConnectionField)(
|
|
124
|
+
connections.push((0, field_parser_1.parseConnectionField)(new core_1.Scanner(line.value)));
|
|
131
125
|
break;
|
|
132
126
|
case 'b':
|
|
133
|
-
bandwidths.push((0, field_parser_1.parseBandwidthField)(
|
|
127
|
+
bandwidths.push((0, field_parser_1.parseBandwidthField)(new core_1.Scanner(line.value)));
|
|
134
128
|
break;
|
|
135
129
|
case 'k':
|
|
136
130
|
if (key !== undefined) {
|
|
137
131
|
throw new errors_1.ParseError('Duplicate key field in media description', 0, 0);
|
|
138
132
|
}
|
|
139
|
-
key = (0, field_parser_1.
|
|
133
|
+
key = (0, field_parser_1.parseKeyDirect)(line.value);
|
|
140
134
|
break;
|
|
141
135
|
case 'a':
|
|
142
|
-
attributes.push((0,
|
|
136
|
+
attributes.push((0, core_1.parseAttributeField)(new core_1.Scanner(line.value)));
|
|
143
137
|
break;
|
|
144
138
|
default:
|
|
145
139
|
// Unknown field type - this shouldn't happen if called correctly
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-parser.d.ts","sourceRoot":"","sources":["../../../src/parser/session-parser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"session-parser.d.ts","sourceRoot":"","sources":["../../../src/parser/session-parser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAkBH,OAAO,EAAE,kBAAkB,EAA4B,MAAM,kBAAkB,CAAC;AAYhF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB,CAkNzE"}
|
|
@@ -6,10 +6,9 @@
|
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
8
|
exports.parseSessionDescription = parseSessionDescription;
|
|
9
|
-
const
|
|
9
|
+
const core_1 = require("./core");
|
|
10
10
|
const field_parser_1 = require("./field-parser");
|
|
11
11
|
const time_parser_1 = require("./time-parser");
|
|
12
|
-
const attribute_parser_1 = require("./attribute-parser");
|
|
13
12
|
const media_parser_1 = require("./media-parser");
|
|
14
13
|
const errors_1 = require("../types/errors");
|
|
15
14
|
const session_1 = require("../types/session");
|
|
@@ -75,13 +74,13 @@ function parseSessionDescription(input) {
|
|
|
75
74
|
// ========================================================================
|
|
76
75
|
// v= version (required, exactly one)
|
|
77
76
|
const vLine = expect('v', 'version');
|
|
78
|
-
const version = (0, field_parser_1.parseVersionField)(new
|
|
77
|
+
const version = (0, field_parser_1.parseVersionField)(new core_1.Scanner(vLine.value));
|
|
79
78
|
// o= origin (required, exactly one)
|
|
80
79
|
const oLine = expect('o', 'origin');
|
|
81
|
-
const origin = (0, field_parser_1.parseOriginField)(new
|
|
80
|
+
const origin = (0, field_parser_1.parseOriginField)(new core_1.Scanner(oLine.value));
|
|
82
81
|
// s= session name (required, exactly one)
|
|
83
82
|
const sLine = expect('s', 'session name');
|
|
84
|
-
const sessionName = (0, field_parser_1.
|
|
83
|
+
const sessionName = (0, field_parser_1.parseSessionNameDirect)(sLine.value);
|
|
85
84
|
// ========================================================================
|
|
86
85
|
// 2. Parse optional session-level fields (i=, u=, e=, p=, c=, b=)
|
|
87
86
|
// ========================================================================
|
|
@@ -94,32 +93,32 @@ function parseSessionDescription(input) {
|
|
|
94
93
|
// i= session information (optional, at most one)
|
|
95
94
|
if (((_a = current()) === null || _a === void 0 ? void 0 : _a.type) === 'i') {
|
|
96
95
|
const iLine = consume();
|
|
97
|
-
sessionInformation = (0, field_parser_1.
|
|
96
|
+
sessionInformation = (0, field_parser_1.parseInformationDirect)(iLine.value);
|
|
98
97
|
}
|
|
99
98
|
// u= URI (optional, at most one)
|
|
100
99
|
if (((_b = current()) === null || _b === void 0 ? void 0 : _b.type) === 'u') {
|
|
101
100
|
const uLine = consume();
|
|
102
|
-
uri = (0, field_parser_1.
|
|
101
|
+
uri = (0, field_parser_1.parseUriDirect)(uLine.value);
|
|
103
102
|
}
|
|
104
103
|
// e= email (optional, multiple)
|
|
105
104
|
while (((_c = current()) === null || _c === void 0 ? void 0 : _c.type) === 'e') {
|
|
106
105
|
const eLine = consume();
|
|
107
|
-
emails.push((0, field_parser_1.
|
|
106
|
+
emails.push((0, field_parser_1.parseEmailDirect)(eLine.value));
|
|
108
107
|
}
|
|
109
108
|
// p= phone (optional, multiple)
|
|
110
109
|
while (((_d = current()) === null || _d === void 0 ? void 0 : _d.type) === 'p') {
|
|
111
110
|
const pLine = consume();
|
|
112
|
-
phones.push((0, field_parser_1.
|
|
111
|
+
phones.push((0, field_parser_1.parsePhoneDirect)(pLine.value));
|
|
113
112
|
}
|
|
114
113
|
// c= connection (optional, at most one at session level)
|
|
115
114
|
if (((_e = current()) === null || _e === void 0 ? void 0 : _e.type) === 'c') {
|
|
116
115
|
const cLine = consume();
|
|
117
|
-
connection = (0, field_parser_1.parseConnectionField)(new
|
|
116
|
+
connection = (0, field_parser_1.parseConnectionField)(new core_1.Scanner(cLine.value));
|
|
118
117
|
}
|
|
119
118
|
// b= bandwidth (optional, multiple)
|
|
120
119
|
while (((_f = current()) === null || _f === void 0 ? void 0 : _f.type) === 'b') {
|
|
121
120
|
const bLine = consume();
|
|
122
|
-
bandwidths.push((0, field_parser_1.parseBandwidthField)(new
|
|
121
|
+
bandwidths.push((0, field_parser_1.parseBandwidthField)(new core_1.Scanner(bLine.value)));
|
|
123
122
|
}
|
|
124
123
|
// ========================================================================
|
|
125
124
|
// 3. Parse time descriptions (required, at least one)
|
|
@@ -132,18 +131,18 @@ function parseSessionDescription(input) {
|
|
|
132
131
|
// Parse time descriptions until we hit k=, a=, m=, or end
|
|
133
132
|
while (((_k = current()) === null || _k === void 0 ? void 0 : _k.type) === 't') {
|
|
134
133
|
const tLine = consume();
|
|
135
|
-
const timing = (0, time_parser_1.parseTimingField)(new
|
|
134
|
+
const timing = (0, time_parser_1.parseTimingField)(new core_1.Scanner(tLine.value));
|
|
136
135
|
// Parse optional repeat times (r=)
|
|
137
136
|
const repeats = [];
|
|
138
137
|
while (((_l = current()) === null || _l === void 0 ? void 0 : _l.type) === 'r') {
|
|
139
138
|
const rLine = consume();
|
|
140
|
-
repeats.push((0, time_parser_1.parseRepeatField)(new
|
|
139
|
+
repeats.push((0, time_parser_1.parseRepeatField)(new core_1.Scanner(rLine.value)));
|
|
141
140
|
}
|
|
142
141
|
// Parse optional timezone adjustments (z=)
|
|
143
142
|
let timezone;
|
|
144
143
|
if (((_m = current()) === null || _m === void 0 ? void 0 : _m.type) === 'z') {
|
|
145
144
|
const zLine = consume();
|
|
146
|
-
timezone = (0, time_parser_1.parseTimezoneField)(new
|
|
145
|
+
timezone = (0, time_parser_1.parseTimezoneField)(new core_1.Scanner(zLine.value));
|
|
147
146
|
}
|
|
148
147
|
timeDescriptions.push((0, time_parser_1.parseTimeDescription)(timing, repeats, timezone));
|
|
149
148
|
}
|
|
@@ -155,12 +154,12 @@ function parseSessionDescription(input) {
|
|
|
155
154
|
// k= key (optional, at most one)
|
|
156
155
|
if (((_o = current()) === null || _o === void 0 ? void 0 : _o.type) === 'k') {
|
|
157
156
|
const kLine = consume();
|
|
158
|
-
key = (0, field_parser_1.
|
|
157
|
+
key = (0, field_parser_1.parseKeyDirect)(kLine.value);
|
|
159
158
|
}
|
|
160
159
|
// a= attributes (optional, multiple)
|
|
161
160
|
while (((_p = current()) === null || _p === void 0 ? void 0 : _p.type) === 'a') {
|
|
162
161
|
const aLine = consume();
|
|
163
|
-
attributes.push((0,
|
|
162
|
+
attributes.push((0, core_1.parseAttributeField)(new core_1.Scanner(aLine.value)));
|
|
164
163
|
}
|
|
165
164
|
// ========================================================================
|
|
166
165
|
// 5. Parse media descriptions (optional, zero or more)
|
|
@@ -176,7 +175,7 @@ function parseSessionDescription(input) {
|
|
|
176
175
|
mediaLines.push({ type: line.type, value: line.value });
|
|
177
176
|
}
|
|
178
177
|
// Parse media description
|
|
179
|
-
const mediaDescription = (0, media_parser_1.parseMediaDescription)(new
|
|
178
|
+
const mediaDescription = (0, media_parser_1.parseMediaDescription)(new core_1.Scanner(mLine.value), mediaLines);
|
|
180
179
|
mediaDescriptions.push(mediaDescription);
|
|
181
180
|
}
|
|
182
181
|
// ========================================================================
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time-parser.d.ts","sourceRoot":"","sources":["../../../src/parser/time-parser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"time-parser.d.ts","sourceRoot":"","sources":["../../../src/parser/time-parser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAgC,MAAM,QAAQ,CAAC;AAE/D,OAAO,EACL,MAAM,EACN,MAAM,EACN,QAAQ,EAER,eAAe,EAMhB,MAAM,eAAe,CAAC;AAOvB;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAsBzD;AAMD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CA2CzD;AAMD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,CAgD7D;AAMD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,MAAM,EAAO,EACtB,QAAQ,CAAC,EAAE,QAAQ,GAClB,eAAe,CAEjB"}
|
|
@@ -9,7 +9,7 @@ exports.parseTimingField = parseTimingField;
|
|
|
9
9
|
exports.parseRepeatField = parseRepeatField;
|
|
10
10
|
exports.parseTimezoneField = parseTimezoneField;
|
|
11
11
|
exports.parseTimeDescription = parseTimeDescription;
|
|
12
|
-
const
|
|
12
|
+
const core_1 = require("./core");
|
|
13
13
|
const errors_1 = require("../types/errors");
|
|
14
14
|
const time_1 = require("../types/time");
|
|
15
15
|
// ============================================================================
|
|
@@ -30,11 +30,11 @@ const time_1 = require("../types/time");
|
|
|
30
30
|
function parseTimingField(scanner) {
|
|
31
31
|
const start = scanner.getPosition();
|
|
32
32
|
// Parse start time
|
|
33
|
-
const startTime = (0,
|
|
33
|
+
const startTime = (0, core_1.parseNtpTime)(scanner);
|
|
34
34
|
// Expect space
|
|
35
35
|
scanner.expectSpace();
|
|
36
36
|
// Parse stop time
|
|
37
|
-
const stopTime = (0,
|
|
37
|
+
const stopTime = (0, core_1.parseNtpTime)(scanner);
|
|
38
38
|
// Validate timing constraints
|
|
39
39
|
try {
|
|
40
40
|
return (0, time_1.createTiming)(startTime, stopTime);
|
|
@@ -67,10 +67,10 @@ function parseTimingField(scanner) {
|
|
|
67
67
|
function parseRepeatField(scanner) {
|
|
68
68
|
const start = scanner.getPosition();
|
|
69
69
|
// Parse repeat interval
|
|
70
|
-
const interval = (0,
|
|
70
|
+
const interval = (0, core_1.parseTypedTime)(scanner);
|
|
71
71
|
scanner.expectSpace();
|
|
72
72
|
// Parse active duration
|
|
73
|
-
const duration = (0,
|
|
73
|
+
const duration = (0, core_1.parseTypedTime)(scanner);
|
|
74
74
|
// Parse offsets (at least one required)
|
|
75
75
|
const offsets = [];
|
|
76
76
|
while (!scanner.isEOF()) {
|
|
@@ -79,7 +79,7 @@ function parseRepeatField(scanner) {
|
|
|
79
79
|
break;
|
|
80
80
|
}
|
|
81
81
|
scanner.expectSpace();
|
|
82
|
-
offsets.push((0,
|
|
82
|
+
offsets.push((0, core_1.parseTypedTime)(scanner));
|
|
83
83
|
}
|
|
84
84
|
// Validate at least one offset
|
|
85
85
|
if (offsets.length === 0) {
|
|
@@ -120,10 +120,10 @@ function parseTimezoneField(scanner) {
|
|
|
120
120
|
break;
|
|
121
121
|
}
|
|
122
122
|
// Parse adjustment time
|
|
123
|
-
const time = (0,
|
|
123
|
+
const time = (0, core_1.parseNtpTime)(scanner);
|
|
124
124
|
scanner.expectSpace();
|
|
125
125
|
// Parse offset (can be negative, but parseTypedTime handles the sign in the string)
|
|
126
|
-
const offset = (0,
|
|
126
|
+
const offset = (0, core_1.parseTypedTime)(scanner);
|
|
127
127
|
adjustments.push((0, time_1.createTimezoneAdjustment)(time, offset));
|
|
128
128
|
// Check for more adjustments
|
|
129
129
|
if (!scanner.isEOF()) {
|