2 * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.yang.data.codec.binfmt;
11 * Magnesium encoding Node types. Encoded as a single byte, split as follows:
20 * <li>Bits 7 and 6 (most significant): predicate presence. Only valid for NODE_MAP_ENTRY and NODE_LEAF</li>
21 * <li>Bits 5 and 4: addressing mode</li>
22 * <li>Bits 3-0 (least significant) node type</li>
25 // TODO: restructure this into some concrete examples
26 //- a leaf referencing a previously-encoded NodeIdentifier would take
28 // (byte) NodeTypes.LEAF_NODE
29 // (byte) TokenTypes.IS_QNAME_CODE
31 //where as new tokens can do that in as few as 2 bytes:
32 // (byte) NodeType.(NODE_LEAF | ADDR_LOOKUP_1B)
34 //with worst-case being 5 bytes:
35 // (byte) NodeType.(NODE_LEAF | ADDR_LOOKUP_4B)
37 //- a map entry node referencing previously-encoded QNames and a single
38 //predicate would take a base of 15 bytes (not counting value object):
39 // (byte) NodeTypes.MAP_ENTRY_NODE
40 // (byte) TokenTypes.IS_QNAME_CODE
42 // (int) size of predicates
43 // (byte) TokenTypes.IS_QNAME_CODE
45 //whereas new tokens can do that in as few as 3 bytes:
46 // (byte) NodeType.(NODE_MAP_ENTRY | ADDR_LOOKUP_1B | PREDICATE_ONE)
49 //this ability is maintained for up to 255 predicates with:
50 // (byte) NodeType.(NODE_MAP_ENTRY | ADDR_LOOKUP_1B | PREDICATE_1B)
52 // (byte) size of predicates
53 // (byte) code value [0-255]
54 //- a leaf representing a key inside a map entry has the ability to skip
55 //value encoding by being as simple as:
56 // (byte) NodeTYpe.(NODE_LEAF | ADDR_LOOKUP_1B | PREDICATE_ONE)
59 final class MagnesiumNode {
61 * End of node marker. Does not support addressing modes.
63 static final byte NODE_END = 0x00; // N/A
65 * A leaf node. Encoding can specify {@link #PREDICATE_ONE}, which indicates the value is skipped as the encoder
66 * has emitted a parent MapNode, whose identifier contains the value.
68 static final byte NODE_LEAF = 0x01;
69 static final byte NODE_CONTAINER = 0x02;
70 static final byte NODE_LIST = 0x03;
71 static final byte NODE_MAP = 0x04;
72 static final byte NODE_MAP_ORDERED = 0x05;
73 static final byte NODE_LEAFSET = 0x06;
74 static final byte NODE_LEAFSET_ORDERED = 0x07;
75 static final byte NODE_CHOICE = 0x08;
76 static final byte NODE_AUGMENTATION = 0x09;
77 static final byte NODE_ANYXML = 0x0A;
78 static final byte NODE_LIST_ENTRY = 0x0B;
79 static final byte NODE_LEAFSET_ENTRY = 0x0C;
80 static final byte NODE_MAP_ENTRY = 0x0D;
82 // Note: unused as of yangtools-7.0.0
84 static final byte NODE_ANYXML_MODELED = 0x0E;
85 // 0x0F reserved for anydata
86 static final byte TYPE_MASK = 0x0F;
90 * Inherit identifier from parent. This addressing mode is applicable in:
92 * <li>{@link #NODE_END}, where an identifier is not applicable
93 * <li>{@link #NODE_LIST_ENTRY}, where the NodeIdentifier is inherited from parent {@link #NODE_LIST}</li>
94 * <li>{@link #NODE_MAP_ENTRY}, where the NodeIdentifier is inherited from parent {@link #NODE_MAP} or
95 * {@link #NODE_MAP_ORDERED}</li>
96 * <li>{@link #NODE_LEAFSET_ENTRY}, where the QName inherited from parent and the value is inferred from the
97 * next {@link MagnesiumValue} encoded</li>
100 static final byte ADDR_PARENT = 0x00;
102 * Define a new QName-based identifier constant. For {@link #NODE_AUGMENTATION} this is a set of QNames. Assign
103 * a new linear key to this constant.
105 static final byte ADDR_DEFINE = 0x10;
107 * Reference a previously {@link #ADDR_DEFINE}d identifier constant. This node byte is followed by an unsigned
108 * byte, which holds the linear key previously defined (i.e. 0-255).
110 static final byte ADDR_LOOKUP_1B = 0x20;
112 * Reference a previously {@link #ADDR_DEFINE}d identifier constant. This node byte is followed by a signed int,
113 * which holds the linear key previously defined.
115 static final byte ADDR_LOOKUP_4B = 0x30;
116 static final byte ADDR_MASK = ADDR_LOOKUP_4B;
119 * Predicate encoding: no predicates are present in a {@link #NODE_MAP_ENTRY}.
121 static final byte PREDICATE_ZERO = 0x00;
124 * Predicate encoding: a single predicate is present in a {@link #NODE_MAP_ENTRY}. In case of {@link #NODE_LEAF}
125 * encoded as part of a {@link #NODE_MAP_ENTRY} this bit indicates the <strong>value</strong> is not encoded and
126 * should be looked up from the map entry's predicates.
129 * The predicate is encoded as a {@link #ADDR_DEFINE} or {@link #ADDR_LOOKUP_1B}/{@link #ADDR_LOOKUP_4B},
130 * followed by an encoded {@link MagnesiumValue}.
132 static final byte PREDICATE_ONE = 0x40;
135 * Predicate encoding: 0-255 predicates are present, as specified by the following {@code unsigned byte}. This
136 * encoding is expected to be exceedingly rare. This should not be used to encode 0 or 1 predicate, those cases
137 * should be encoded as:
139 * <li>no PREDICATE_* set when there are no predicates (probably not valid anyway)</li>
140 * <li><{@link #PREDICATE_ONE} if there is only one predicate</li>
143 static final byte PREDICATE_1B = (byte) 0x80;
146 * Predicate encoding 0 - {@link Integer#MAX_VALUE} predicates are present, as specified by the following
147 * {@code int}. This should not be used where 0-255 predicates are present.
149 static final byte PREDICATE_4B = (byte) (PREDICATE_ONE | PREDICATE_1B);
150 static final byte PREDICATE_MASK = PREDICATE_4B;
152 private MagnesiumNode() {