@osano/osano-cmp-react-native 0.9.0 → 0.10.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/lib/typescript/src/iab/gpp/api.d.ts +28 -0
- package/lib/typescript/src/iab/gpp/api.d.ts.map +1 -0
- package/lib/typescript/src/iab/gpp/consent.d.ts +24 -0
- package/lib/typescript/src/iab/gpp/consent.d.ts.map +1 -0
- package/lib/typescript/src/iab/gpp/constants.d.ts +37 -0
- package/lib/typescript/src/iab/gpp/constants.d.ts.map +1 -0
- package/lib/typescript/src/iab/gpp/encoders/AbstractBase64UrlEncoder.d.ts +28 -0
- package/lib/typescript/src/iab/gpp/encoders/AbstractBase64UrlEncoder.d.ts.map +1 -0
- package/lib/typescript/src/iab/gpp/encoders/BooleanEncoder.d.ts +34 -0
- package/lib/typescript/src/iab/gpp/encoders/BooleanEncoder.d.ts.map +1 -0
- package/lib/typescript/src/iab/gpp/encoders/CompressedBase64UrlEncoder.d.ts +28 -0
- package/lib/typescript/src/iab/gpp/encoders/CompressedBase64UrlEncoder.d.ts.map +1 -0
- package/lib/typescript/src/iab/gpp/encoders/DatetimeEncoder.d.ts +28 -0
- package/lib/typescript/src/iab/gpp/encoders/DatetimeEncoder.d.ts.map +1 -0
- package/lib/typescript/src/iab/gpp/encoders/EncodableOptimizedFixedRange.d.ts +16 -0
- package/lib/typescript/src/iab/gpp/encoders/EncodableOptimizedFixedRange.d.ts.map +1 -0
- package/lib/typescript/src/iab/gpp/encoders/FibonacciIntegerEncoder.d.ts +28 -0
- package/lib/typescript/src/iab/gpp/encoders/FibonacciIntegerEncoder.d.ts.map +1 -0
- package/lib/typescript/src/iab/gpp/encoders/FibonacciIntegerRangeEncoder.d.ts +28 -0
- package/lib/typescript/src/iab/gpp/encoders/FibonacciIntegerRangeEncoder.d.ts.map +1 -0
- package/lib/typescript/src/iab/gpp/encoders/FixedBitfieldEncoder.d.ts +28 -0
- package/lib/typescript/src/iab/gpp/encoders/FixedBitfieldEncoder.d.ts.map +1 -0
- package/lib/typescript/src/iab/gpp/encoders/FixedIdBitMapEncoder.d.ts +6 -0
- package/lib/typescript/src/iab/gpp/encoders/FixedIdBitMapEncoder.d.ts.map +1 -0
- package/lib/typescript/src/iab/gpp/encoders/FixedIntegerEncoder.d.ts +28 -0
- package/lib/typescript/src/iab/gpp/encoders/FixedIntegerEncoder.d.ts.map +1 -0
- package/lib/typescript/src/iab/gpp/encoders/FixedIntegerListEncoder.d.ts +28 -0
- package/lib/typescript/src/iab/gpp/encoders/FixedIntegerListEncoder.d.ts.map +1 -0
- package/lib/typescript/src/iab/gpp/encoders/FixedIntegerRangeEncoder.d.ts +28 -0
- package/lib/typescript/src/iab/gpp/encoders/FixedIntegerRangeEncoder.d.ts.map +1 -0
- package/lib/typescript/src/iab/gpp/encoders/FixedStringEncoder.d.ts +26 -0
- package/lib/typescript/src/iab/gpp/encoders/FixedStringEncoder.d.ts.map +1 -0
- package/lib/typescript/src/iab/gpp/encoders/TraditionalBase64UrlEncoder.d.ts +28 -0
- package/lib/typescript/src/iab/gpp/encoders/TraditionalBase64UrlEncoder.d.ts.map +1 -0
- package/lib/typescript/src/iab/gpp/encoders/errors.d.ts +19 -0
- package/lib/typescript/src/iab/gpp/encoders/errors.d.ts.map +1 -0
- package/lib/typescript/src/iab/gpp/encoders/index.d.ts +16 -0
- package/lib/typescript/src/iab/gpp/encoders/index.d.ts.map +1 -0
- package/lib/typescript/src/iab/gpp/encoders/types.d.ts +5 -0
- package/lib/typescript/src/iab/gpp/encoders/types.d.ts.map +1 -0
- package/lib/typescript/src/iab/gpp/index.d.ts +10 -0
- package/lib/typescript/src/iab/gpp/index.d.ts.map +1 -0
- package/lib/typescript/src/iab/gpp/reducer.d.ts +6 -0
- package/lib/typescript/src/iab/gpp/reducer.d.ts.map +1 -0
- package/lib/typescript/src/iab/gpp/selectors.d.ts +6 -0
- package/lib/typescript/src/iab/gpp/selectors.d.ts.map +1 -0
- package/lib/typescript/src/iab/gpp/types.d.ts +3 -0
- package/lib/typescript/src/iab/gpp/types.d.ts.map +1 -0
- package/lib/typescript/src/iab/gpp/v1/constants.d.ts +9 -0
- package/lib/typescript/src/iab/gpp/v1/constants.d.ts.map +1 -0
- package/lib/typescript/src/iab/gpp/v1/index.d.ts +19 -0
- package/lib/typescript/src/iab/gpp/v1/index.d.ts.map +1 -0
- package/lib/typescript/src/iab/usp/api.d.ts +4 -0
- package/lib/typescript/src/iab/usp/api.d.ts.map +1 -0
- package/lib/typescript/src/iab/usp/consent.d.ts +13 -0
- package/lib/typescript/src/iab/usp/consent.d.ts.map +1 -0
- package/lib/typescript/src/iab/usp/constants.d.ts +77 -0
- package/lib/typescript/src/iab/usp/constants.d.ts.map +1 -0
- package/lib/typescript/src/iab/usp/index.d.ts +10 -0
- package/lib/typescript/src/iab/usp/index.d.ts.map +1 -0
- package/lib/typescript/src/iab/usp/reducer.d.ts +13 -0
- package/lib/typescript/src/iab/usp/reducer.d.ts.map +1 -0
- package/lib/typescript/src/iab/usp/selectors.d.ts +9 -0
- package/lib/typescript/src/iab/usp/selectors.d.ts.map +1 -0
- package/lib/typescript/src/iab/usp/types.d.ts +5 -0
- package/lib/typescript/src/iab/usp/types.d.ts.map +1 -0
- package/lib/typescript/src/iab/usp/v1/constants.d.ts +9 -0
- package/lib/typescript/src/iab/usp/v1/constants.d.ts.map +1 -0
- package/lib/typescript/src/iab/usp/v1/index.d.ts +16 -0
- package/lib/typescript/src/iab/usp/v1/index.d.ts.map +1 -0
- package/package.json +2 -6
- package/src/iab/gpp/api.js +253 -0
- package/src/iab/gpp/consent.js +114 -0
- package/src/iab/gpp/constants.js +49 -0
- package/src/iab/gpp/encoders/AbstractBase64UrlEncoder.ts +89 -0
- package/src/iab/gpp/encoders/BooleanEncoder.ts +39 -0
- package/src/iab/gpp/encoders/CompressedBase64UrlEncoder.ts +41 -0
- package/src/iab/gpp/encoders/DatetimeEncoder.ts +46 -0
- package/src/iab/gpp/encoders/EncodableOptimizedFixedRange.ts +213 -0
- package/src/iab/gpp/encoders/FibonacciIntegerEncoder.ts +81 -0
- package/src/iab/gpp/encoders/FibonacciIntegerRangeEncoder.ts +122 -0
- package/src/iab/gpp/encoders/FixedBitfieldEncoder.ts +59 -0
- package/src/iab/gpp/encoders/FixedIdBitMapEncoder.ts +30 -0
- package/src/iab/gpp/encoders/FixedIntegerEncoder.ts +61 -0
- package/src/iab/gpp/encoders/FixedIntegerListEncoder.ts +87 -0
- package/src/iab/gpp/encoders/FixedIntegerRangeEncoder.ts +102 -0
- package/src/iab/gpp/encoders/FixedStringEncoder.ts +74 -0
- package/src/iab/gpp/encoders/LICENSE-IABTechLab +176 -0
- package/src/iab/gpp/encoders/TraditionalBase64UrlEncoder.ts +38 -0
- package/src/iab/gpp/encoders/errors.ts +41 -0
- package/src/iab/gpp/encoders/index.ts +15 -0
- package/src/iab/gpp/encoders/types.ts +5 -0
- package/src/iab/gpp/index.js +9 -0
- package/src/iab/gpp/reducer.js +7 -0
- package/src/iab/gpp/selectors.js +21 -0
- package/src/iab/gpp/types.ts +3 -0
- package/src/iab/gpp/v1/constants.js +7 -0
- package/src/iab/gpp/v1/index.js +73 -0
- package/src/iab/usp/api.js +56 -0
- package/src/iab/usp/consent.js +150 -0
- package/src/iab/usp/constants.js +40 -0
- package/src/iab/usp/index.js +9 -0
- package/src/iab/usp/reducer.js +107 -0
- package/src/iab/usp/selectors.js +31 -0
- package/src/iab/usp/types.ts +4 -0
- package/src/iab/usp/v1/constants.js +10 -0
- package/src/iab/usp/v1/index.js +54 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Comment-out the sections that we do not implement as they aren't necessary
|
|
2
|
+
// for functionality.
|
|
3
|
+
export const SECTIONS = {
|
|
4
|
+
// tcfeuv1: 1,
|
|
5
|
+
tcfeuv2: 2,
|
|
6
|
+
// GPP header section is ID 3
|
|
7
|
+
// GPP signal integrity section is ID 4
|
|
8
|
+
tcfcav1: 5,
|
|
9
|
+
uspv1: 6,
|
|
10
|
+
// usnatv1: 7,
|
|
11
|
+
// uscav1: 8,
|
|
12
|
+
// usvav1: 9,
|
|
13
|
+
// uscov1: 10,
|
|
14
|
+
// usutv1: 11,
|
|
15
|
+
// usctv1: 12,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* GPP's defined CMP status codes
|
|
20
|
+
* @enum {string}
|
|
21
|
+
*/
|
|
22
|
+
export const CmpStatusCodes = {
|
|
23
|
+
STUB: 'stub',
|
|
24
|
+
LOADED: 'loaded',
|
|
25
|
+
ERROR: 'error',
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* GPP's defined CMP display status codes
|
|
30
|
+
* @enum {string}
|
|
31
|
+
*/
|
|
32
|
+
export const CmpDisplayStatusCodes = {
|
|
33
|
+
VISIBLE: 'visible',
|
|
34
|
+
HIDDEN: 'hidden',
|
|
35
|
+
DISABLED: 'disabled',
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The GPP API's events
|
|
40
|
+
* @enum {string}
|
|
41
|
+
*/
|
|
42
|
+
export const EventNames = {
|
|
43
|
+
LISTENER_REGISTERED: 'listenerRegistered',
|
|
44
|
+
LISTENER_REMOVED: 'listenerRemoved',
|
|
45
|
+
CMP_STATUS_CHANGED: 'cmpStatus',
|
|
46
|
+
CMP_DISPLAY_STATUS_CHANGED: 'cmpDisplayStatus',
|
|
47
|
+
ERROR: 'error',
|
|
48
|
+
SECTION_CHANGED: 'sectionChange',
|
|
49
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapted from IABTechLab's GPP JavaScript Reference Implementation
|
|
3
|
+
*
|
|
4
|
+
* https://github.com/IABTechLab/iabgpp-es/blob/42060d7ac2b6d0ee70fc1b5bcd33fc447bf5123c/modules/cmpapi/src/encoder/datatype/encoder/AbstractBase64UrlEncoder.ts
|
|
5
|
+
*
|
|
6
|
+
* @license
|
|
7
|
+
* Copyright 2023 IABTechLab
|
|
8
|
+
*
|
|
9
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
10
|
+
* use this file except in compliance with the License. You may obtain a copy of
|
|
11
|
+
* the License at
|
|
12
|
+
*
|
|
13
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
14
|
+
*
|
|
15
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
16
|
+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
17
|
+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
18
|
+
* License for the specific language governing permissions and limitations under
|
|
19
|
+
* the License.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { InvalidBase64UrlError, InvalidBitStringError } from './errors';
|
|
23
|
+
import {
|
|
24
|
+
decode as intDecode,
|
|
25
|
+
encode as intEncode,
|
|
26
|
+
} from './FixedIntegerEncoder';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Base 64 URL character set. Different from standard Base64 char set in that
|
|
30
|
+
* '+' and '/' are replaced with '-' and '_'.
|
|
31
|
+
*/
|
|
32
|
+
const DICT = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
|
|
33
|
+
// prettier-ignore
|
|
34
|
+
const REVERSE_DICT: Record<string,number> = Object.freeze({
|
|
35
|
+
0: 52, 1: 53, 2: 54, 3: 55, 4: 56, 5: 57, 6: 58, 7: 59, 8: 60, 9: 61, A: 0,
|
|
36
|
+
B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7, I: 8, J: 9, K: 10, L: 11, M: 12,
|
|
37
|
+
N: 13, O: 14, P: 15, Q: 16, R: 17, S: 18, T: 19, U: 20, V: 21, W: 22, X: 23,
|
|
38
|
+
Y: 24, Z: 25, a: 26, b: 27, c: 28, d: 29, e: 30, f: 31, g: 32, h: 33, i: 34,
|
|
39
|
+
j: 35, k: 36, l: 37, m: 38, n: 39, o: 40, p: 41, q: 42, r: 43, s: 44, t: 45,
|
|
40
|
+
u: 46, v: 47, w: 48, x: 49, y: 50, z: 51, '-': 62, _: 63,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
export const makeEncode =
|
|
44
|
+
(pad: (str: string) => string) => (bitString: string) => {
|
|
45
|
+
// should only be 0 or 1
|
|
46
|
+
if (!/^[01]*$/.test(bitString)) {
|
|
47
|
+
throw new InvalidBitStringError(bitString);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
bitString = pad(bitString);
|
|
51
|
+
|
|
52
|
+
let str = '';
|
|
53
|
+
|
|
54
|
+
let index = 0;
|
|
55
|
+
while (index <= bitString.length - 6) {
|
|
56
|
+
const s = bitString.substring(index, index + 6);
|
|
57
|
+
const n = intDecode(s);
|
|
58
|
+
const c = DICT.charAt(n);
|
|
59
|
+
str += c;
|
|
60
|
+
|
|
61
|
+
index += 6;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return str;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const decode = (str: string) => {
|
|
68
|
+
// should contain only characters from the base64url set
|
|
69
|
+
if (!/^[A-Za-z0-9\-_]*$/.test(str)) {
|
|
70
|
+
throw new InvalidBase64UrlError(str);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
let bitString = '';
|
|
74
|
+
|
|
75
|
+
for (let i = 0; i < str.length; i++) {
|
|
76
|
+
const c = str.charAt(i);
|
|
77
|
+
|
|
78
|
+
const n = REVERSE_DICT[`${c}`]!;
|
|
79
|
+
const s = intEncode(n, 6);
|
|
80
|
+
bitString += s;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return bitString;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export default {
|
|
87
|
+
decode,
|
|
88
|
+
makeEncode,
|
|
89
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapted from IABTechLab's GPP JavaScript Reference Implementation
|
|
3
|
+
*
|
|
4
|
+
* https://github.com/IABTechLab/iabgpp-es/blob/42060d7ac2b6d0ee70fc1b5bcd33fc447bf5123c/modules/cmpapi/src/encoder/datatype/encoder/BooleanEncoder.ts
|
|
5
|
+
*
|
|
6
|
+
* @license
|
|
7
|
+
* Copyright 2023 IABTechLab
|
|
8
|
+
*
|
|
9
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
10
|
+
* use this file except in compliance with the License. You may obtain a copy of
|
|
11
|
+
* the License at
|
|
12
|
+
*
|
|
13
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
14
|
+
*
|
|
15
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
16
|
+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
17
|
+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
18
|
+
* License for the specific language governing permissions and limitations under
|
|
19
|
+
* the License.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* encode a TCString boolean
|
|
24
|
+
*/
|
|
25
|
+
export const encode = (bool: boolean) => {
|
|
26
|
+
return bool ? '1' : '0';
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* decode a TCString boolean
|
|
30
|
+
*/
|
|
31
|
+
export const decode = (bitString: string) => {
|
|
32
|
+
// fewer operations than !!parseInt(value, 2)
|
|
33
|
+
return bitString === '1';
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export default {
|
|
37
|
+
decode,
|
|
38
|
+
encode,
|
|
39
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapted from IABTechLab's GPP JavaScript Reference Implementation
|
|
3
|
+
*
|
|
4
|
+
* https://github.com/IABTechLab/iabgpp-es/blob/42060d7ac2b6d0ee70fc1b5bcd33fc447bf5123c/modules/cmpapi/src/encoder/datatype/encoder/CompressedBase64UrlEncoder.ts
|
|
5
|
+
*
|
|
6
|
+
* @license
|
|
7
|
+
* Copyright 2023 IABTechLab
|
|
8
|
+
*
|
|
9
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
10
|
+
* use this file except in compliance with the License. You may obtain a copy of
|
|
11
|
+
* the License at
|
|
12
|
+
*
|
|
13
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
14
|
+
*
|
|
15
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
16
|
+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
17
|
+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
18
|
+
* License for the specific language governing permissions and limitations under
|
|
19
|
+
* the License.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { decode, makeEncode } from './AbstractBase64UrlEncoder';
|
|
23
|
+
|
|
24
|
+
const pad = (bitString: string) => {
|
|
25
|
+
while (bitString.length % 8 > 0) {
|
|
26
|
+
bitString += '0';
|
|
27
|
+
}
|
|
28
|
+
while (bitString.length % 6 > 0) {
|
|
29
|
+
bitString += '0';
|
|
30
|
+
}
|
|
31
|
+
return bitString;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const encode = makeEncode(pad);
|
|
35
|
+
|
|
36
|
+
export { decode } from './AbstractBase64UrlEncoder';
|
|
37
|
+
|
|
38
|
+
export default {
|
|
39
|
+
decode,
|
|
40
|
+
encode,
|
|
41
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapted from IABTechLab's GPP JavaScript Reference Implementation
|
|
3
|
+
*
|
|
4
|
+
* https://github.com/IABTechLab/iabgpp-es/blob/42060d7ac2b6d0ee70fc1b5bcd33fc447bf5123c/modules/cmpapi/src/encoder/datatype/encoder/DatetimeEncoder.ts
|
|
5
|
+
*
|
|
6
|
+
* @license
|
|
7
|
+
* Copyright 2023 IABTechLab
|
|
8
|
+
*
|
|
9
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
10
|
+
* use this file except in compliance with the License. You may obtain a copy of
|
|
11
|
+
* the License at
|
|
12
|
+
*
|
|
13
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
14
|
+
*
|
|
15
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
16
|
+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
17
|
+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
18
|
+
* License for the specific language governing permissions and limitations under
|
|
19
|
+
* the License.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import {
|
|
23
|
+
decode as intDecode,
|
|
24
|
+
encode as intEncode,
|
|
25
|
+
} from './FixedIntegerEncoder';
|
|
26
|
+
|
|
27
|
+
export const encode = (date: Date | number, numBits: number = 36) => {
|
|
28
|
+
let deciseconds: number;
|
|
29
|
+
if (date instanceof Date) {
|
|
30
|
+
deciseconds = Math.round(date.getTime() / 100);
|
|
31
|
+
} else {
|
|
32
|
+
deciseconds = date;
|
|
33
|
+
}
|
|
34
|
+
return intEncode(deciseconds, numBits);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const decode = (bitString: string) => {
|
|
38
|
+
const date = new Date(intDecode(bitString) * 100);
|
|
39
|
+
|
|
40
|
+
return date;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export default {
|
|
44
|
+
decode,
|
|
45
|
+
encode,
|
|
46
|
+
};
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
// This is our own implementation but is analogous to
|
|
2
|
+
// https://github.com/IABTechLab/iabgpp-es/blob/42060d7ac2b6d0ee70fc1b5bcd33fc447bf5123c/modules/cmpapi/src/encoder/datatype/EncodableOptimizedFixedRange.ts
|
|
3
|
+
|
|
4
|
+
import BooleanEncoder from './BooleanEncoder';
|
|
5
|
+
import { default as FixedIdBitMapEncoder } from './FixedIdBitMapEncoder';
|
|
6
|
+
import IntEncoder from './FixedIntegerEncoder';
|
|
7
|
+
|
|
8
|
+
export const BitLength = {
|
|
9
|
+
encodingType: 1,
|
|
10
|
+
maxId: 16,
|
|
11
|
+
numEntries: 12,
|
|
12
|
+
singleOrRange: 1,
|
|
13
|
+
vendorId: 16,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const HEADER_LENGTH = BitLength.maxId + BitLength.encodingType;
|
|
17
|
+
const RANGE_MINIMUM_LENGTH =
|
|
18
|
+
BitLength.vendorId + BitLength.singleOrRange + BitLength.numEntries;
|
|
19
|
+
|
|
20
|
+
const ENCODING_TYPE = {
|
|
21
|
+
FIELD: 0,
|
|
22
|
+
RANGE: 1,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const buildRangeEncoding = (ranges: (number | string)[][]) => {
|
|
26
|
+
// describe the number of entries to follow
|
|
27
|
+
const numEntries = ranges.length;
|
|
28
|
+
let rangeString = IntEncoder.encode(numEntries, BitLength.numEntries);
|
|
29
|
+
|
|
30
|
+
// each range
|
|
31
|
+
ranges.forEach((range /*: number[]*/) => {
|
|
32
|
+
// is this range a single?
|
|
33
|
+
const single = range.length === 1;
|
|
34
|
+
|
|
35
|
+
// first is the indicator of whether this is a single id or range (two)
|
|
36
|
+
// 0 is single and range is 1
|
|
37
|
+
rangeString += BooleanEncoder.encode(!single);
|
|
38
|
+
|
|
39
|
+
// second is the first (or only) vendorId
|
|
40
|
+
rangeString += IntEncoder.encode(`${range[0]}`, BitLength.vendorId);
|
|
41
|
+
|
|
42
|
+
if (!single) {
|
|
43
|
+
// add the second id if it exists
|
|
44
|
+
rangeString += IntEncoder.encode(`${range[1]}`, BitLength.vendorId);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
return rangeString;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const encode = (value: Record<number, boolean>) => {
|
|
52
|
+
// Filter out any falsey values and convert the keys to numbers
|
|
53
|
+
const vendorIds = Object.entries(value)
|
|
54
|
+
.filter(([, v]) => !!v)
|
|
55
|
+
.map(([id]) => {
|
|
56
|
+
const parsedId = parseInt(id, 10);
|
|
57
|
+
if (isNaN(parsedId) || parsedId < 1 || /^\d+$/.test(id) === false) {
|
|
58
|
+
throw new Error(`Invalid vendor ID: ${id}`);
|
|
59
|
+
}
|
|
60
|
+
return parsedId;
|
|
61
|
+
});
|
|
62
|
+
const vendorSet = new Set(vendorIds);
|
|
63
|
+
const maxId = Math.max(0, ...vendorIds);
|
|
64
|
+
// collectors for range encoding
|
|
65
|
+
const ranges = []; // : number[][]
|
|
66
|
+
let range = []; // : number[]
|
|
67
|
+
|
|
68
|
+
// bit field will be just the encoded value of the ID corresponding to the
|
|
69
|
+
// position in the bit field
|
|
70
|
+
let bitField = '';
|
|
71
|
+
// A range is a minimum of 29 bits, so if the max vendor ID in this value
|
|
72
|
+
// is less than that then we know that a bitfield encoding will be shorter
|
|
73
|
+
// than any range encoding.
|
|
74
|
+
let rangeIsSmaller = maxId > RANGE_MINIMUM_LENGTH;
|
|
75
|
+
|
|
76
|
+
const bitFieldLength = HEADER_LENGTH + maxId;
|
|
77
|
+
|
|
78
|
+
// grows as we add to the range
|
|
79
|
+
let rangeLength = HEADER_LENGTH + BitLength.numEntries;
|
|
80
|
+
|
|
81
|
+
for (let vendorId = 1; vendorId <= maxId; vendorId++) {
|
|
82
|
+
const vendorIsOn = vendorSet.has(vendorId);
|
|
83
|
+
|
|
84
|
+
// build our bitfield no matter what
|
|
85
|
+
bitField += BooleanEncoder.encode(vendorIsOn);
|
|
86
|
+
|
|
87
|
+
// For each vendor ID up to maxId, we're re-evaluating whether the range
|
|
88
|
+
// grows larger than the bitfield. If it does, we'll abandon building
|
|
89
|
+
// the range
|
|
90
|
+
rangeIsSmaller = rangeIsSmaller && rangeLength < bitFieldLength;
|
|
91
|
+
if (rangeIsSmaller && vendorIsOn) {
|
|
92
|
+
const isEndOfRange = !vendorSet.has(vendorId + 1);
|
|
93
|
+
if (isEndOfRange) {
|
|
94
|
+
range.push(vendorId);
|
|
95
|
+
|
|
96
|
+
// add to the range length the additional vendorId
|
|
97
|
+
rangeLength += BitLength.vendorId;
|
|
98
|
+
|
|
99
|
+
// store the array in our bigger array
|
|
100
|
+
ranges.push(range);
|
|
101
|
+
|
|
102
|
+
// clear the array for the next range
|
|
103
|
+
range = [];
|
|
104
|
+
} else if (range.length === 0) {
|
|
105
|
+
// this is the first value for this range
|
|
106
|
+
range.push(vendorId);
|
|
107
|
+
|
|
108
|
+
// update our count with new range overhead
|
|
109
|
+
rangeLength += BitLength.singleOrRange;
|
|
110
|
+
rangeLength += BitLength.vendorId;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
rangeIsSmaller = rangeIsSmaller && rangeLength < bitFieldLength;
|
|
116
|
+
|
|
117
|
+
// since both encodings need the maxId, start with that
|
|
118
|
+
const encodedMaxId = IntEncoder.encode(maxId, BitLength.maxId);
|
|
119
|
+
return (
|
|
120
|
+
encodedMaxId +
|
|
121
|
+
(rangeIsSmaller
|
|
122
|
+
? ENCODING_TYPE.RANGE.toString() + buildRangeEncoding(ranges)
|
|
123
|
+
: ENCODING_TYPE.FIELD.toString() + bitField)
|
|
124
|
+
);
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const decode = (bitString: string) => {
|
|
128
|
+
if (!bitString) {
|
|
129
|
+
return { bitLength: 0, value: {} };
|
|
130
|
+
}
|
|
131
|
+
let index = 0;
|
|
132
|
+
|
|
133
|
+
const maxId = IntEncoder.decode(
|
|
134
|
+
bitString.substr(index, BitLength.maxId),
|
|
135
|
+
BitLength.maxId,
|
|
136
|
+
);
|
|
137
|
+
index += BitLength.maxId;
|
|
138
|
+
const encodingType = IntEncoder.decode(
|
|
139
|
+
bitString.charAt(index),
|
|
140
|
+
BitLength.encodingType,
|
|
141
|
+
);
|
|
142
|
+
index += BitLength.encodingType;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Range is handled in batches so we'll need a different decoding scheme
|
|
146
|
+
*/
|
|
147
|
+
if (encodingType === ENCODING_TYPE.RANGE) {
|
|
148
|
+
const vendorIds = new Set();
|
|
149
|
+
|
|
150
|
+
const numEntries = IntEncoder.decode(
|
|
151
|
+
bitString.substr(index, BitLength.numEntries),
|
|
152
|
+
BitLength.numEntries,
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
index += BitLength.numEntries;
|
|
156
|
+
|
|
157
|
+
// loop through each group of entries
|
|
158
|
+
for (let i = 0; i < numEntries; i++) {
|
|
159
|
+
// Ranges can represent a single id or a range of ids.
|
|
160
|
+
const isIdRange = BooleanEncoder.decode(bitString.charAt(index));
|
|
161
|
+
|
|
162
|
+
index += BitLength.singleOrRange;
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* regardless of whether or not it's a single entry or range, the next
|
|
166
|
+
* set of bits is a vendor ID
|
|
167
|
+
*/
|
|
168
|
+
const firstId = IntEncoder.decode(
|
|
169
|
+
bitString.substr(index, BitLength.vendorId),
|
|
170
|
+
BitLength.vendorId,
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
index += BitLength.vendorId;
|
|
174
|
+
|
|
175
|
+
// if it's a range, the next set of bits is the second id
|
|
176
|
+
if (isIdRange) {
|
|
177
|
+
const secondId = IntEncoder.decode(
|
|
178
|
+
bitString.substr(index, BitLength.vendorId),
|
|
179
|
+
BitLength.vendorId,
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
index += BitLength.vendorId;
|
|
183
|
+
|
|
184
|
+
// we'll need to set or unset all the vendor ids between the first and second
|
|
185
|
+
for (let j = firstId; j <= secondId; j++) {
|
|
186
|
+
vendorIds.add(j);
|
|
187
|
+
}
|
|
188
|
+
} else {
|
|
189
|
+
vendorIds.add(firstId);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const decodedValue: Record<number, boolean> = {};
|
|
194
|
+
for (let vendorId = 1; vendorId <= maxId; vendorId++) {
|
|
195
|
+
decodedValue[vendorId] = vendorIds.has(vendorId);
|
|
196
|
+
}
|
|
197
|
+
return { bitLength: index, value: decodedValue };
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Bitfield decoding
|
|
201
|
+
const bitField = bitString.substr(index, maxId);
|
|
202
|
+
|
|
203
|
+
index += maxId;
|
|
204
|
+
return {
|
|
205
|
+
bitLength: index,
|
|
206
|
+
value: FixedIdBitMapEncoder.decode(bitField, maxId),
|
|
207
|
+
};
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
export default {
|
|
211
|
+
decode,
|
|
212
|
+
encode,
|
|
213
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapted from IABTechLab's GPP JavaScript Reference Implementation
|
|
3
|
+
*
|
|
4
|
+
* https://github.com/IABTechLab/iabgpp-es/blob/42060d7ac2b6d0ee70fc1b5bcd33fc447bf5123c/modules/cmpapi/src/encoder/datatype/encoder/FibonacciIntegerEncoder.ts
|
|
5
|
+
*
|
|
6
|
+
* @license
|
|
7
|
+
* Copyright 2023 IABTechLab
|
|
8
|
+
*
|
|
9
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
10
|
+
* use this file except in compliance with the License. You may obtain a copy of
|
|
11
|
+
* the License at
|
|
12
|
+
*
|
|
13
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
14
|
+
*
|
|
15
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
16
|
+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
17
|
+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
18
|
+
* License for the specific language governing permissions and limitations under
|
|
19
|
+
* the License.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
export const encode = (value: number) => {
|
|
23
|
+
const fib = [];
|
|
24
|
+
if (value >= 1) {
|
|
25
|
+
fib.push(1);
|
|
26
|
+
|
|
27
|
+
if (value >= 2) {
|
|
28
|
+
fib.push(2);
|
|
29
|
+
|
|
30
|
+
let i = 2;
|
|
31
|
+
while (value >= fib[i - 1]! + fib[i - 2]!) {
|
|
32
|
+
fib.push(fib[i - 1]! + fib[i - 2]!);
|
|
33
|
+
i++;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
let bitString = '1';
|
|
39
|
+
for (let i = fib.length - 1; i >= 0; i--) {
|
|
40
|
+
const f = fib[i]!;
|
|
41
|
+
if (value >= f) {
|
|
42
|
+
bitString = '1' + bitString;
|
|
43
|
+
value -= f;
|
|
44
|
+
} else {
|
|
45
|
+
bitString = '0' + bitString;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return bitString;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const decode = (bitString: string) => {
|
|
53
|
+
if (!/^[01]*11$/.test(bitString)) {
|
|
54
|
+
throw new Error('Invalid bit string');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let value = 0;
|
|
58
|
+
|
|
59
|
+
const fib: number[] = [];
|
|
60
|
+
for (let i = 0; i < bitString.length - 1; i++) {
|
|
61
|
+
if (i === 0) {
|
|
62
|
+
fib.push(1);
|
|
63
|
+
} else if (i === 1) {
|
|
64
|
+
fib.push(2);
|
|
65
|
+
} else {
|
|
66
|
+
fib.push(fib[i - 1]! + fib[i - 2]!);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
for (let i = 0; i < bitString.length - 1; i++) {
|
|
71
|
+
if (bitString.charAt(i) === '1') {
|
|
72
|
+
value += fib[i]!;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return value;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export default {
|
|
79
|
+
decode,
|
|
80
|
+
encode,
|
|
81
|
+
};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapted from IABTechLab's GPP JavaScript Reference Implementation
|
|
3
|
+
*
|
|
4
|
+
* https://github.com/IABTechLab/iabgpp-es/blob/42060d7ac2b6d0ee70fc1b5bcd33fc447bf5123c/modules/cmpapi/src/encoder/datatype/encoder/FibonacciIntegerRangeEncoder.ts
|
|
5
|
+
*
|
|
6
|
+
* @license
|
|
7
|
+
* Copyright 2023 IABTechLab
|
|
8
|
+
*
|
|
9
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
10
|
+
* use this file except in compliance with the License. You may obtain a copy of
|
|
11
|
+
* the License at
|
|
12
|
+
*
|
|
13
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
14
|
+
*
|
|
15
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
16
|
+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
17
|
+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
18
|
+
* License for the specific language governing permissions and limitations under
|
|
19
|
+
* the License.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import {
|
|
23
|
+
decode as fibIntDecode,
|
|
24
|
+
encode as fibIntEncode,
|
|
25
|
+
} from './FibonacciIntegerEncoder';
|
|
26
|
+
import {
|
|
27
|
+
decode as intDecode,
|
|
28
|
+
encode as intEncode,
|
|
29
|
+
} from './FixedIntegerEncoder';
|
|
30
|
+
|
|
31
|
+
import { decode as boolDecode } from './BooleanEncoder';
|
|
32
|
+
|
|
33
|
+
export const encode = (value: number[]) => {
|
|
34
|
+
value = value.sort((n1, n2) => n1 - n2);
|
|
35
|
+
|
|
36
|
+
const groups = [];
|
|
37
|
+
|
|
38
|
+
let offset = 0;
|
|
39
|
+
let groupStartIndex = 0;
|
|
40
|
+
while (groupStartIndex < value.length) {
|
|
41
|
+
let groupEndIndex = groupStartIndex;
|
|
42
|
+
while (
|
|
43
|
+
groupEndIndex < value.length - 1 &&
|
|
44
|
+
value[groupEndIndex]! + 1 === value[groupEndIndex + 1]
|
|
45
|
+
) {
|
|
46
|
+
groupEndIndex++;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
groups.push(value.slice(groupStartIndex, groupEndIndex + 1));
|
|
50
|
+
|
|
51
|
+
groupStartIndex = groupEndIndex + 1;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let bitString = intEncode(groups.length, 12);
|
|
55
|
+
for (let i = 0; i < groups.length; i++) {
|
|
56
|
+
const group = groups[i]!;
|
|
57
|
+
if (group.length > 0) {
|
|
58
|
+
const startInt = group[0]!;
|
|
59
|
+
if (groups.length === 1) {
|
|
60
|
+
const v = startInt - offset;
|
|
61
|
+
offset = startInt;
|
|
62
|
+
bitString += '0' + fibIntEncode(v);
|
|
63
|
+
} else {
|
|
64
|
+
const startVal = startInt - offset;
|
|
65
|
+
offset = startInt;
|
|
66
|
+
const endInt = group[group.length - 1]!;
|
|
67
|
+
const endVal = endInt - offset;
|
|
68
|
+
offset = endInt;
|
|
69
|
+
bitString += '1' + fibIntEncode(startVal) + fibIntEncode(endVal);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return bitString;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export const decode = (bitString: string) => {
|
|
77
|
+
if (!/^[01]{12,}$/.test(bitString)) {
|
|
78
|
+
throw new Error('invalid bit string');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const value = [];
|
|
82
|
+
const count = intDecode(bitString.substring(0, 12));
|
|
83
|
+
|
|
84
|
+
let offset = 0;
|
|
85
|
+
let startIndex = 12;
|
|
86
|
+
for (let i = 0; i < count; i++) {
|
|
87
|
+
const group = boolDecode(bitString.substring(startIndex, startIndex + 1));
|
|
88
|
+
startIndex++;
|
|
89
|
+
|
|
90
|
+
if (group === true) {
|
|
91
|
+
let index = bitString.indexOf('11', startIndex);
|
|
92
|
+
const start =
|
|
93
|
+
fibIntDecode(bitString.substring(startIndex, index + 2)) + offset;
|
|
94
|
+
offset = start;
|
|
95
|
+
startIndex = index + 2;
|
|
96
|
+
|
|
97
|
+
index = bitString.indexOf('11', startIndex);
|
|
98
|
+
const end =
|
|
99
|
+
fibIntDecode(bitString.substring(startIndex, index + 2)) + offset;
|
|
100
|
+
offset = end;
|
|
101
|
+
startIndex = index + 2;
|
|
102
|
+
|
|
103
|
+
for (let j = start; j <= end; j++) {
|
|
104
|
+
value.push(j);
|
|
105
|
+
}
|
|
106
|
+
} else {
|
|
107
|
+
const index = bitString.indexOf('11', startIndex);
|
|
108
|
+
const val =
|
|
109
|
+
fibIntDecode(bitString.substring(startIndex, index + 2)) + offset;
|
|
110
|
+
offset = val;
|
|
111
|
+
value.push(val);
|
|
112
|
+
startIndex = index + 2;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return value;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
export default {
|
|
120
|
+
decode,
|
|
121
|
+
encode,
|
|
122
|
+
};
|