Zum Hauptinhalt springen

3. Specification of the CBOR Encoding (CBOR-Kodierungsspezifikation)

CBOR-Datenelemente (Abschnitt 2) werden in oder aus Byte-Strings kodiert oder dekodiert, die wohlgeformte kodierte Datenelemente enthalten, wie in diesem Abschnitt beschrieben. Die Kodierung ist in Tabelle 7 in Anhang B zusammengefasst, indiziert nach dem initialen Byte. Encoder müssen (MUST) nur wohlgeformte kodierte Datenelemente erzeugen. Wenn ein Decoder auf eine Eingabe trifft, die kein wohlgeformtes kodiertes CBOR-Datenelement ist, darf er (MUST NOT) ein dekodiertes Datenelement zurückgeben (dies schmälert nicht die Nützlichkeit von Diagnose- und Wiederherstellungstools, die möglicherweise einige Informationen aus beschädigten kodierten CBOR-Datenelementen bereitstellen).

Das initiale Byte (Initial Byte) jedes kodierten Datenelements enthält Informationen über den Haupttyp (Major Type, obere 3 Bits, beschrieben in Abschnitt 3.1) und zusätzliche Informationen (Additional Information, untere 5 Bits). Mit wenigen Ausnahmen beschreibt der Wert der zusätzlichen Informationen, wie eine vorzeichenlose Ganzzahl als "Argument" (Argument) geladen wird:

Kleiner als 24: Der Wert des Arguments ist der Wert der zusätzlichen Information.

24, 25, 26 oder 27: Der Wert des Arguments wird in den folgenden 1, 2, 4 oder 8 Bytes gespeichert, in Netzwerk-Byte-Reihenfolge. Für Haupttyp 7 und zusätzliche Informationswerte 25, 26, 27 werden diese Bytes nicht als Ganzzahl-Argument verwendet, sondern als Fließkommawert (siehe Abschnitt 3.3).

28, 29, 30: Diese Werte sind für zukünftige Erweiterungen des CBOR-Formats reserviert. Im aktuellen Version von CBOR ist das kodierte Element nicht wohlgeformt.

31: Es wird kein Argumentwert abgeleitet. Wenn der Haupttyp 0, 1 oder 6 ist, ist das kodierte Element nicht wohlgeformt. Für Haupttypen 2 bis 5 ist die Länge des Elements unbestimmt (Indefinite), für Haupttyp 7 bildet dieses Byte überhaupt kein Datenelement, sondern beendet ein Element mit unbestimmter Länge; all dies wird in Abschnitt 3.2 beschrieben.

Das initiale Byte und alle zusätzlichen Bytes, die zum Konstruieren des Arguments verbraucht werden, werden zusammen als Kopf (Head) des Datenelements bezeichnet.

Die Bedeutung dieses Arguments hängt vom Haupttyp ab. Zum Beispiel ist im Haupttyp 0 das Argument der Wert des Datenelements selbst (in Haupttyp 1 wird der Wert des Datenelements aus dem Argument berechnet); in Haupttypen 2 und 3 gibt es die Byte-Länge der folgenden String-Daten an; in Haupttypen 4 und 5 wird es verwendet, um die Anzahl der eingeschlossenen Datenelemente zu bestimmen.

Wenn die kodierte Byte-Sequenz endet, bevor das Datenelement vollständig ist, ist das Element nicht wohlgeformt. Wenn nach dem Dekodieren des äußersten kodierten Elements noch Bytes in der kodierten Byte-Sequenz verbleiben, ist die Kodierung kein einzelnes wohlgeformtes CBOR-Element. Abhängig von der Anwendung kann der Decoder die Kodierung als nicht wohlgeformt betrachten oder nur die Startposition der verbleibenden Bytes an die Anwendung melden.

CBOR-Decoder-Implementierungen können auf einer Sprungtabelle (Jump Table) basieren, die alle 256 definierten Werte des initialen Bytes enthält (Tabelle 7). Decoder in eingeschränkten Implementierungen können die Struktur des initialen Bytes und nachfolgender Bytes verwenden, um kompakteren Code zu implementieren (siehe Anhang C für dessen ungefähres Aussehen).

3.1. Major Types (Haupttypen)

Im Folgenden sind die Haupttypen sowie die typbezogenen zusätzlichen Informationen und anderen Bytes aufgeführt.

Haupttyp 0 (Major type 0):

Vorzeichenlose Ganzzahl (Unsigned Integer) im Bereich 0..2^64-1 (inklusive). Der Wert des kodierten Elements ist das Argument selbst. Zum Beispiel wird die Ganzzahl 10 als einzelnes Byte 0b000_01010 (Haupttyp 0, zusätzliche Information 10) dargestellt. Die Ganzzahl 500 wäre 0b000_11001 (Haupttyp 0, zusätzliche Information 25) gefolgt von zwei Bytes 0x01f4, was dezimal 500 ist.

Haupttyp 1 (Major type 1):

Negative Ganzzahl (Negative Integer) im Bereich -2^64..-1 (inklusive). Der Wert des Elements ist -1 minus das Argument. Zum Beispiel wäre die Ganzzahl -500 0b001_11001 (Haupttyp 1, zusätzliche Information 25) gefolgt von zwei Bytes 0x01f3, was dezimal 499 ist.

Haupttyp 2 (Major type 2):

Byte-String (Byte String). Die Anzahl der Bytes im String entspricht dem Argument. Zum Beispiel hätte ein Byte-String mit einer Länge von 5 ein initiales Byte von 0b010_00101 (Haupttyp 2, zusätzliche Information 5 für die Länge), gefolgt von 5 Bytes binären Inhalts. Ein Byte-String mit einer Länge von 500 hätte 3 initiale Bytes 0b010_11001 (Haupttyp 2, zusätzliche Information 25 für Zwei-Byte-Länge) gefolgt von zwei Bytes 0x01f4 für die Länge 500, dann gefolgt von 500 Bytes binären Inhalts.

Haupttyp 3 (Major type 3):

Text-String (Text String), kodiert in UTF-8 [RFC3629] (Abschnitt 2). Die Anzahl der Bytes im String entspricht dem Argument. Strings, die ungültige UTF-8-Sequenzen enthalten, sind wohlgeformt, aber ungültig (Abschnitt 1.2). Dieser Typ wird für Systeme bereitgestellt, die menschenlesbaren Text interpretieren oder anzeigen müssen, und ermöglicht die Unterscheidung zwischen unstrukturierten Bytes und Text mit einem spezifizierten Zeichensatz (Unicode) und einer Kodierung (UTF-8). Im Gegensatz zu Formaten wie JSON werden Unicode-Zeichen in diesem Typ niemals escaped. Daher wird das Zeilenumbruchzeichen (U+000A) immer als Byte 0x0a im String dargestellt, nicht als Bytes 0x5c6e (Zeichen "\" und "n") oder 0x5c7530303061 (Zeichen "\", "u", "0", "0", "0" und "a").

Haupttyp 4 (Major type 4):

Array von Datenelementen (Array). In anderen Formaten werden Arrays auch als Listen (List), Sequenzen (Sequence) oder Tupel (Tuple) bezeichnet ("CBOR sequence" ist etwas anderes, siehe [RFC8742]). Das Argument ist die Anzahl der Datenelemente im Array. Die Elemente im Array müssen nicht alle vom selben Typ sein. Zum Beispiel hätte ein Array mit 10 Elementen beliebigen Typs ein initiales Byte von 0b100_01010 (Haupttyp 4, zusätzliche Information 10 für die Länge), gefolgt von den 10 verbleibenden Elementen.

Haupttyp 5 (Major type 5):

Map von Datenelementpaaren (Map). Maps werden auch als Tabellen (Table), Wörterbücher (Dictionary), Hashes (Hash) oder Objekte (Object, in JSON) bezeichnet. Eine Map besteht aus Datenelementpaaren, wobei jedes Paar einen Schlüssel (Key) enthält, gefolgt von einem Wert (Value). Das Argument ist die Anzahl der Datenelementepaare in der Map. Zum Beispiel hätte eine Map mit 9 Paaren ein initiales Byte von 0b101_01001 (Haupttyp 5, zusätzliche Information 9 für Paare), gefolgt von den 18 verbleibenden Elementen. Das erste Element ist der erste Schlüssel, das zweite Element ist der erste Wert, das dritte Element ist der zweite Schlüssel und so weiter. Da die Elemente in einer Map paarweise auftreten, ist ihre Gesamtanzahl immer gerade: Eine Map, die eine ungerade Anzahl von Elementen enthält (ohne Wertdatenelement nach dem letzten Schlüsseldatenelement), ist nicht wohlgeformt. Eine Map mit doppelten Schlüsseln kann wohlgeformt sein, ist aber nicht gültig und führt zu unbestimmter Dekodierung; siehe auch Abschnitt 5.6.

Haupttyp 6 (Major type 6):

Tagged Data Item (Tagged Data Item, "tag"), dessen Tag-Nummer (Tag Number) eine Ganzzahl im Bereich 0..2^64-1 (inklusive) ist, die das Argument ist, und dessen eingeschlossenes Datenelement (Tag-Inhalt, Tag Content) das einzelne kodierte Datenelement nach dem Kopf ist. Siehe Abschnitt 3.4.

Haupttyp 7 (Major type 7):

Fließkommazahlen und einfache Werte sowie der "break"-Stop-Code. Siehe Abschnitt 3.3.

Diese acht Haupttypen bilden eine einfache Tabelle, die zeigt, welche der 256 möglichen Werte des initialen Bytes eines Datenelements verwendet werden (Tabelle 7).

In den Haupttypen 6 und 7 sind viele mögliche Werte für zukünftige Spezifikationen reserviert. Weitere Informationen zu diesen Werten finden Sie in Abschnitt 9.

Tabelle 1 fasst die von CBOR definierten Haupttypen zusammen, wobei Abschnitt 3.2 vorübergehend ignoriert wird. Die Zahl N in dieser Tabelle steht für das Argument.

+============+=======================+=========================+
| Haupttyp | Bedeutung | Inhalt |
+============+=======================+=========================+
| 0 | Vorzeichenlose | - |
| | Ganzzahl N | |
+------------+-----------------------+-------------------------+
| 1 | Negative Ganzzahl | - |
| | -1-N | |
+------------+-----------------------+-------------------------+
| 2 | Byte-String | N Bytes |
+------------+-----------------------+-------------------------+
| 3 | Text-String | N Bytes (UTF-8-Text) |
+------------+-----------------------+-------------------------+
| 4 | Array | N Datenelemente |
| | | (Elemente) |
+------------+-----------------------+-------------------------+
| 5 | Map | 2N Datenelemente |
| | | (Schlüssel/Wert-Paare) |
+------------+-----------------------+-------------------------+
| 6 | Tag mit Nummer N | 1 Datenelement |
+------------+-----------------------+-------------------------+
| 7 | Einfacher Wert/ | - |
| | Fließkommazahl | |
+------------+-----------------------+-------------------------+

Tabelle 1: Übersicht über die Verwendung fester Längen der CBOR-Haupttypen (N = Argument)

3.2. Indefinite Lengths for Some Major Types (Unbestimmte Längen für einige Haupttypen)

Vier CBOR-Elemente (Arrays, Maps, Byte-Strings und Text-Strings) können mit unbestimmter Länge (Indefinite Length) unter Verwendung des zusätzlichen Informationswerts 31 kodiert werden. Dies ist nützlich, wenn die Kodierung dieses Elements begonnen werden muss, bevor die Anzahl der Elemente in einem Array oder einer Map oder die Gesamtlänge eines Strings bekannt ist. (Die Fähigkeit, mit dem Senden eines Datenelements zu beginnen, bevor der gesamte Inhalt des Datenelements bekannt ist, wird innerhalb dieses Datenelements oft als "Streaming" bezeichnet).

Unbestimmt lange Arrays und Maps werden anders behandelt als unbestimmt lange Strings (Byte-Strings und Text-Strings).

3.2.1. The "break" Stop Code ("break"-Stop-Code)

Der "break"-Stop-Code wird mit Haupttyp 7 und zusätzlichem Informationswert 31 (0b111_11111) kodiert. Er ist selbst kein Datenelement: Er ist nur ein syntaktisches Merkmal zum Schließen eines Elements mit unbestimmter Länge.

Wenn der "break"-Stop-Code an einer Position erscheint, an der ein Datenelement erwartet wird, aber nicht direkt innerhalb eines unbestimmt langen Strings, Arrays oder einer Map – zum Beispiel direkt innerhalb eines Arrays oder einer Map fester Länge – ist das enthaltende Element nicht wohlgeformt.

3.2.2. Indefinite-Length Arrays and Maps (Arrays und Maps mit unbestimmter Länge)

Unbestimmt lange Arrays und Maps werden mit ihrem Haupttyp und dem zusätzlichen Informationswert 31 angegeben, gefolgt von einer beliebig langen Sequenz von null oder mehr Elementen für Arrays oder Schlüssel/Wert-Paaren für Maps, schließlich abgeschlossen durch einen "break"-Stop-Code (Abschnitt 3.2.1). Mit anderen Worten, unbestimmt lange Arrays und Maps sehen genauso aus wie andere Arrays und Maps, außer dass sie mit dem zusätzlichen Informationswert 31 beginnen und mit einem "break"-Stop-Code enden.

3.2.3. Indefinite-Length Byte Strings and Text Strings (Byte-Strings und Text-Strings mit unbestimmter Länge)

Kodierung unbestimmt langer Strings:

  • Haupttyp-Byte (zusätzlicher Informationswert 31) + null oder mehr String-Blöcke fester Länge + "break"-Stop-Code
  • Das endgültige Datenelement ist die Verkettung aller Blöcke
  • Zwischen Blöcken können keine unbestimmt langen Strings verschachtelt werden
  • Jeder Block eines Text-Strings muss an einer Unicode-Codepunkt-Grenze beginnen (UTF-8-Bytes können nicht über Blöcke hinweg aufgeteilt werden)

Beispiel:

5F              -- Beginn unbestimmt langer Byte-String
44 -- Byte-String mit Länge 4
aabbccdd -- Byte-Inhalt
43 -- Byte-String mit Länge 3
eeff99 -- Byte-Inhalt
FF -- "break"

Dekodierungsergebnis: Ein einzelner 7-Byte-Byte-String 0xaabbccddeeff99

3.2.4. Summary of Indefinite-Length Use of Major Types (Zusammenfassung der Verwendung unbestimmter Längen)

Tabelle 2: Verwendung unbestimmter Längen der Haupttypen (zusätzliche Information = 31)

HaupttypBedeutungInhalt vor "break"
0(nicht wohlgeformt)-
1(nicht wohlgeformt)-
2Byte-StringByte-Strings fester Länge
3Text-StringText-Strings fester Länge
4ArrayDatenelemente (Elemente)
5MapDatenelemente (Schlüssel/Wert-Paare)
6(nicht wohlgeformt)-
7"break"-Stop-Code-

Hauptpunkte:

  • Haupttypen 0, 1, 6 unterstützen keine unbestimmte Länge
  • Haupttypen 2-5 unterstützen Kodierung mit unbestimmter Länge
  • Unbestimmte Länge ermöglicht Streaming, wobei die Kodierung vor Kenntnis der Gesamtlänge beginnt

3.3. Floating-Point Numbers and Values with No Content (Fließkommazahlen und Werte ohne Inhalt)

Spezielle Verwendung von Haupttyp 7:

Haupttyp 7 wird zur Kodierung von Fließkommazahlen und einfachen Werten verwendet:

Einfache Werte (Simple Values):

  • false (20), true (21), null (22), undefined (23)
  • Zusätzliche Information 0-19: Nicht zugewiesene einfache Werte
  • Zusätzliche Information 24: Ein-Byte-Erweiterung für einfache Werte (Werte 32-255)

Fließkomma-Kodierung:

  • Zusätzliche Information 25: Halbpräzisions-Fließkommazahl (IEEE 754 binary16, 2 Bytes)
  • Zusätzliche Information 26: Einfachpräzisions-Fließkommazahl (IEEE 754 binary32, 4 Bytes)
  • Zusätzliche Information 27: Doppelpräzisions-Fließkommazahl (IEEE 754 binary64, 8 Bytes)

Beispiele für spezielle Werte:

  • false: 0xF4
  • true: 0xF5
  • null: 0xF6
  • undefined: 0xF7
  • Fließkommazahl 0.0: 0xF90000 (Halbpräzision) oder 0xFA00000000 (Einfachpräzision)

Design-Überlegungen:

  • Bietet mehrere Präzisionsoptionen zur Optimierung der Kodierungsgröße
  • Unterstützt alle IEEE 754-Spezialwerte (NaN, Infinity usw.)
  • Einfache Werte bieten kompakte Kodierung für gängige boolesche und Nullwerte

3.4. Tagging of Items (Kennzeichnung von Elementen)

Der Tag-Mechanismus (Tags) wird verwendet, um semantische Informationen zu Datenelementen hinzuzufügen.

Tag-Struktur:

  • Haupttyp 6 + Tag-Nummer (als Argument) + Tag-Inhalt (ein Datenelement)
  • Tag-Nummernbereich: 0 bis 2^64-1

Beispiele für Standard-Tags:

Tag-Nr.SemantikBeispiel
0RFC 3339 Datum-Zeit-String"2013-03-21T20:04:00Z"
1Unix-Zeitstempel (Epoch-Sekunden)1363896240
2Positive Bignum (Positive Bignum)18446744073709551616
3Negative Bignum (Negative Bignum)-18446744073709551617
4Dezimalbruch[e, m] bedeutet m×10^e
5Bigfloat (Bigfloat)[e, m] bedeutet m×2^e

3.4.1-3.4.6 Detaillierte Tag-Typen

Datum-Zeit-Tags (0 und 1):

  • Tag 0: Datum-Zeit im Textformat (RFC 3339-Format)
  • Tag 1: Zeitstempel im numerischen Format (Unix-Epoch-Sekunden)

Bignum-Tags (2 und 3):

  • Zur Darstellung von Zahlen außerhalb des 64-Bit-Ganzzahlbereichs
  • Tag-Inhalt ist ein Byte-String, der den Zahlenwert in Big-Endian-Reihenfolge darstellt

Zahlenerweiterungs-Tags (4 und 5):

  • Dezimalbruch: Präzise Darstellung von Dezimalzahlen
  • Bigfloat: Binäre Fließkommazahlen beliebiger Präzision

Andere häufig verwendete Tags:

  • Tags 21-23: Base64-Kodierungshinweise
  • Tag 24: Kodiertes CBOR-Datenelement
  • Tag 32: URI
  • Tag 55799: Selbstbeschreibende CBOR-Identifikation

Erweiterbarkeit:

  • Tags werden von der IANA-Registrierung verwaltet
  • Anwendungen können private Tags definieren (Konflikte vermeiden)
  • Decoder können Tags selektiv unterstützen, unbekannte Tags können an die Anwendung weitergegeben werden

Zusammenfassung von Kapitel 3:

Dieses Kapitel definiert die vollständige Kodierungsspezifikation von CBOR, einschließlich:

  1. Kodierungsregeln für 8 Haupttypen
  2. Kodierungsmechanismus für unbestimmte Längen
  3. Darstellung von Fließkommazahlen und einfachen Werten
  4. Tag-Erweiterungssystem

Diese Designs machen CBOR sowohl kompakt als auch flexibel und eignen sich für das Internet der Dinge und eingeschränkte Umgebungen.