Skip to content

Commit

Permalink
Add support for compressing arbitrary URLs.
Browse files Browse the repository at this point in the history
Add support for compressing arbitrary URLs. Any id which is in the
`appContextMap` will be compressed as a single number before using other
URL codecs.
  • Loading branch information
davidlehn committed Feb 8, 2024
1 parent eba334a commit 38ba50e
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 5 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# @digitalbazaar/cborld ChangeLog

## 6.1.0 - 2023-xx-xx

### Added
- Add support for compressing arbitrary URLs. Any id which is in the
`appContextMap` will be compressed as a single number before using other URL
codecs.

## 6.0.3 - 2023-12-19

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion lib/Decompressor.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ export class Decompressor extends Transformer {
}

_transformObjectId({obj, termInfo, value}) {
const decoder = UriDecoder.createDecoder({value});
const decoder = UriDecoder.createDecoder({value, transformer: this});
obj[termInfo.term] = decoder ? decoder.decode({value}) : value;
}

Expand Down
36 changes: 36 additions & 0 deletions lib/codecs/AppUrlDecoder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*!
* Copyright (c) 2021-2023 Digital Bazaar, Inc. All rights reserved.
*/
import {CborldDecoder} from './CborldDecoder.js';
import {CborldError} from '../CborldError.js';

const ID = 1026;

export class AppUrlDecoder extends CborldDecoder {
constructor({reverseAppContextMap} = {}) {
super();
this.reverseAppContextMap = reverseAppContextMap;
}

decode({value} = {}) {
// handle compressed app URL
const url = this.reverseAppContextMap.get(value[1]);
if(url === undefined) {
throw new CborldError(
'ERR_UNDEFINED_COMPRESSED_APP_URL',
`Undefined compressed app URL "${value}".`);
}
return url;
}

static createDecoder({value, transformer} = {}) {
if(!(Array.isArray(value) && value.length === 2)) {
return false;
}
if(!(value[0] === ID)) {
return false;
}
const {reverseAppContextMap} = transformer;
return new AppUrlDecoder({reverseAppContextMap});
}
}
35 changes: 35 additions & 0 deletions lib/codecs/AppUrlEncoder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*!
* Copyright (c) 2021-2023 Digital Bazaar, Inc. All rights reserved.
*/
import {Token, Type} from 'cborg';
import {CborldEncoder} from './CborldEncoder.js';

const ID = 1026;

export class AppUrlEncoder extends CborldEncoder {
constructor({value, appContextMap} = {}) {
super();
this.value = value;
this.appContextMap = appContextMap;
}

encode() {
const {value} = this;
// FIXME: handle errors (shouldn't happen if called correctly)
const id = this.appContextMap.get(value);
const entries = [
new Token(Type.uint, ID),
new Token(Type.uint, id)
];
return [new Token(Type.array, entries.length), entries];
}

static createEncoder({value, transformer} = {}) {
// FIXME: needed?
if(typeof value !== 'string') {
return false;
}
const {appContextMap} = transformer;
return new AppUrlEncoder({value, appContextMap});
}
}
9 changes: 6 additions & 3 deletions lib/codecs/UriDecoder.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*!
* Copyright (c) 2021-2023 Digital Bazaar, Inc. All rights reserved.
*/
import {AppUrlDecoder} from './AppUrlDecoder.js';
import {Base58DidUrlDecoder} from './Base58DidUrlDecoder.js';
import {CborldDecoder} from './CborldDecoder.js';
import {HttpUrlDecoder} from './HttpUrlDecoder.js';
Expand All @@ -11,16 +12,18 @@ const SCHEME_ID_TO_DECODER = new Map([
[2, HttpUrlDecoder],
[3, UuidUrnDecoder],
[1024, Base58DidUrlDecoder],
[1025, Base58DidUrlDecoder]
[1025, Base58DidUrlDecoder],
// FIXME: encdeds as 3 bytes, may want to use a lower id
[1026, AppUrlDecoder]
]);

export class UriDecoder extends CborldDecoder {
static createDecoder({value} = {}) {
static createDecoder({value, transformer} = {}) {
if(!(Array.isArray(value) || value.length > 1)) {
return false;
}

const DecoderClass = SCHEME_ID_TO_DECODER.get(value[0]);
return DecoderClass && DecoderClass.createDecoder({value});
return DecoderClass && DecoderClass.createDecoder({value, transformer});
}
}
8 changes: 7 additions & 1 deletion lib/codecs/UriEncoder.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*!
* Copyright (c) 2021-2023 Digital Bazaar, Inc. All rights reserved.
*/
import {AppUrlEncoder} from './AppUrlEncoder.js';
import {Base58DidUrlEncoder} from './Base58DidUrlEncoder.js';
import {CborldEncoder} from './CborldEncoder.js';
import {HttpUrlEncoder} from './HttpUrlEncoder.js';
Expand All @@ -15,11 +16,16 @@ const SCHEME_TO_ENCODER = new Map([
]);

export class UriEncoder extends CborldEncoder {
static createEncoder({value} = {}) {
static createEncoder({value, transformer} = {}) {
if(typeof value !== 'string') {
return false;
}

const {appContextMap} = transformer;
if(appContextMap.has(value)) {
return AppUrlEncoder.createEncoder({value, transformer});
}

// get full colon-delimited prefix
let scheme;
try {
Expand Down

0 comments on commit 38ba50e

Please sign in to comment.