Skip to content

Commit 4eef553

Browse files
authored
fix(nano): resource locator kid parse issue (#330)
* fix(nano): resource locator kid parse issue * Fix the unit test and improved the code * 🤖 🎨 Autoformat Signed-off-by: sujan kota <[email protected]> --------- Signed-off-by: sujan kota <[email protected]> Co-authored-by: sujankota <[email protected]>
1 parent 69e0a81 commit 4eef553

File tree

2 files changed

+54
-40
lines changed

2 files changed

+54
-40
lines changed

lib/src/nanotdf/models/ResourceLocator.ts

Lines changed: 51 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -29,49 +29,63 @@ export default class ResourceLocator {
2929
static readonly LENGTH_OFFSET = 1;
3030
static readonly LENGTH_LENGTH = 1;
3131
static readonly BODY_OFFSET = 2;
32+
static readonly IDENTIFIER_0_BYTE: number = 0 << 4; // 0
33+
static readonly IDENTIFIER_2_BYTE: number = 1 << 4; // 16
34+
static readonly IDENTIFIER_8_BYTE: number = 2 << 4; // 32
35+
static readonly IDENTIFIER_32_BYTE: number = 3 << 4; // 48
3236

3337
static parse(url: string, identifier: string = ''): ResourceLocator {
3438
const [protocol, body] = url.split('://');
35-
const bodyLength = body.length;
36-
const identifierLength = identifier.length;
37-
let identifierPaddedLength = 0;
38-
// protocol and identifier byte
39+
40+
// Validate and set protocol identifier byte
3941
const protocolIdentifierByte = new Uint8Array(1);
40-
if (protocol.toLowerCase() == 'http') {
41-
protocolIdentifierByte[0] = protocolIdentifierByte[0] & 0x0f;
42-
} else if (protocol.toLowerCase() == 'https') {
43-
protocolIdentifierByte[0] = (protocolIdentifierByte[0] & 0x0f) | 0b0010;
44-
} else {
45-
throw new Error('Resource locator protocol is not supported.');
46-
}
47-
if (identifierLength === 0) {
48-
protocolIdentifierByte[0] = (protocolIdentifierByte[0] & 0xf0) | 0b0000;
49-
} else if (identifierLength <= 2) {
50-
protocolIdentifierByte[0] = (protocolIdentifierByte[0] & 0xf0) | 0b0010;
51-
identifierPaddedLength = ResourceLocatorIdentifierEnum.TwoBytes.valueOf();
52-
} else if (identifierLength <= 8) {
53-
protocolIdentifierByte[0] = (protocolIdentifierByte[0] & 0xf0) | 0b0100;
54-
identifierPaddedLength = ResourceLocatorIdentifierEnum.EightBytes.valueOf();
55-
} else if (identifierLength <= 32) {
56-
protocolIdentifierByte[0] = (protocolIdentifierByte[0] & 0xf0) | 0b1000;
57-
identifierPaddedLength = ResourceLocatorIdentifierEnum.ThirtyTwoBytes.valueOf();
58-
} else {
59-
throw new Error('Unsupported identifier length: ' + identifierLength);
42+
switch (protocol.toLowerCase()) {
43+
case 'http':
44+
protocolIdentifierByte[0] = 0x00;
45+
break;
46+
case 'https':
47+
protocolIdentifierByte[0] = 0x01;
48+
break;
49+
default:
50+
throw new Error('Resource locator protocol is not supported.');
6051
}
61-
// Buffer to hold the protocol, length of body, body, and identifierPadded
62-
const buffer = new Uint8Array(1 + 1 + bodyLength + identifierPaddedLength);
52+
53+
// Set identifier padded length and protocol identifier byte
54+
const identifierPaddedLength = (() => {
55+
switch (identifier.length) {
56+
case 0:
57+
protocolIdentifierByte[0] |= ResourceLocator.IDENTIFIER_0_BYTE;
58+
return ResourceLocatorIdentifierEnum.None.valueOf();
59+
case 2:
60+
protocolIdentifierByte[0] |= ResourceLocator.IDENTIFIER_2_BYTE;
61+
return ResourceLocatorIdentifierEnum.TwoBytes.valueOf();
62+
case 8:
63+
protocolIdentifierByte[0] |= ResourceLocator.IDENTIFIER_8_BYTE;
64+
return ResourceLocatorIdentifierEnum.EightBytes.valueOf();
65+
case 32:
66+
protocolIdentifierByte[0] |= ResourceLocator.IDENTIFIER_32_BYTE;
67+
return ResourceLocatorIdentifierEnum.ThirtyTwoBytes.valueOf();
68+
default:
69+
throw new Error(`Unsupported identifier length: ${identifier.length}`);
70+
}
71+
})();
72+
73+
// Create buffer to hold protocol, body length, body, and identifier
74+
const bodyBytes = new TextEncoder().encode(body);
75+
const buffer = new Uint8Array(1 + 1 + bodyBytes.length + identifierPaddedLength);
76+
77+
// Set the protocol, body length, body and identifier into buffer
6378
buffer.set(protocolIdentifierByte, 0);
64-
buffer.set([bodyLength], 1);
65-
buffer.set(new TextEncoder().encode(body), 2);
66-
// add padded identifier
79+
buffer.set([bodyBytes.length], 1);
80+
buffer.set(bodyBytes, 2);
81+
6782
if (identifierPaddedLength > 0) {
68-
const identifierArray = new Uint8Array(identifierPaddedLength);
69-
const encodedIdentifier = new TextEncoder()
83+
const identifierBytes = new TextEncoder()
7084
.encode(identifier)
7185
.subarray(0, identifierPaddedLength);
72-
identifierArray.set(encodedIdentifier);
73-
buffer.set(identifierArray, 2 + bodyLength);
86+
buffer.set(identifierBytes, 2 + bodyBytes.length);
7487
}
88+
7589
return new ResourceLocator(buffer);
7690
}
7791

@@ -86,12 +100,12 @@ export default class ResourceLocator {
86100
buff.subarray(ResourceLocator.BODY_OFFSET, ResourceLocator.BODY_OFFSET + this.lengthOfBody)
87101
);
88102
// identifier
89-
const identifierTypeNibble = this.protocol & 0xf;
90-
if ((identifierTypeNibble & 0b0010) !== 0) {
103+
const identifierTypeNibble = this.protocol & 0xf0;
104+
if (identifierTypeNibble === ResourceLocator.IDENTIFIER_2_BYTE) {
91105
this.identifierType = ResourceLocatorIdentifierEnum.TwoBytes;
92-
} else if ((identifierTypeNibble & 0b0100) !== 0) {
106+
} else if (identifierTypeNibble === ResourceLocator.IDENTIFIER_8_BYTE) {
93107
this.identifierType = ResourceLocatorIdentifierEnum.EightBytes;
94-
} else if ((identifierTypeNibble & 0b1000) !== 0) {
108+
} else if (identifierTypeNibble === ResourceLocator.IDENTIFIER_32_BYTE) {
95109
this.identifierType = ResourceLocatorIdentifierEnum.ThirtyTwoBytes;
96110
}
97111
switch (this.identifierType) {

lib/tests/web/nanotdf/ntdf-spec-basic-example.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ describe('NanoTDF', () => {
2121
rl = ResourceLocator.parse('http://localhost:8080', 'e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0');
2222
assert.equal(rl.identifierType, ResourceLocatorIdentifierEnum.ThirtyTwoBytes);
2323
assert.equal(rl.getIdentifier(), 'e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0');
24-
rl = ResourceLocator.parse('http://localhost:8080', 'e0e0e0e0e0e0e0e0');
25-
assert.equal(rl.identifierType, ResourceLocatorIdentifierEnum.ThirtyTwoBytes);
26-
assert.equal(rl.getIdentifier(), 'e0e0e0e0e0e0e0e0');
24+
expect(() => ResourceLocator.parse('http://localhost:8080', 'e0e0e0e0e0e0e0e0')).throw(
25+
'Unsupported identifier length: 16'
26+
);
2727
});
2828
for (const { policyType, fixture } of [
2929
{ policyType: PolicyTypeEnum.Remote, fixture: remoteFixture },

0 commit comments

Comments
 (0)