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.
This document is experimental.
There is a
reference implementation that is
capable of demonstrating the features described in this document.
CBOR Tags for CBOR-LD
CBOR-LD payloads need to be identifiable as such at the binary level. CBOR natively supports
this via its "tag" feature — a header value in the binary data that describes the rest of the
payload via a global registry.
To this end, the CBOR tag `0xCB1D` (tag value `51997`) has been registered
at the
IANA CBOR tag registry to be used for CBOR-LD. The data that immediately
follows this tag value identifies the use-case-specific registry entry (if
any) that was used to create the compressed payload.
CBOR-LD payloads MUST be structured such that the item tagged with tag `0xCB1D` is
a two-element array, and the first element MUST be a
major type 0 integer.
This integer is a CBOR-LD Registry Entry ID. The binary structure is `tag([registryEntryId, payload])`.
The value of the CBOR-LD Registry Entry ID is then used to look up a CBOR-LD Registry Entry
in the CBOR-LD Registry.
CBOR-LD Registry
To enable unbounded extension on possible use cases for CBOR-LD that require different
compression table material for consumption while working with a single
CBOR tag value, we define the following.
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 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` (use-case-specific compression tables for
compressing typed values rather than JSON-LD terms) are to be used for this registry entry.
-
`processingModel`: what processing model is used for this registry entry. A processing model
specifies the following:
-
Whether or not semantic compression is used for dynamic JSON-LD term compression,
-
What codecs are used for dynamic typed value compression.
The `default` processing model uses semantic compression and includes the codecs specified in this document.
-
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 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 current CBOR-LD Registry can be found here.
To register an entry, follow the instructions in the README. The registry is owned by the W3C JSON-LD Community Group.
Algorithms
In this section, we specify the algorithms required to convert JSON-LD to CBOR-LD
and vice versa. The majority of the algorithms in this section relate to the semantic
compression feature and are not used in conversions between CBOR-LD and JSON-LD where
the CBOR-LD payload does not use semantic compression.
Encoding and Decoding
JSON-LD to CBOR-LD Encoding 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.
-
If the registry entry associated with `registryEntryId` requires semantic compression:
-
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`.
-
Otherwise, set `suffix` to the CBOR encoding of `jsonldDocument`.
-
Set `cborldBytes` to a hexidecimal encoding of `prefix` prepended to `suffix`.
-
Return `cborldBytes`.
CBOR-LD to JSON-LD Decoding Algorithm
This algorithm takes a CBOR-LD payload `cborldBytes`, and returns a JSON-LD document `jsonldDocument`.
-
Set `result` to the result of passing `cborldBytes` to
.
-
Set `state`.`registryEntryId` to `result`.`registryEntryId` and `suffix` to `result`.`suffix`.
-
Set `state` to an empty map.
-
If the registry entry associated with `state`.`registryEntryId` uses semantic compression:
-
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 .
-
Otherwise, set `jsonldDocument` to the result of parsing `cborldBytes`.
-
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 CBOR Tag Structure Algorithm
This algorithm takes as input an integer `registryEntryId`, and returns a byte string `prefix`.
-
Set `registryEntryBytes` to the CBOR encoding of `registryEntryID`
-
Set `prefix` to the result of appending `registryEntryBytes` to the end
of the bytestring `0xD9CB1D82`.
-
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 `0xCB1D` (tag value 51997),
throw an `ERR_NON_CBOR_LD_TAG` error.
-
If the tagged item is not an array of two elements where the first is a CBOR integer,
throw an `ERR_INVALID_PAYLOAD_STRUCTURE` error.
-
Set the value of `registryEntryId` to the value of the integer at index 0 of the tagged
array.
-
Set the value of `suffix` to the value of the second element of 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`.