CBOR is a compact binary data serialization and messaging format. This
specification defines CBOR-LD 1.0, a CBOR-based format to serialize Linked Data.
The encoding is designed to leverage the existing JSON-LD ecosystem, which is
deployed on hundreds of millions of systems today, to provide a compact
serialization format for those seeking efficient encoding schemes for Linked
Data. By utilizing semantic compression schemes, compression ratios in excess of
60% better than generalized compression schemes are possible. This format is
primarily intended to be a way to use Linked Data in storage and bandwidth
constrained programming environments, to build interoperable semantic wire-level
protocols, and to efficiently store Linked Data in CBOR-based storage engines.
CBOR Tags for CBOR-LD
The first step in decoding a CBOR-LD payload is to recreate the term codec
map that was used to encode it by processing the contexts in the payload. However,
the contexts needed to create the term codec map can have their URLs encoded as integers
by CBOR-LD. If a CBOR-LD payload contains context URLs compressed in such a way, the
consumer of the CBOR-LD needs to know what compression tables (maps from JSON-LD terms to integers)
were used to compress the context URLs during creation to be able to reconstruct the term codec
map. The following sections define the exact mechanism by which this can be accomplished, allowing
an arbitrary CBOR-LD consumer to decompress any CBOR-LD payload that conforms to this specification.
To this end, we have registered the range of CBOR tags 1536-1791** (0x0600-0x06FF) to be used for CBOR-LD,
where data that includes tag value is used to lookup what compression table(s) are needed
to decompress the CBOR-LD context URLs.
This exact range of tag values has not yet been officially registered with
the IANA CBOR
Tag Registry. The exact range is subject to change.
CBOR-LD Varint
To enable unbounded extension on possible use cases for CBOR-LD that require different
compression table material for consumption while working within a fixed number of
CBOR tag values, we define the following.
Implementers MUST interpret the last byte of the two-byte CBOR tag value on a CBOR-LD payload
as the beginning of a varint. If the CBOR tag is in the range `0x0600`–`0x067F`, the last byte of
the CBOR tag is a one-byte varint, and the tagged item MUST be a map containing the encoded
JSON-LD. If the CBOR tag is `0x0680` or greater, the tagged item MUST be an array containing
two elements. The first item in the array MUST be a major type 2 byte string containing the
rest of the varint, and the second item in the array MUST be a map containing the
encoded JSON-LD. See Algorithm for
more information.
The value of this varint is then used to lookup a CBOR-LD Varint Registry Entry in the
CBOR-LD Varint Registry.
CBOR-LD Varint Registry
The CBOR-LD Registry is a global list that provides
consumers of CBOR-LD payloads the information they need to reconstruct the term codec map
required for decompression. A CBOR-LD Varint Registry Entry contains the following:
-
Registry Entry ID: a positive integer.
-
Use Case: what type of CBOR-LD payload this entry is used for.
-
`typeTables`: an array containing what `Type Tables` are to be used for this
type of payload.
-
`processingModel`: what processing model is used for this registry entry. A processing model
specifies how auto-generated CBOR-LD values are created from JSON-LD contexts as well as what
type encoders are used alongside the `Type Tables` (e.g. how to partially compress an
`xsd:dateTime` value that does not appear in `Type Table`). The default processing model,
which will be defined later in this specification, will be used unless otherwise specified
in the Registry Entry.
-
Provisional: a yes/no flag indicating whether the entry is provisional. Provisional entries
may change or be removed.
The `typeTables` associated with a CBOR-LD Varint Registry Entry MUST be an array of
or JSON objects. The only exception is the string "callerProvidedTable", which may appear in this array,
denoting that for this use case, a `Type Table` is required which is not globally
defined.
Dereferencing one of these URLs MUST result in a JSON object with the following properties:
-
`type`: a JSON-LD type.
-
`table`: a JSON object that maps values of the above type to integers.
If a JSON object is present in the `typeTables` array, it MUST be in the above format.
The following is the current CBOR-LD registry:
Registry Entry Id |
Use Case |
typeTables |
Processing Model |
Provisional |
0 |
Uncompressed CBORLD |
None |
DEFAULT |
No |
1 |
Compressed CBORLD, default use case. |
DEFAULT |
DEFAULT |
No |
100 |
Verifiable Credential Barcodes Specification Test Vectors |
[
{
type: "context",
table:
{
"https://www.w3.org/ns/credentials/v2": 32768,
"https://w3id.org/vc-barcodes/v1": 32769,
"https://w3id.org/utopia/v2": 32770
}
},
{
type: "https://w3id.org/security#cryptosuiteString",
table:
{
"ecdsa-rdfc-2019": 1,
"ecdsa-sd-2023": 2,
"eddsa-rdfc-2022": 3,
"ecdsa-xi-2023": 4
}
}
]
|
DEFAULT |
Yes |
10001 |
Provisional California DMV Credentials |
[
{
type: "context",
table:
{
"https://www.w3.org/ns/credentials/v2": 1,
"https://w3id.org/vc-barcodes/v1": 2,
"https://w3id.org/vc-dpp/v1rc1": 3,
"https://w3id.org/vdl/v1": 4
}
},
{
type: "https://w3id.org/security#cryptosuiteString",
table:
{
"ecdsa-rdfc-2019": 1
}
},
{
type: "url",
table:
{
"did:key:zDnaeW9VZZs7NH1ykvS5EMFmdodu2wj4dPcrV3DzTAadrXJee": 1,
"did:key:zDnaeW9VZZs7NH1ykvS5EMFmdodu2wj4dPcrV3DzTAadrXJee#zDnaeW9VZZs7NH1ykvS5EMFmdodu2wj4dPcrV3DzTAadrXJee": 2,
"https://dmv.ca.gov/statuses/12345/status-lists": 3
}
}
]
|
DEFAULT |
Yes |
10002 |
Provisional First Responder SAP Credentials |
[
{
type: "context",
table:
{
"https://www.w3.org/ns/credentials/v2": 1,
"https://w3id.org/vc-barcodes/v1": 2,
"https://w3id.org/first-responder/sap/v1rc1": 3,
}
},
{
type: "https://w3id.org/security#cryptosuiteString",
table:
{
"ecdsa-rdfc-2019": 1
}
},
{
type: "url",
table:
{
"did:key:zDnaeW9VZZs7NH1ykvS5EMFmdodu2wj4dPcrV3DzTAadrXJee": 1,
"did:key:zDnaeW9VZZs7NH1ykvS5EMFmdodu2wj4dPcrV3DzTAadrXJee#zDnaeW9VZZs7NH1ykvS5EMFmdodu2wj4dPcrV3DzTAadrXJee": 2,
"https://caloes.ca.gov/statuses/12345/status-lists": 3
}
}
]
|
DEFAULT |
Yes |
Algorithms
In this section, we specify the algorithms required to convert JSON-LD to CBOR-LD
and vice versa. We provide first the context processing algorithms, which are required
for both decompression and compression; we then provide the mode-specific algorithms.
Encoding and Decoding
JSON-LD to CBOR-LD Compression Algorithm
This algorithm takes a map `typeTable`, an integer `registryEntryId`, and a JSON-LD
document `jsonldDocument` as inputs, and returns a hexadecimal string `cborldBytes`.
-
Set `prefix` to the result of passing `registryEntryId` to
.
-
Set `state` to an empty map.
-
Set `state.strategy` to "compression".
-
Set `state.typeTable` to `typeTable`.
-
Set `state.registryEntryId` to `registryEntryId`.
-
Set `state` to the result of passing `state` to
.
-
Set `output` to the result of passing `state` and `jsonldDocument`
as `inputDocument` to .
-
Set `suffix` to the CBOR encoding of `output`.
-
Set `cborldBytes` to a hexidecimal encoding of `prefix` prepended to `suffix`.
-
Return `cborldBytes`.
CBOR-LD to JSON-LD Decompression Algorithm
This algorithm takes a CBOR-LD payload `cborldBytes`, and returns a JSON-LD document `jsonldDocument`.
-
Set `result` to the result of passing `registryEntryId` and `cborldBytes` to
.
-
Set `state`.`registryEntryId` to `result`.`registryEntryId` and `suffix` to `result`.`suffix`.
-
Set `state` to an empty map.
-
Set `state.strategy` to "decompression".
-
For each entry `type`: `map` in the `typeTables` array in the CBOR-LD Varint Registry Entry
associated with `registryEntryId`, add that entry to `state`.`typeTable`, and set the value of `type`
in `state`.`reverseTypeTable` to `inverseMap`, where `inverseMap` is `map` with the mapping inverted.
-
Set `state` to the result of passing `state` to
.
-
Set `input` to the result of decoding `suffix` from bytes to a map.
-
Set `jsonldDocument` to the result of passing `state` and `input` as `inputDocuments`
to .
-
Return `jsonldDocument`.
Conversion Algorithms
The algorithms in this section describe the behavior of a "converter" for abstractly
converting inputs between data forms. When used in conjunction with a "strategy",
such as the "compression" and "decompression" strategies defined later in this section,
these algorithms can be instantiated to convert between concrete data forms. The
"compression" strategy converts from JSON-LD to CBOR-LD, while the "decompression"
strategy converts from CBOR-LD to JSON-LD.
Initialize Conversion Algorithm
This algorithm takes and returns a map `state`.
-
Set `state` to the result of passing `state` to
.
-
Set `state.initialActiveContext` to the result of passing empty maps `termMap` and
`previousActiveContext` to .
-
Set `state.typesEncodedAsBytes` to an empty set.
-
Add "none", "http://www.w3.org/2001/XMLSchema#date", "http://www.w3.org/2001/XMLSchema#dateTime",
and "url" to `state.typesEncodedAsBytes`.
-
Return `state`.
Convert Document Algorithm
This algorithm takes a map `state` and a map or array of
maps `inputDocuments`, and returns a map containing a map `state` and a map or
array of maps `outputMaps`.
-
If `inputDocuments` is an array, set `inputs` to `inputDocuments`. Otherwise, set `inputs`
to `[inputDocuments]`.
-
Set `outputMaps` to an empty array.
-
For `input` in `inputs`:
-
Set `output` to an empty map.
-
Set `result` to the result of passing `state`, `input`, `output`, and
`state.initialActiveContext` as `activeContext` to
.
-
Add `result.output` to `outputMaps`.
-
Set `state` to `result.state`.
-
If `inputDocuments` is an array, return `outputMaps`. Otherwise, return the
first element of `outputMaps`.
General Conversion Algorithm
This algorithm takes maps `input`, `output`, `state`, and `activeContext`
as inputs, and returns a map containing maps `state` and `output`.
-
If `state.strategy` is set to "compression":
-
Set `contextConversionResult` to the result of
, passing
`state`, `activeContext`, `input`, and `output`.
-
Set `activeContext` to `contextConversionResult.activeContext`, `output`
to `contextConversionResult.output`, and `state` to `contextConversionResult.state`.
-
Otherwise, set `activeContext` to
`result.activeContext` and `state` to `result.state` of `result` resulting from
, passing `state`,
`activeContext`, `input`, and `output`.
-
If `state.strategy` is set to "compression", set `state` to `result.state` and
`objectTypes` to `result.objectTypes` for `result` resulting from
, passing `state`,
`activeContext`, `input`, and `output`.
-
Otherwise, set `state` to `result.state` and `objectTypes` to `result.objectTypes`
for `result` resulting from ,
passing `state`, `activeContext`, `input`, and `output`.
-
Set `activeContext` to the result of passing `activeContext` and `objectTypes` to
.
-
If `state.strategy` is set to "compression", set `state` to `result.state` and
`termEntries` to `result.termEntries` for `result` resulting from
, passing `state`,
`input`, and `activeContext`.
-
Otherwise, set `state` to `result.state`, `output` to `result.output`,
and `termEntries` to `result.termEntries` for `result` resulting from
,
passing `state`, `input`, output, and `activeContext`.
-
For `[termInfo, value]` in `termEntries`:
-
Set `term` to `termInfo.term`.
-
Set `valueActiveContext` to the result of passing `activeContext` and `term` to
.
-
Set `plural` to the value of `termInfo.plural` and `termType` to the value of `@type`
in `termInfo.def`.
-
If `plural` is set to `true`, set `values` to the value of `value`. Otherwise, set `values` to
an array containing the value of `value` as a single element.
-
Set `outputs` to an empty array.
-
For `unconvertedValue` in `values`:
-
Set `result` to the result of ,
passing `state`, `termType`, `unconvertedValue` as `value`, and `valueActiveContext`
as `activeContext`.
-
Set `state` to `result.state` and add `result.output` to `outputs`.
-
If `plural` is set to `true`, set `outputValues` to `outputs`. Otherwise, set `outputValues`
to the first element of `outputs`.
-
If `state.strategy` is set to "compression", set the value of `termInfo.termId` to map to
`outputValues` in `output`. Otherwise, set the value of `termInfo.term` to map to `outputValues`
in `output`.
-
Set `result` to be an empty map.
-
Set `result.state` to `state` and `result.output` to `output`.
-
Return `result`.
Convert Value Algorithm
This algorithm takes maps `state`, `activeContext`, `termInfo`, and values `value` and `termType`.
It returns a `result` object containing maps `state` and `output`.
-
If `value` is `null`, return `null`.
-
If `state`.`strategy` is set to "compression", set `output` to the result of passing `state`, `termType`,
`termInfo`, and `value` to .
-
Otherwise, set `output` to the result of passing `state`, `termType`,
`termInfo`, and `value` to .
-
If `output` is defined, return `result`, a map contatining `state` and `output`.
-
If `value` is an array:
-
Set `outputs` to be an empty array.
-
For `element` of `value`:
-
Let `result` be the result of , passing `activeContext`, `state`,
`termInfo`, `termType`, and `element` as `value`. Set `state` to `result`.`state` and add `result`.`output`
to `outputs`.
-
Set `result` to be an empty map. Set `result`.`state` to `state` and `result`.`output` to `outputs`.
-
Return `result`.
-
Set `output` to an empty map.
-
Set `result` to the result of , passing `state`,
`activeContext`, `value` as `input`, and `output`.
-
Return `result`.
Compression Strategy Algorithms
The algorithms in this section define the "compression" strategy
to be used with the "conversion" algorithms defined previously to
convert JSON-LD to CBOR-LD.
Convert Contexts for Compression Algorithm
This algorithm takes maps `state`, `activeContext`, `input`, and `output`,
and returns a map `result` containing maps `output`, `state`, and `activeContext`.
-
Set `applyEmbeddedResult` to the result of ,
passing `state`, `activeContext`, and `input`.
-
Set `activeContext` to `applyEmbeddedResult.activeContext` and `state` to
`applyEmbeddedResult.state`.
-
If "@context" does not have an entry in `input`:
-
Set `result` to an empty map.
-
Set `result.state` to `state` and `result.activeContext` to `activeContext`.
-
Return `result`.
-
Set `context` to the value of "@context" in `input`.
-
Set `encodedContexts` to an empty array.
-
If `context` is an array, set `isArray` to `true` and `contexts` to `context`.
Otherwise, set `isArray` to `false` and `contexts` to `[context]`.
-
For `contextValue` in `contexts`:
-
Set `encoderData` to the result of , passing
`state.typeTable` and `contextValue`.
-
If `encoderData` is an empty map, add `contextValue` to `encodedContexts`.
-
Otherwise, add the value of `encoderData` to `encodedContexts`.
-
If `isArray` is `true`, set `id` to the value of "@context" in `state.keywordsMap` plus 1
and set the value of `id` in `output` to `encodedContexts`.
-
Otherwise, set `id` to the value of "@context" in `state.keywordMap` and set the value of
`id` in `output` to the first element of `encodedContexts`.
-
Set `result.output` to `output`, `result.state` to `state`, and `result.activeContext`
to `activeContext`.
-
Return `result`.
Convert Value for Compression Algorithm
This algorithm takes maps `state` and `termInfo`, and values `valueToEncode` and `termType`,
and returns a map `encoderData`.
-
If `valueToEncode` is an object, return.
-
Otherwise, set `result` to the result of , passing
`state`, `termInfo`, `valueToToEncode`, and `termType`.
-
Return `result`.
Get Input Entries for Compression Algorithm
This algorithm takes maps `state`, `activeContext`, and `input`, and returns a map `state` and an array `entries`.
-
Initialize `entries` as an empty array.
-
Set an array `keys` to the keys of `input`, sorted lexicographically.
-
For `key` in `keys`:
-
If `key` is "@context", continue.
-
Set `value` to the value of `key` in `input`.
-
If `value` is an array, set `plural` to `true`. Otherwise, set `plural` to `false`.
-
If `key` does not have an entry in `state`.`termToId`, set `termId` to `key`.
-
Otherwise, if `plural` is `true`, set `termId` to the value of `key` in `state`.`termToId` plus 1.
-
Otherwise, set `termId` to the value of `key` in `state`.`termToId`.
-
If `activeContext`.`termMap` has an entry for `key`, set `definition` to the value of `key` in
`activeContext`.`termMap`. Otherwise, set `definition` to an empty map.
-
Set `entryTerm` to be a new map.
-
Set the value of "term" in `entryTerm` to be the value of `key`. Add `termId`, `plural`, and `definition`
to `entryTerm`.
-
Create an array `entry` with two elements, `entryTerm` and `value`.
-
Add `entry` to `entries`.
-
Return a map `result` containing `entries` and `state`.
Get Object Types for Compression Algorithm
This algorithm takes maps `activeContext` and `input`, and returns a set
`objectTypes`.
-
Set `objectTypes` to be an empty set.
-
For `term` in `activeContext`.`typeTerms`:
-
If `term` has an entry in `input`:
-
Set `types` to the value of `term` in `input`.
-
Add each value in `types` to `objectTypes`.
-
Return `objectTypes`.
Decompression Strategy Algorithms
The algorithms in this section define the "decompression" strategy
to be used with the "conversion" algorithms defined previously to
convert CBOR-LD to JSON-LD.
Convert Contexts for Decompression Algorithm
This algorithm takes maps `state`, `activeContext`, `input`, and `output`, and returns a map
`result` containing maps `output`, `state`, and `activeContext`.
-
Set `decoderData` to the result of , passing `state`.`reverseTypeTable`.
-
Set `contextTermId` to the value of "@context" in `state`.`keywordsMap`.
-
If `contextTermId` has an entry in `input`, set the value of
"@context" in `output` to the result of , passing `decoderData` and
the value of `contextTermId` in `input` as `value`.
-
Set `contextTermIdPlural` to the value of `contextTermId` plus 1.
-
If `contextTermIdPlural` has an entry in `input`:
-
If `contextTermId` also had an entry in `input` during the previous check, throw an
`ERR_INVALID_ENCODED_CONTEXT` error.
-
Set `encodedContexts` to be the value of `contextTermIdPlural` in `input`. If `encodedContexts` is
not an array, throw an `ERR_INVALID_ENCODED_CONTEXT` error.
-
Set `contexts` to be an empty array.
-
For each `valueToDecode` in `encodedContexts`, add the result of passing `decoderData` and `valueToDecode`
as `value` to to `contexts`.
-
Set the value of "@context" in `output` to `contexts`.
-
Set `embeddedContextResult` to the result of , passing
`activeContext`, `output` as `input`, and `state`.
-
Set `result` to an empty map.
-
Set `result`.`state` to `embeddedContextResult`.`state` and `result.activeContext` to
`embeddedContextResult`.`activeContext`.
-
Return `result`.
Convert Value for Decompression Algorithm
This algorithm takes maps `state` and `termInfo`, and values `termType` and `valueToDecode`, and returns a value
`decodedValue`.
-
If `value` is a map, return.
-
Set `decoderData` to the result of , passing `valueToDecode`,
`state`, `termInfo`, and `termType`.
-
Set `decodedValue` to the result of , passing `decoderData`.
-
Return `decodedValue`.
Get Input Entries for Decompression Algorithm
This algorithm takes maps `state`, `activeContext`, and `input`, and returns a map `state` and an array
`entries`.
-
Initialize `entries` to an empty array.
-
For key-value pair `key` and `value` in `input`:
-
If `key` is the value of "@context" in `state`.`keywordsMap` or that value plus 1, continue.
-
Otherwise, if `key` is a string, set `plural` to false and `term` to `key`.
-
Otherwise:
-
If `key` is odd, set `plural` to true. Otherwise, set `plural` to false.
-
If `plural` is `true`, set `term` to the value of `id` minus 1 in `state`.`idToTerm`.
If that value does not have an entry, throw an error ERR_UNKNOWN_CBORLD_TERM_ID.
-
Otherwise, set `term` to the value of `id` in `state`.`idToTerm`. If that value does not have
an entry, throw an error ERR_UNKNOWN_CBORLD_TERM_ID.
-
Set `definition` to the value of `term` in `activeContext`.`termMap`.
-
Set `entryTerm` to be a new map.
-
Set the value of "termId" in `entryTerm` to be the value of `key`. Add `term`, `plural`, and `definition`
to `entryTerm`.
-
Create an array `entry` with two elements, `entryTerm` and `value`.
-
Add `entry` to `entries`.
-
Sort `entries` by the value of `term` in each element of `entries`.
-
Return a map `result` containing `entries` and `state`.
Get Object Types for Decompression Algorithm
This algorithm takes maps `state`, `activeContext`, `input` as inputs, and
returns a map `state` and a set `objectTypes`.
-
Set `objectTypes` to be an empty set.
-
For `term` in `activeContext`.`typeTerms`:
-
If `term` does not have an entry in `state`.`termToId`, set `termId` to `term`.
-
Otherwise, set `termId` to the value of `term` in `state`.`termToId`.
-
If neither `termId` nor `termId` plus 1 are present in `input`, continue.
-
Otherwise, if `termId` is present in `input`, set `value` to the value of `termId` in `input`.
-
Otherwise, set `value` to the value of `termId` plus 1 in `input`.
-
If `key` is a string, set `plural` to false and `term` to `key`.
-
Otherwise:
-
If `key` is odd, set `plural` to true. Otherwise, set `plural` to false.
-
If `plural` is `true`, set `term` to the value of `id` minus 1 in `state`.`idToTerm`.
If that value does not have an entry, throw an error ERR_UNKNOWN_CBORLD_TERM_ID.
-
Otherwise, set `term` to the value of `id` in `state`.`idToTerm`. If that value does not have
an entry, throw an error ERR_UNKNOWN_CBORLD_TERM_ID.
-
Set `definition` to the value of `term` in `activeContext`.`termMap`.
-
Set `termInfo` to be a new map.
-
Add `term`, `termId`, `plural`, and `definition` to `termInfo`.
-
If `value` is not an array, set `values` to be an array containing as a single element `value`.
Otherwise, set `values` to the value of `value`.
-
For each `value` in `values`:
-
Set `decoderData` to the result of , passing `value`,
`termInfo`, `state`, and "@vocab" as `termType`.
-
If `decoderData` exists, add the result of , passing `decoderData`, to `objectTypes.
-
Otherwise, add `value` to `objectTypes`.
-
Return `objectTypes`.
Active Context Processing
The algorithms in this section describe how to determine
what components of the context documents associated with a JSON-LD
document are in use at any point during compression or decompression.
These algorithms include how to apply embedded, type-scoped, and
property-scoped contexts with CBOR-LD. This is in contrast to the Context
Loading algorithms defined later in this specification, which describe how
to construct the mappings from terms to integers that are the core CBOR-LD
compression technique. Together, the Active Context Processing and Context
Loading algorithms specify how JSON-LD context documents should be processed
when converting to and from CBOR-LD.
Initialize Active Context Algorithm
This algorithm takes maps `previousActiveContext` and `termMap`,
and returns a map `activeContext`. It updates the active context
in use and finds all aliases for `'@type'`.
-
Set `activeContext` to a new map.
-
Set `activeContext.previousActiveContext` to `previousActiveContext`.
-
Set `activeContext.termMap` to `termMap`.
-
Set `activeContext.typeTerms` to the array `['@type']`.
-
For `[term, def]` in `termMap`:
-
If the value of "@id" in `def` is "@type", add `term` to `activeContext.typeTerms`.
-
Return `activeContext`.
Apply Embedded Contexts Algorithm
This algorithm takes maps `state`, `activeContext`, and `input` as inputs, and
returns a map `result` containing maps `state` and `activeContext`.
-
Set `termMapUpdateResult` to the result of passing `state`, `activeContext.termMap` as
`activeTermMap`, and the value of '@context' in `input` as `contexts` to
.
-
Set `state` to `termMapUpdateResult.state`.
-
Set `termMap` to `termMapUpdateResult.activeTermMap`.
-
Set `newActiveContext` to the result of ,
passing `termMap` and `activeContext` as `previousActiveContext`.
-
Set `result` to be a new map, and set `result.activeContext` to `newActiveContext` and
`result.state` to `state`.
-
Return `result`.
Apply Property Scoped Contexts Algorithm
This algorithm takes maps `state`, `activeContext`, and a string `term` as inputs and
returns a map `result` containing maps `state` and `activeContext`.
-
Set `revertedTermMap` to the result of ,
passing `activeContext`.
-
Set `termDef` to the value of `term` in `activeContext.termMap`. Set `contexts` to the value of
"@context" in `termDef`.
-
Set `termMapUpdateResult` to the result of passing `state`, `revertedTermMap` as
`activeTermMap`, `true` as `propertyScope`, and `contexts` to
.
-
Set `state` to `termMapUpdateResult.state`.
-
Set `termMap` to `termMapUpdateResult.activeTermMap`.
-
Set `newActiveContext` to the result of ,
passing `termMap` and `activeContext` as `previousActiveContext`.
-
Set `result` to be a new map, and set `result.activeContext` to `newActiveContext` and
`result.state` to `state`.
-
Return `result`.
Apply Type Scoped Contexts Algorithm
This algorithm takes maps `state`, `activeContext` ,and a set `objectTypes` as inputs, and
returns a map `result` containing maps `state` and `activeContext`.
-
Set `objectTypesSorted` to an empty array.
-
Lexicographically sort the elements of `objectTypes` and add the elements to
`objectTypesSorted` in order.
-
Set `newTermMap` to `activeContext.termMap`.
-
For `type` in `objectTypesSorted`:
-
Set `typeDef` to the value of `type` in `newTermMap`. Set `contexts` to the value of
"@context" in `typeDef`.
-
Set `termMapUpdateResult` to the result of passing `state`, `newTermMap` as
`activeTermMap`, `contexts`, and `true` as `typeScope` to
.
-
Set `state` to `termMapUpdateResult.state` and `newTermMap` to
`termMapUpdateResult.activeTermMap`.
-
Set `newActiveContext` to the result of ,
passing `newTermMap` as `termMap` and `activeContext` as `previousActiveContext`.
-
Set `result` to be a new map, and set `result.activeContext` to `newActiveContext` and
`result.state` to `state`.
-
Return `result`.
Update Term Map Algorithm
This algorithm takes maps `state`, `activeTermMap`, and map or array `contexts` as well as booleans `typeScope`
and `propertyScope`, both of which default to `false` if not provided, as inputs. It returns maps `state`
and `activeTermMap`.
-
If `contexts` is not an array, set `contexts` to be an array with the previous value of `contexts`
as its sole element.
-
Set `allowProtectedOverride` to the value of `propertyScope`.
-
Set `propagateDefault` to the negation of the value of `typeScope`.
-
For `contextIdentifier` in `contexts`:
-
Set `loadResult` to the result of , passing `state` and
`contextIdentifier`.
-
Set `entry` to `loadResult`.`entry`, `context` to `entry`.`context`, and `state` to `loadResult`.`state`.
-
If `@propagate` appears in `context`, set `propagate` to the value of `@propagate` in `context`.
Otherwise, set `propagate` to the value of `propagateDefault`.
-
Set `newTermMap` to be an empty map. For [`key`, `value`] in `entry`.`termMap`:
-
Shallow copy the contents of `value` into a new map `newValue` and add `propagate`
to `newValue`.
-
Set the value of `key` in `newTermMap` to `newValue`.
-
For [`term`, `activeDef`] in `activeTermMap`:
-
Let `def` be the value of `term` in `newTermMap`.
-
If `def` is defined:
-
If the value of `protected` in `activeDef` is `true`:
-
If `allowProtectedOverride` is set to `false` and `def` is not identical to `activeDef`,
throw an error ERR_PROTECTED_TERM_REDEFINITION.
-
Otherwise, set the value of `term` in `newTermMap` to a map containing the values from `activeDef`
and `propagate` set to the value of `def`.`propagate`.
-
Otherwise, if `term` appears in `context`, set the value of `term` in `newTermMap` to
a map containing all values from `activeDef`.
-
Set the value of `activeTermMap` to the value of `newTermMap`.
-
Set `result` to be an empty map.
-
Set `result`.`state` to `state` and `result`.`activeTermMap` to `activeTermMap`.
-
Return `result`.
Revert Term Map Algorithm
This algorithm takes as input a map `activeContext`, and returns a map
`newTermMap`.
-
Set `newTermMap` to an empty map.
-
Set `nonPropagatingTerms` to an empty array.
-
For `[term, def]` in `activeContext`:
-
If `def.propagate` is set to `false`, add `term` to `nonPropagatingTerms`
and proceed to the next iteration of this loop.
-
Otherwise, set the value of `term` in `newTermMap` to `def`.
-
For `term` in `nonPropagatingTerms`:
-
Set `currentContext` to `activeContext.previousActiveContext`.
-
Set `def` to the value of `term` in `currentContext.termMap`.
-
While `def` is not undefined and `def.propagate` is set to `false`:
-
Set `currentContext` to `activeContext.previousActiveContext`.
-
Set `def` to the value of `term` in `currentContext.termMap`.
-
If `def` is not undefined, set the value of `term` in `newTermMap` to `def`.
-
Return `newTermMap`.
Context Loading
The algorithms in this section define how to construct the mappings between
terms and integers that are used as the core CBOR-LD compression technique.
Initialize Context Loader Algorithm
This algorithm takes and returns a map `state`.
-
Set `state.contextMap` to a new map.
-
Set `state.nextTermId` to 100.
-
Set `state.keywordsMap` to the following map of JSON-LD keywords to their associated
integer values:
{
'@context' => 0,
'@type' => 2,
'@id' => 4,
'@value' => 6,
'@direction' => 8,
'@graph' => 10,
'@included' => 12,
'@index' => 14,
'@json' => 16,
'@language' => 18,
'@list' => 20,
'@nest' => 22,
'@reverse' => 24,
'@base' => 26,
'@container' => 28,
'@default' => 30,
'@embed' => 32,
'@explicit' => 34,
'@none' => 36,
'@omitDefault' => 38,
'@prefix' => 40,
'@preserve' => 42,
'@protected' => 44,
'@requireAll' => 46,
'@set' => 48,
'@version' => 50,
'@vocab' => 52,
'@propagate' => 54
}
-
Add each entry in `state.keywordsMap` to `state.termToId`.
-
If `state.strategy` is set to "decompression", set `state.idToTerm` to the reverse map
of `state.termToId` (i.e., a map from integers to JSON-LD keywords).
-
Return `state`.
Load Context Algorithm
This algorithm takes a map `state` and a context map or URL `contextIdentifier`, and returns
`result`, a map containing maps `state` and `entry`.
-
If `state.contextMap` has an entry for `contextIdentifier`:
-
Initialize `result` to an empty map.
-
Set `result.state` to `state`.
-
Set `result.entry` to the value of `contextIdentifier` in `state.contextMap`.
-
Return `result`.
-
If `context` is a string:
-
Fetch the associated context object and set `context` to the value
of "@context" in that object.
-
Set `contextUrl` to the value of `contextIdentifier`.
-
Otherwise, set `context` to `contextIdentifier`.
-
Set `result` to the result of , passing
`state`, `context`, and `contextUrl` if set.
-
Return `result`.
Add Context Algorithm
This algorithm takes a map `state`, a context object `context`, and a context URL `contextUrl`,
and returns `result`, a map containing maps `state` and `entry`.
-
If `context` has an entry "@import":
-
Set `importUrl` to the value of "@import" in `context.
-
If `state.contextMap` does not have an entry for `importUrl`:
-
Fetch the context object associated with `importUrl` and set `importContext` to the value of
"@context" in that object.
-
Set `importedContextAdditionResult` to the result of ,
passing `state`, `importContext` as `context`, and `importUrl` as `contextUrl`.
-
Set `state` to `importedContextAdditionResult.state` and `importEntry` to
`importedContextAdditionResult.entry`.
-
Otherwise, set `importEntry` to the value of `importUrl` in `state.contextMap`.
-
Set `context` to a map containing all entries from `context` as well as `importEntry.context`.
-
Set `termMap` to an empty map.
-
Set `entry` to be an object containing `context` and `termMap`.
-
Set `sortedTerms` to the result of sorting the keys in `context` in lexicographic order.
-
Set `isProtected` to `true` if "@protected" has an entry in `context` and `false` otherwise.
-
For `term` in `sortedTerms`:
-
If `term` has an entry in `state.keywordsMap`, proceed to the next iteration of this loop.
-
Set `definition` to the value of `term` in `context`.
-
If `definition` is `null`, proceed to the next iteration of this loop.
-
If `definition` is a string:
-
Set `newDefinition` to an empty map.
-
Set the value of "@id" in `newDefinition` to `definition`.
-
Set the value of `definition` to `newDefinition`.
-
Set the value of `protected` in `definition` to `isProtected`.
-
Set the value of `term` in `termMap` to `definition`.
-
If `term` does not have an entry in `state.termToId`:
-
Set `termId` to `state.nextTermId`.
-
Increment `state.nextTermId` by 2.
-
Set the value of `term` in `state.termToId` to `termId`.
-
Set the value of `termId` in `state.idToTerm` to `term`.
-
If `contextUrl` is defined, set the value of `contextUrl` in
`state.contextMap` to `entry`.
-
Otherwise, set the value of `context` in `state.contextMap`
to `entry`.
-
Set `result` to be an empty map.
-
Set `result.state` to `state` and `result.entry` to `entry`.
-
Return `result`.
Codecs
The codecs in this section specify exactly how individual values in JSON-LD should be converted to CBOR
and vice versa. They are used by the algorithms in the previous section, and allow CBOR-LD to efficiently
encode both primitive and non-primitive types as CBOR.
Context Codec
Create Context Encoder
This algorithm takes a map `typeTable` and a value `contextValue` and
returns a map `encoderData`.
-
Initialize `encoderData` to an empty map.
-
If `contextValue` is not a string, return.
-
Otherwise, set `contextTable` to the value of "context" in `typeTable`.
-
Set `encoderData.context` to `contextValue` and `encoderData.contextTable` to
`contextTable`.
-
Return `encoderData`.
Encode Context
This algorithm takes a map `encoderData`, and returns CBOR binary data.
-
If `encoderData`.`context` has an entry in `encoderData`.`contextTable`, return a CBOR encoding
of the value of `encoderData`.`context` in `encoderData` as a Major Type 0 (unsigned integer) object.
-
Otherwise, return a CBOR encoding of the value of `encoderData`.`context` as a Major Type 3
(text string) object.
Create Context Decoder
This algorithm takes a map `reverseTypeTable`, and
returns a map `encoderData`.
-
Set `reverseContextTable` to the value of "context" in `reverseTypeTable`.
-
Initialize `decoderData` to an empty map.
-
Set `decoderData`.`reverseContextTable` to the value of `reverseContextTable` and
return `decoderData`.
Decode Context
This algorithm takes a map `decoderData` and a value `value`, and returns a value.
-
If `value` is not a number, return `value`.
-
Otherwise, if `decoderData`.`reverseContextTable` has an entry for `value`, return
the value of that entry.
-
Otherwise, throw an error ERR_UNDEFINED_COMPRESSED_CONTEXT.
Value Codec
Create Value Encoder
This algorithm takes maps `state` and `termInfo`, and values
`termType` and `valueToEncode`, and returns a map `encoderData` or `valueToEncode`.
-
Set `isUrl` to `false`.
-
If `termInfo.term` is "@id" or "@type", set `isUrl` to `true`.
-
If the value of "@id" in `termInfo.def` is "@id" or "@type", set
`isUrl` to true.
-
If `termType` is "@id" or "@vocab", set `isUrl` to `true`.
-
If `isUrl` is `true`, set `tableType` to "url".
-
Otherwise, if `termType` is defined, set `tableType` to `termType`.
-
Otherwise, set `tableType` to "none".
-
If `state.typeTable` has an entry for `tableType`:
-
Set `subTable` to the value of `tableType` in `state.typeTable`.
-
If `subTable` has an entry for `valueToEncode`:
-
Set `intValue` to the value of `valueToEncode` in `subTable`. Set `includeSign` to `false`.
-
If `state`.`typesEncodedAsBytes` has an entry for `tableType`, set `convertToBytes` to `true`.
Otherwise, set `convertToBytes` to `false`.
-
Otherwise, if `tableType` is not "none" and `valueToEncode` is an integer:
-
Set `intValue` to the value of `valueToEncode`.
-
Set `convertToBytes` and `includeSign` to `true`.
-
If `intValue` is defined:
-
Initialize `encoderData` to an empty map.
-
Set `encoderData`.`intValue` to the value of `intValue`, `encoderData`.`convertToBytes` to
the value of `convertToBytes`, and `encoderData`.`includeSign` to the value of `includeSign`.
-
Return `encoderData`.
-
If `tableType` has an entry in `state.processingModeTypeEncoders`, set `encoderData` to the result of
calling the `Create Encoder` algorithm associated with that entry's codec.
-
If `encoderData` is defined, return `encoderData`.
-
Return `valueToEncode`.
Encode Value
This algorithm takes a map `encoderData`, and returns CBOR binary data.
-
If `encoderData`.`convertToBytes` is `true`:
-
Set `bytes` to the result of converting `intValue` to bytes, using the value of `includeSign` to
determine whether the binary representation of the integer should be signed or unsigned.
-
Return a CBOR encoding of `bytes` as a Major Type 2 (byte string) object.
-
Otherwise, return a CBOR encoding of `intValue` as a Major Type 0 (unsigned integer) object.
Create Value Decoder
This algorithm takes maps `state` and `termInfo`, and values
`termType` and `valueToDecode`, and returns a map `decoderData`.
-
Set `isUrl` to `false`.
-
If `termInfo.term` is "@id" or "@type", set `isUrl` to `true`.
-
If the value of "@id" in `termInfo.def` is "@id" or "@type", set
`isUrl` to `true`.
-
If `termType` is "@id" or "@vocab", set `isUrl` to `true`.
-
If `isUrl` is `true`, set `tableType` to "url".
-
Otherwise, if `termType` is defined, set `tableType` to `termType`.
-
Otherwise, set `tableType` to "none".
-
If `state.reverseTypeTable` has an entry for `tableType`:
-
Set `subTable` to the value of `tableType` in `state.reverseTypeTable`.
-
Set `useTable` to `false`.
-
If `valueToDecode` is a byte array and `state`.`typesEncodedAsBytes` has an entry
for `tableType`:
-
Set `useTable` to `true`.
-
Set `intValue` to the unsigned integer conversion of the `valueToDecode` bytes.
-
Otherwise, if `valueToDecode` is an integer and `state`.`typesEncodedAsBytes` does not
have an entry for `tableType`:
-
Set `useTable` to `true`.
-
Set `intValue` to `valueToDecode`.
-
If `useTable` is `true`:
-
If `intValue` is not in `subTable`, throw an error ERR_UNKNOWN_COMPRESSED_VALUE.
-
Otherwise, set `decoded` to the value of `intValue` in `subTable`.
-
Otherwise, if `valueToDecode` is a byte array and `tableType` is not "none", set
`decoded` to the integer conversion of `valueToDecode`.
-
If `decoded` is defined, initialize `decoderData` to an empty map, set `decoderData`.`decoded` to
the value of `decoded`, and return `decoderData`.
-
If `tableType` has an entry in `state.processingModeTypeDecoders`, set `DecoderData` to the result of
calling the `Create Decoder` algorithm associated with that entry's codec.
-
If `decoderData` is defined, return `decoderData`.
-
Otherwise, if `valueToDecode` is not an array, initialize `decoderData` to an empty map, set
`decoderData`.`decoded` to `valueToDecode`, and return `decoderData`.
Decode Value
This algorithm takes a map `decoderData`, and returns a value.
-
Return `decoderData`.`decoded`.
CBOR Tag Processing
Get Varint Structure Algorithm
This algorithm takes as input an integer `registryEntryId`, and returns a byte string `prefix`.
-
If `registryEntryId` is less than 128:
-
Set `varintEncoded` to the byte encoding of `registryEntryId`.
-
Set `prefix` to the result of appending `varintEncoded` to the end of the bytes
`0xD906`.
-
Otherwise:
-
Set `varintArray` to an array containing the varint representation of `registryEntryId`.
-
Set `varintTagValue` to `varintArray[0]` appended to the end of the bytes `0xD906`.
-
Set `varintBytesValue` to a CBOR byte string containing the rest of `varintArray` appended
to the end of the bytes `0x82`.
-
Set `prefix` to `varintBytesValue` appended to the end of `varintTagValue`.
-
Return `prefix`.
Get Registry Entry ID Algorithm
This algorithm takes an encoded CBOR-LD payload `cborldBytes` as input, and returns
`suffix`, the main data to be decoded, as well as the `registryEntryId` value that
should be used to decompress `suffix`.
-
If the CBOR tag on `cborldBytes` is not in the range `0x0600`-`0x06FF`, throw an
ERR_NON_CBOR_LD_TAG error.
-
Otherwise, if the CBOR tag on `cborldBytes` is in the range `0x0600`-`0x067F`, set `registryEntryId` to
the value of the last byte of the CBOR tag and set `suffix` to the portion of `cborldBytes` after the tag.
-
Otherwise:
-
If the last byte of the CBOR tag does not form the first byte of a valid varint, throw an
`ERR_INVALID_VARINT_VALUE` error.
-
If the CBOR tagged item is not an array containing exactly two elements, throw an `ERR_INVALID_VARINT_STRUCTURE`
error.
-
Otherwise, set the value of `registryEntryId` to the value of the varint for which the first byte is the last
byte of the CBOR tag and the rest of the varint is the first element in the two element array. Set `suffix` to the
value of the second element in the array.
-
Set `result` to be an empty map.
-
Set `result`.`suffix` to the value of `suffix` and `result`.`registryEntryId` to the value of `registryEntryId`.
-
Return `result`.