url-safe-bitpacking 0.1.6 → 0.1.8

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.
@@ -1 +1,2 @@
1
1
  export declare const getBitsForIntegerNumber: (number: number, maxBits: number) => number;
2
+ export declare const getMaxIntegerValueForGivenBitWidth: (bitCount: number) => number;
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { ObjectGenerationOutputStatus, DataType } from './enums';
2
2
  export { DataEntryFactory } from './factory';
3
- export { getDefaultObject, updateDataEntry } from './objectmap';
4
- export { valueBitsParser, dataBitsParser, getBitsCount, dataBitsArrayParser, dataBitsStringifier, dataEntryCorrecting, parseBitsToBase64, parseBase64ToBits, dataArrayStringifier, } from './parsers';
3
+ export { createParserObject, parseUrl, updateDataEntry, getURLSafeBase64ForData, getSemanticallyNestedValues } from './objectmap';
4
+ export {} from './parsers';
5
5
  export { SingleLevelContentType, NestedContentDataType, NestedContentType, DoubleLevelContentType, NonEmptyValidEntryArrayType, OptionalEntryDataType, EnumEntryDataType, VersionArrayDefinitionType, PrecisionRangeType, SignificandMaxBits, FloatData, IntegerMaxBits, IntData, VersionRangeType, VersionData, BooleanData, DataEntry, DataEntryArray, SemanticlyNestedDataEntry, ObjectGeneratorMethod, DefinitionGenerationObject, DefinitionNestedArray, DefinitionNestedGenerationObject, DefinitionSubObject, DefinitionArrayObject, VersionDefinitionObject, VersionEnumSemantics, ParserForVersion, ParsersForVersionObject, } from './types';
6
6
  export {} from './update';
7
7
  export { interpolateEntryAt, getRelativeValue } from './utils';
package/dist/index.js CHANGED
@@ -25,6 +25,7 @@ var getBitsForIntegerNumber = (number, maxBits) => {
25
25
  throw new Error(`Cannot get ${maxBits} bits for a number with ${bitCount} bits`);
26
26
  return bitCount;
27
27
  };
28
+ var getMaxIntegerValueForGivenBitWidth = (bitCount) => 2 ** bitCount - 1;
28
29
 
29
30
  // src/factory/floatFactory.ts
30
31
  var create = (value, min = 0, max = 1, precision = 2, name = "", index = -1) => {
@@ -95,6 +96,65 @@ var DataEntryFactory = {
95
96
  createBoolean: create3,
96
97
  createVersion: create4
97
98
  };
99
+ // src/types/arrayDefinitions.ts
100
+ var NAME_DELIMETER = "_";
101
+
102
+ // src/objectmap/versionArrayDefinitionToObjectDefintion.ts
103
+ var isSingleLevelContentType = (data) => singleLevelContentTypeIsDataEntry(data[0]) || singleLevelContentTypeIsNestedContentDataType(data[0]);
104
+ var isDoubleLevelContentType = (data) => !isSingleLevelContentType(data);
105
+ var singleLevelContentTypeIsDataEntry = (data) => !Array.isArray(data) && typeof data === "object";
106
+ var singleLevelContentTypeIsNestedContentDataType = (data) => Array.isArray(data) && typeof data[0] === "string";
107
+ var singleLevelContentTypeIsEnumEntryDataType = (data) => isDoubleLevelContentType(data) && typeof data[0] === "number";
108
+ var singleLevelContentTypeIsOptionalEntryDataType = (data) => isDoubleLevelContentType(data) && typeof data[0] === "boolean";
109
+ var parseSingleLevelContentTypeToDefinitionSubObject = (data, internalPrecedingName) => {
110
+ if (singleLevelContentTypeIsDataEntry(data))
111
+ return parseDataEntry(data, internalPrecedingName);
112
+ else if (singleLevelContentTypeIsNestedContentDataType(data))
113
+ return parseNestedContentDataTypeToDefinitionNestedArray(data, internalPrecedingName);
114
+ else {
115
+ throw new Error("this is an invalid output value, wonder why?");
116
+ }
117
+ };
118
+ var parseNestedContentDataTypeToDefinitionNestedArray = (data, internalPrecedingName) => {
119
+ const [attributeName, localData] = data;
120
+ if (isSingleLevelContentType(localData))
121
+ return [attributeName, localData.map((v) => parseSingleLevelContentTypeToDefinitionSubObject(v, internalPrecedingName))];
122
+ else if (singleLevelContentTypeIsEnumEntryDataType(localData))
123
+ return parseEnumEntryDataTypeToDefinitionNestedGenerationObject(localData, attributeName, internalPrecedingName);
124
+ else if (singleLevelContentTypeIsOptionalEntryDataType(localData))
125
+ return parseOptionalEntryDataTypeToDefinitionNestedGenerationObject(localData, attributeName, internalPrecedingName);
126
+ else {
127
+ throw new Error("this is an invalid output value, wonder why?");
128
+ }
129
+ };
130
+ var parseEnumEntryDataTypeToDefinitionNestedGenerationObject = (data, name, internalPrecedingName) => {
131
+ if (Math.round(data[0]) !== data[0])
132
+ `given default (${data[0]}) value isn't an integer, rounding it`;
133
+ if (data.length - 2 < Math.round(data[0]))
134
+ console.log(`given default value (${data[0]}) was larger than the amount of options available, using the largest value (${data.length - 2}) instead`);
135
+ if (data[0] < 0)
136
+ console.log(`given default value (${data[0]}) was negative, using first index (0) instead`);
137
+ const dataEntry = parseDataEntry(DataEntryFactory.createEnum(Math.max(Math.min(data.length - 2, Math.round(data[0])), 0), data.length - 2, name), internalPrecedingName);
138
+ const generationMethod = (d) => [
139
+ d,
140
+ ...data[d.value + 1].map((v) => parseSingleLevelContentTypeToDefinitionSubObject(v, dataEntry.internalName))
141
+ ];
142
+ return [name, dataEntry, generationMethod];
143
+ };
144
+ var parseOptionalEntryDataTypeToDefinitionNestedGenerationObject = (data, name, internalPrecedingName) => {
145
+ const dataEntry = parseDataEntry(DataEntryFactory.createBoolean(data[0], name), internalPrecedingName);
146
+ const generationMethod = (d) => [
147
+ d,
148
+ ...data[Number(!d.value) + 1].map((v) => parseSingleLevelContentTypeToDefinitionSubObject(v, dataEntry.internalName))
149
+ ];
150
+ return [name, dataEntry, generationMethod];
151
+ };
152
+ var parseDataEntry = (d, internalPrecedingName) => internalPrecedingName ? { ...d, internalName: `${internalPrecedingName}${NAME_DELIMETER}${d.name}` } : d;
153
+ var parseVersionArrayDefinitionTypeToVersionDefinitionObject = (v, optionalIndexOverwrite) => [
154
+ optionalIndexOverwrite ? { ...parseDataEntry(v[0]), value: optionalIndexOverwrite } : parseDataEntry(v[0]),
155
+ ...v.slice(1).map((d) => parseSingleLevelContentTypeToDefinitionSubObject(d, "_"))
156
+ ];
157
+
98
158
  // src/parsers/intParser.ts
99
159
  var getBitsCount = (intData2) => intData2.bits;
100
160
  var rawValueParser = (stateString, bitCount) => {
@@ -255,20 +315,58 @@ var dataArrayStringifier = (dataEntryArray) => {
255
315
 
256
316
  // src/objectmap/versionReading.ts
257
317
  var currentObjectIndex = -1;
258
- var nestedDataEntryArrayToObject = (definitionArrayObject) => {
259
- currentObjectIndex = -1;
260
- return internalNestedDataEntryArrayToObject(definitionArrayObject);
318
+ var definitionArrayObjectParser = (bitString, v) => {
319
+ const [key, values] = v;
320
+ const [nestedSemanticObject, objectGenerationStatus, localEndIndex] = parsingDefinitionArrayObject(bitString, values);
321
+ return [[key, nestedSemanticObject], objectGenerationStatus, localEndIndex];
322
+ };
323
+ var methodParser = (bitString, v) => {
324
+ const [key, keyDataDescription, methodGenerator] = v;
325
+ const [keyDataEntry, status] = dataEntryParser(bitString, keyDataDescription, false);
326
+ const [result, localStatus, localEndIndex] = definitionArrayObjectParser(bitString, [key, methodGenerator(keyDataEntry)]);
327
+ return [result, localStatus !== ObjectGenerationOutputStatus.PARSED ? localStatus : status, localEndIndex];
328
+ };
329
+ var dataEntryParser = (bitString, v, iterate = true) => {
330
+ const bitWidth = getBitsCount6(v);
331
+ const value = iterate ? { ...dataBitsParser(bitString.slice(0, bitWidth), v), index: ++currentObjectIndex } : dataBitsParser(bitString.slice(0, bitWidth), v);
332
+ return [value, ObjectGenerationOutputStatus.PARSED, bitWidth];
333
+ };
334
+ var parsingDefinitionArrayObject = (bitString, definitionArrayObject) => {
335
+ let startIndex = 0;
336
+ let objectGenerationStatus = ObjectGenerationOutputStatus.PARSED;
337
+ return [
338
+ Object.fromEntries(definitionArrayObject.map((value) => {
339
+ if (Array.isArray(value)) {
340
+ if (value.length === 2) {
341
+ const [[key, nestedSemanticObject], status, localEndIndex] = definitionArrayObjectParser(bitString.slice(startIndex), value);
342
+ startIndex += localEndIndex;
343
+ ObjectGenerationOutputStatus.PARSED;
344
+ return [key, nestedSemanticObject];
345
+ } else {
346
+ const [[key, nestedSemanticObject], status, localEndIndex] = methodParser(bitString.slice(startIndex), value);
347
+ startIndex += localEndIndex;
348
+ ObjectGenerationOutputStatus.PARSED;
349
+ return [key, nestedSemanticObject];
350
+ }
351
+ } else {
352
+ const [dataEntry, status, localEndIndex] = dataEntryParser(bitString.slice(startIndex), value);
353
+ startIndex += localEndIndex;
354
+ ObjectGenerationOutputStatus.PARSED;
355
+ return [dataEntry.name, dataEntry];
356
+ }
357
+ })),
358
+ objectGenerationStatus,
359
+ startIndex
360
+ ];
261
361
  };
262
- var internalNestedDataEntryArrayToObject = (definitionArrayObject) => {
263
- return Object.fromEntries(definitionArrayObject.map((value) => {
264
- if (Array.isArray(value)) {
265
- if (value.length === 2)
266
- return [value[0], internalNestedDataEntryArrayToObject(value[1])];
267
- else
268
- return [value[0], internalNestedDataEntryArrayToObject(value[2](value[1]))];
269
- }
270
- return [value.name, { ...value, index: ++currentObjectIndex }];
271
- }));
362
+ var parseUrlMethod = (url, parserVersions) => {
363
+ currentObjectIndex = -1;
364
+ const bitString = parseBase64ToBits(url);
365
+ const version = dataBitsArrayParser(bitString, [DataEntryFactory.createVersion(0, parserVersions.versionBitCount)])[0];
366
+ const versionParser = parserVersions.parsers[version.value];
367
+ if (!versionParser)
368
+ throw new Error(`No parser for version ${version.value}`);
369
+ return parsingDefinitionArrayObject(bitString, versionParser.objectGeneratorParameters)[0];
272
370
  };
273
371
  var parseDownNestedDataDescription = (nestedDataDescription) => {
274
372
  const dataDescriptions = [];
@@ -280,6 +378,12 @@ var parseDownNestedDataDescription = (nestedDataDescription) => {
280
378
  });
281
379
  return dataDescriptions.sort();
282
380
  };
381
+ var getURLForData = (data) => {
382
+ const dataEntryArray = parseDownNestedDataDescription(data);
383
+ const bitstring = dataArrayStringifier(dataEntryArray);
384
+ return parseBitsToBase64(bitstring);
385
+ };
386
+
283
387
  // src/update/floatUpdate.ts
284
388
  var updateValue = (original, update) => {
285
389
  const value = Math.max(Math.min(update.value, original.max), original.min);
@@ -380,11 +484,6 @@ var updateDataEntryObject = (definitionArrayObject, dataArray) => {
380
484
  });
381
485
  return newNestedObject;
382
486
  };
383
- var getDefaultObject = (versionParser, versionindex) => {
384
- if (!versionParser.parsers[versionindex])
385
- throw new Error(`No parser for version ${versionindex} index`);
386
- return nestedDataEntryArrayToObject(versionParser.parsers[versionindex].objectGeneratorParameters);
387
- };
388
487
  var updateDataEntry = (data, newDataEntry, parsersForVersion) => {
389
488
  currentObjectIndex2 = 0;
390
489
  const version = data.version;
@@ -396,6 +495,42 @@ var updateDataEntry = (data, newDataEntry, parsersForVersion) => {
396
495
  const virginDataEntryArray = [correctedDataEntry, ...dataEntryArray];
397
496
  return updateDataEntryObject(versionParser.objectGeneratorParameters, virginDataEntryArray);
398
497
  };
498
+
499
+ // src/objectmap/versionUserMethods.ts
500
+ var createParserObject = (versionArray, versionBitCount, enumSemanticsMapping, attributeSemanticsMapping) => {
501
+ const maxAllowedParsers = getMaxIntegerValueForGivenBitWidth(versionBitCount);
502
+ if (versionArray.length > maxAllowedParsers)
503
+ throw new Error(`Cannot have more than ${maxAllowedParsers} versions`);
504
+ return {
505
+ versionBitCount,
506
+ parsers: versionArray.map((version, index) => ({
507
+ attributeSemanticsMapping: attributeSemanticsMapping ? Array.isArray(attributeSemanticsMapping) ? attributeSemanticsMapping[index] : attributeSemanticsMapping : undefined,
508
+ enumSemanticsMapping: enumSemanticsMapping ? Array.isArray(enumSemanticsMapping) ? enumSemanticsMapping[index] : enumSemanticsMapping : undefined,
509
+ objectGeneratorParameters: parseVersionArrayDefinitionTypeToVersionDefinitionObject(version, index)
510
+ }))
511
+ };
512
+ };
513
+ var parseUrl = (urlSafeBase64, parserVersions) => parseUrlMethod(urlSafeBase64, parserVersions);
514
+ var updateDataEntry2 = (updatedEntry, currentObject, parserVersions) => updateDataEntry(currentObject, updatedEntry, parserVersions.parsers);
515
+ var getURLSafeBase64ForData = (data) => getURLForData(data);
516
+ var internalParseDataEntry = (data, enumSemanticsMapping) => {
517
+ if (data.type === DataType.ENUM && enumSemanticsMapping) {
518
+ const mapping = enumSemanticsMapping[data.name]?.find((entry) => entry.value === data.value);
519
+ if (mapping)
520
+ return mapping.label;
521
+ }
522
+ return data.value;
523
+ };
524
+ var internalStrictSemanticallyNestedValues = (data, enumSemanticsMapping, attributeSemanticsMapping) => Object.fromEntries(Object.entries(data).map(([key, value]) => [
525
+ attributeSemanticsMapping ? attributeSemanticsMapping[key] ?? key : key,
526
+ value.type !== undefined ? internalParseDataEntry(value, enumSemanticsMapping) : internalStrictSemanticallyNestedValues(value, enumSemanticsMapping, attributeSemanticsMapping)
527
+ ]));
528
+ var getSemanticallyNestedValues = (data, parserVersions) => {
529
+ const versionNumber = data.version.value;
530
+ const enumSemanticsMapping = parserVersions.parsers[versionNumber]?.enumSemanticsMapping;
531
+ const attributeSemanticsMapping = parserVersions.parsers[versionNumber]?.attributeSemanticsMapping;
532
+ return internalStrictSemanticallyNestedValues(data, enumSemanticsMapping, attributeSemanticsMapping);
533
+ };
399
534
  // src/utils/interpolateData.ts
400
535
  var interpolateEntryAt = (dataEntry2, t) => {
401
536
  const localT = Math.max(Math.min(1, t), 0);
@@ -429,19 +564,13 @@ var getRelativeValue = (dataEntry2) => {
429
564
  }
430
565
  };
431
566
  export {
432
- valueBitsParser,
433
- updateDataEntry,
434
- parseBitsToBase64,
435
- parseBase64ToBits,
567
+ updateDataEntry2 as updateDataEntry,
568
+ parseUrl,
436
569
  interpolateEntryAt,
570
+ getURLSafeBase64ForData,
571
+ getSemanticallyNestedValues,
437
572
  getRelativeValue,
438
- getDefaultObject,
439
- getBitsCount6 as getBitsCount,
440
- dataEntryCorrecting,
441
- dataBitsStringifier,
442
- dataBitsParser,
443
- dataBitsArrayParser,
444
- dataArrayStringifier,
573
+ createParserObject,
445
574
  SignificandMaxBits,
446
575
  ObjectGenerationOutputStatus,
447
576
  IntegerMaxBits,
@@ -1,2 +1 @@
1
- export * from './versionReading';
2
- export * from './versionUpdate';
1
+ export * from './versionUserMethods';
@@ -11,4 +11,4 @@ export declare const parseNestedContentDataTypeToDefinitionNestedArray: (data: N
11
11
  export declare const parseEnumEntryDataTypeToDefinitionNestedGenerationObject: (data: EnumEntryDataType, name: string, internalPrecedingName?: string) => DefinitionNestedGenerationObject;
12
12
  export declare const parseOptionalEntryDataTypeToDefinitionNestedGenerationObject: (data: OptionalEntryDataType, name: string, internalPrecedingName?: string) => DefinitionNestedGenerationObject;
13
13
  export declare const parseDataEntry: (d: DataEntry, internalPrecedingName?: string) => DataEntry;
14
- export declare const parseVersionArrayDefinitionTypeToVersionDefinitionObject: (v: VersionArrayDefinitionType) => VersionDefinitionObject;
14
+ export declare const parseVersionArrayDefinitionTypeToVersionDefinitionObject: (v: VersionArrayDefinitionType, optionalIndexOverwrite?: number) => VersionDefinitionObject;
@@ -0,0 +1,43 @@
1
+ import { VersionArrayDefinitionType, VersionRangeType, VersionEnumSemantics, ParsersForVersionObject, SemanticlyNestedDataEntry, DataEntry, SemanticlyNestedValues } from '../types';
2
+ /**
3
+ * Method to create version definition objects
4
+ * @param {VersionArrayDefinitionType[]} versionArray - version definition array
5
+ * @param {VersionRangeType} versionBitCount - bit count
6
+ * @param {VersionEnumSemantics[] | VersionEnumSemantics} enumSemanticsMapping - optional semantics mapping for enums. If not given, values will be numbers
7
+ * @param {undefined | Record<string, string> | Record<string, string>[]} attributeSemanticsMapping - optional semantics mapping, if nothing given no semantics will be mapped
8
+ * @returns ParsersForVersionObject
9
+ */
10
+ export declare const createParserObject: (versionArray: VersionArrayDefinitionType[], versionBitCount: VersionRangeType, enumSemanticsMapping?: VersionEnumSemantics[] | VersionEnumSemantics, attributeSemanticsMapping?: Record<string, string>[] | Record<string, string>) => ParsersForVersionObject;
11
+ /** the data object needs to be accesible in 3 versions.
12
+ *
13
+ * 1. As a semanticly nested object (primary data structure, also used for UI)
14
+ * 2. As an array of entries (derived from semanticly nested object, to translate and from to bitstream)
15
+ * 3. As an object with all the data entry information stripped (derived from semanticly nested object, read only)
16
+ */
17
+ /**
18
+ * Construct SemanticlyNestedDataEntry
19
+ * @param urlSafeBase64 - the url to parse
20
+ * @param parserVersions - the object containing the version parsers
21
+ * @returns the parsed SemanticlyNestedDataEntry
22
+ */
23
+ export declare const parseUrl: (urlSafeBase64: string, parserVersions: ParsersForVersionObject) => SemanticlyNestedDataEntry;
24
+ /**
25
+ * Update a data entry in a SemanticlyNestedDataEntry
26
+ * @param {DataEntry} updatedEntry - the updated data entry
27
+ * @param {SemanticlyNestedDataEntry} currentObject - the current Data Object
28
+ * @param {ParsersForVersionObject} parserVersions - the object containing the version parsers
29
+ * @returns {SemanticlyNestedDataEntry} - the updated SemanticlyNestedDataEntry
30
+ */
31
+ export declare const updateDataEntry: (updatedEntry: DataEntry, currentObject: SemanticlyNestedDataEntry, parserVersions: ParsersForVersionObject) => SemanticlyNestedDataEntry;
32
+ /**
33
+ * Method to get the URLSafeBase64 representation of a SemanticlyNestedDataEntry
34
+ * @param {SemanticlyNestedDataEntry} data - the data object
35
+ * @returns {string} - the urlSafeBase64 representation
36
+ */
37
+ export declare const getURLSafeBase64ForData: (data: SemanticlyNestedDataEntry) => string;
38
+ /**
39
+ * Method for getting the basic object for a given semanticly nested data entry
40
+ * @param {SemanticlyNestedDataEntry} data - the data object
41
+ * @returns {SemanticlyNestedDataEntry} - the basic object
42
+ */
43
+ export declare const getSemanticallyNestedValues: (data: SemanticlyNestedDataEntry, parserVersions: ParsersForVersionObject) => SemanticlyNestedValues;
@@ -7,5 +7,4 @@ export type NonEmptyValidEntryArrayType = [SingleLevelContentType, ...SingleLeve
7
7
  export type OptionalEntryDataType = [boolean, NonEmptyValidEntryArrayType, []] | [boolean, [], NonEmptyValidEntryArrayType];
8
8
  export type EnumEntryDataType = [number, NonEmptyValidEntryArrayType, NonEmptyValidEntryArrayType, ...SingleLevelContentType[][]];
9
9
  export type VersionArrayDefinitionType = [VersionDataEntry, ...SingleLevelContentType[]];
10
- export declare const INDEX_DELIMETER = "$";
11
10
  export declare const NAME_DELIMETER = "_";
@@ -17,5 +17,6 @@ export type EnumDataEntry = Prettify<EnumData & DataDescription>;
17
17
  export type FloatDataEntry = Prettify<FloatData & DataDescription>;
18
18
  export type VersionDataEntry = Prettify<VersionData & DataDescription>;
19
19
  export type DataEntry = BooleanDataEntry | IntDataEntry | EnumDataEntry | FloatDataEntry | VersionDataEntry;
20
+ export type ProtectedAttributeNames = Prettify<keyof BooleanDataEntry | keyof IntDataEntry | keyof EnumDataEntry | keyof FloatDataEntry | keyof VersionDataEntry>;
20
21
  export type DataEntryArray = DataEntry[];
21
22
  export {};
@@ -2,3 +2,6 @@ import { DataEntry } from './dataEntry';
2
2
  export type SemanticlyNestedDataEntry = {
3
3
  [key: string]: SemanticlyNestedDataEntry | DataEntry;
4
4
  };
5
+ export type SemanticlyNestedValues = {
6
+ [key: string]: SemanticlyNestedValues | boolean | number | string;
7
+ };
@@ -22,7 +22,8 @@ export type VersionEnumSemantics = {
22
22
  }[];
23
23
  };
24
24
  export type ParserForVersion = {
25
- versionEnumSemantics?: VersionEnumSemantics;
25
+ enumSemanticsMapping?: VersionEnumSemantics;
26
+ attributeSemanticsMapping?: Record<string, string>;
26
27
  objectGeneratorParameters: VersionDefinitionObject;
27
28
  };
28
29
  export type ParsersForVersionObject = {
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "dist/*"
8
8
  ],
9
9
  "type": "module",
10
- "version": "0.1.6",
10
+ "version": "0.1.8",
11
11
  "author": "Jonas Ward",
12
12
  "description": "Library for creating web safe base64 objects with custom bith widths and dynamic values.",
13
13
  "scripts": {