xref: /openbmc/libbej/src/bej_encoder_core.c (revision 6df0c486)
199bd6c90Skasunath #include "bej_encoder_core.h"
299bd6c90Skasunath 
399bd6c90Skasunath #include "bej_common.h"
499bd6c90Skasunath #include "bej_encoder_metadata.h"
599bd6c90Skasunath 
699bd6c90Skasunath #include <stdio.h>
799bd6c90Skasunath #include <string.h>
899bd6c90Skasunath 
999bd6c90Skasunath /**
1099bd6c90Skasunath  * @brief Encode a unsigned value with nnint format.
1199bd6c90Skasunath  */
bejEncodeNnint(uint64_t value,struct BejEncoderOutputHandler * output)1299bd6c90Skasunath static int bejEncodeNnint(uint64_t value,
1399bd6c90Skasunath                           struct BejEncoderOutputHandler* output)
1499bd6c90Skasunath {
1599bd6c90Skasunath     // The length of the value bytes in nnint.
1699bd6c90Skasunath     uint8_t nnintLengthByte = bejNnintLengthFieldOfUInt(value);
1799bd6c90Skasunath     RETURN_IF_IERROR(output->recvOutput(&nnintLengthByte, sizeof(uint8_t),
1899bd6c90Skasunath                                         output->handlerContext));
1999bd6c90Skasunath     // Write the nnint value bytes.
2099bd6c90Skasunath     return output->recvOutput(&value, nnintLengthByte, output->handlerContext);
2199bd6c90Skasunath }
2299bd6c90Skasunath 
2399bd6c90Skasunath /**
2499bd6c90Skasunath  * @brief Encode a BejTupleF type.
2599bd6c90Skasunath  */
bejEncodeFormat(const struct BejTupleF * format,struct BejEncoderOutputHandler * output)2699bd6c90Skasunath static int bejEncodeFormat(const struct BejTupleF* format,
2799bd6c90Skasunath                            struct BejEncoderOutputHandler* output)
2899bd6c90Skasunath {
2999bd6c90Skasunath     return output->recvOutput(format, sizeof(struct BejTupleF),
3099bd6c90Skasunath                               output->handlerContext);
3199bd6c90Skasunath }
3299bd6c90Skasunath 
3399bd6c90Skasunath /**
3499bd6c90Skasunath  * @brief Encode a BejSet or BejArray type.
3599bd6c90Skasunath  */
bejEncodeBejSetOrArray(struct RedfishPropertyParent * node,struct BejEncoderOutputHandler * output)3699bd6c90Skasunath static int bejEncodeBejSetOrArray(struct RedfishPropertyParent* node,
3799bd6c90Skasunath                                   struct BejEncoderOutputHandler* output)
3899bd6c90Skasunath {
3999bd6c90Skasunath     // Encode Sequence number.
4099bd6c90Skasunath     RETURN_IF_IERROR(bejEncodeNnint(node->metaData.sequenceNumber, output));
4199bd6c90Skasunath     // Add the format.
4299bd6c90Skasunath     RETURN_IF_IERROR(bejEncodeFormat(&node->nodeAttr.format, output));
4399bd6c90Skasunath     // Encode the value length.
4499bd6c90Skasunath     RETURN_IF_IERROR(bejEncodeNnint(node->metaData.vSize, output));
4599bd6c90Skasunath     // Encode the child count
4699bd6c90Skasunath     return bejEncodeNnint(node->nChildren, output);
4799bd6c90Skasunath }
4899bd6c90Skasunath 
4999bd6c90Skasunath /**
500a29193fSkasunath  * @brief Encode an integer to bejInteger type.
510a29193fSkasunath  */
bejEncodeInteger(int64_t val,struct BejEncoderOutputHandler * output)520a29193fSkasunath static uint8_t bejEncodeInteger(int64_t val,
530a29193fSkasunath                                 struct BejEncoderOutputHandler* output)
540a29193fSkasunath {
550a29193fSkasunath     uint8_t copyLength = bejIntLengthOfValue(val);
560a29193fSkasunath     return output->recvOutput(&val, copyLength, output->handlerContext);
570a29193fSkasunath }
580a29193fSkasunath 
590a29193fSkasunath /**
600a29193fSkasunath  * @brief Encode a BejInteger type.
610a29193fSkasunath  */
bejEncodeBejInteger(struct RedfishPropertyLeafInt * node,struct BejEncoderOutputHandler * output)620a29193fSkasunath int bejEncodeBejInteger(struct RedfishPropertyLeafInt* node,
630a29193fSkasunath                         struct BejEncoderOutputHandler* output)
640a29193fSkasunath {
650a29193fSkasunath     // Encode Sequence number.
660a29193fSkasunath     RETURN_IF_IERROR(
670a29193fSkasunath         bejEncodeNnint(node->leaf.metaData.sequenceNumber, output));
680a29193fSkasunath     // Add the format.
690a29193fSkasunath     RETURN_IF_IERROR(bejEncodeFormat(&node->leaf.nodeAttr.format, output));
700a29193fSkasunath     // Encode the value length.
710a29193fSkasunath     RETURN_IF_IERROR(bejEncodeNnint(node->leaf.metaData.vSize, output));
720a29193fSkasunath     // Encode the value.
730a29193fSkasunath     return bejEncodeInteger(node->value, output);
740a29193fSkasunath }
750a29193fSkasunath 
760a29193fSkasunath /**
770a29193fSkasunath  * @brief Encode a BejEnum type.
780a29193fSkasunath  */
bejEncodeBejEnum(struct RedfishPropertyLeafEnum * node,struct BejEncoderOutputHandler * output)790a29193fSkasunath int bejEncodeBejEnum(struct RedfishPropertyLeafEnum* node,
800a29193fSkasunath                      struct BejEncoderOutputHandler* output)
810a29193fSkasunath {
820a29193fSkasunath     // S: Encode Sequence number.
830a29193fSkasunath     RETURN_IF_IERROR(
840a29193fSkasunath         bejEncodeNnint(node->leaf.metaData.sequenceNumber, output));
850a29193fSkasunath     // F: Add the format.
860a29193fSkasunath     RETURN_IF_IERROR(bejEncodeFormat(&node->leaf.nodeAttr.format, output));
870a29193fSkasunath     // L: Encode the value length.
880a29193fSkasunath     RETURN_IF_IERROR(bejEncodeNnint(node->leaf.metaData.vSize, output));
890a29193fSkasunath     // V: Encode the value.
900a29193fSkasunath     return bejEncodeNnint(node->enumValueSeq, output);
910a29193fSkasunath }
920a29193fSkasunath 
bejEncodeBejString(struct RedfishPropertyLeafString * node,struct BejEncoderOutputHandler * output)93*6df0c486Skasunath int bejEncodeBejString(struct RedfishPropertyLeafString* node,
94*6df0c486Skasunath                        struct BejEncoderOutputHandler* output)
95*6df0c486Skasunath {
96*6df0c486Skasunath     // S: Encode Sequence number.
97*6df0c486Skasunath     RETURN_IF_IERROR(
98*6df0c486Skasunath         bejEncodeNnint(node->leaf.metaData.sequenceNumber, output));
99*6df0c486Skasunath     // F: Add the format.
100*6df0c486Skasunath     RETURN_IF_IERROR(bejEncodeFormat(&node->leaf.nodeAttr.format, output));
101*6df0c486Skasunath     // L: Encode the value length.
102*6df0c486Skasunath     RETURN_IF_IERROR(bejEncodeNnint(node->leaf.metaData.vSize, output));
103*6df0c486Skasunath     // V: Encode the value.
104*6df0c486Skasunath     return output->recvOutput((void*)node->value, node->leaf.metaData.vSize,
105*6df0c486Skasunath                               output->handlerContext);
106*6df0c486Skasunath }
107*6df0c486Skasunath 
bejEncodeBejReal(struct RedfishPropertyLeafReal * node,struct BejEncoderOutputHandler * output)108*6df0c486Skasunath int bejEncodeBejReal(struct RedfishPropertyLeafReal* node,
109*6df0c486Skasunath                      struct BejEncoderOutputHandler* output)
110*6df0c486Skasunath {
111*6df0c486Skasunath     // S: Encode Sequence number.
112*6df0c486Skasunath     RETURN_IF_IERROR(
113*6df0c486Skasunath         bejEncodeNnint(node->leaf.metaData.sequenceNumber, output));
114*6df0c486Skasunath     // F: Add the format.
115*6df0c486Skasunath     RETURN_IF_IERROR(bejEncodeFormat(&node->leaf.nodeAttr.format, output));
116*6df0c486Skasunath     // L: Encode the value length.
117*6df0c486Skasunath     RETURN_IF_IERROR(bejEncodeNnint(node->leaf.metaData.vSize, output));
118*6df0c486Skasunath     // V: Encode the value.
119*6df0c486Skasunath     // Length of the "whole" value as nnint.
120*6df0c486Skasunath     RETURN_IF_IERROR(
121*6df0c486Skasunath         bejEncodeNnint(bejIntLengthOfValue(node->bejReal.whole), output));
122*6df0c486Skasunath     // Add the "whole" value.
123*6df0c486Skasunath     RETURN_IF_IERROR(bejEncodeInteger(node->bejReal.whole, output));
124*6df0c486Skasunath     // Leading zero count as a nnint.
125*6df0c486Skasunath     RETURN_IF_IERROR(bejEncodeNnint(node->bejReal.zeroCount, output));
126*6df0c486Skasunath     // Fraction as a nnint.
127*6df0c486Skasunath     RETURN_IF_IERROR(bejEncodeNnint(node->bejReal.fract, output));
128*6df0c486Skasunath     // Exp length as a nnint.
129*6df0c486Skasunath     RETURN_IF_IERROR(bejEncodeNnint(node->bejReal.expLen, output));
130*6df0c486Skasunath     if (node->bejReal.expLen > 0)
131*6df0c486Skasunath     {
132*6df0c486Skasunath         // Exp length as a nnint.
133*6df0c486Skasunath         RETURN_IF_IERROR(bejEncodeNnint(node->bejReal.expLen, output));
134*6df0c486Skasunath         RETURN_IF_IERROR(bejEncodeInteger(node->bejReal.exp, output));
135*6df0c486Skasunath     }
136*6df0c486Skasunath     return 0;
137*6df0c486Skasunath }
138*6df0c486Skasunath 
bejEncodeBejBool(struct RedfishPropertyLeafBool * node,struct BejEncoderOutputHandler * output)139*6df0c486Skasunath int bejEncodeBejBool(struct RedfishPropertyLeafBool* node,
140*6df0c486Skasunath                      struct BejEncoderOutputHandler* output)
141*6df0c486Skasunath {
142*6df0c486Skasunath     // S: Encode Sequence number.
143*6df0c486Skasunath     RETURN_IF_IERROR(
144*6df0c486Skasunath         bejEncodeNnint(node->leaf.metaData.sequenceNumber, output));
145*6df0c486Skasunath     // F: Add the format.
146*6df0c486Skasunath     RETURN_IF_IERROR(bejEncodeFormat(&node->leaf.nodeAttr.format, output));
147*6df0c486Skasunath     // L: Encode the value length.
148*6df0c486Skasunath     RETURN_IF_IERROR(bejEncodeNnint(node->leaf.metaData.vSize, output));
149*6df0c486Skasunath     // V: Encode the value.
150*6df0c486Skasunath     uint8_t value = node->value ? 0xFF : 0x00;
151*6df0c486Skasunath     return output->recvOutput(&value, /*data_size=*/sizeof(uint8_t),
152*6df0c486Skasunath                               output->handlerContext);
153*6df0c486Skasunath }
154*6df0c486Skasunath 
bejEncodeBejProAnno(struct RedfishPropertyParent * node,struct BejEncoderOutputHandler * output)155*6df0c486Skasunath int bejEncodeBejProAnno(struct RedfishPropertyParent* node,
156*6df0c486Skasunath                         struct BejEncoderOutputHandler* output)
157*6df0c486Skasunath {
158*6df0c486Skasunath     // Encode Sequence number.
159*6df0c486Skasunath     RETURN_IF_IERROR(bejEncodeNnint(node->metaData.sequenceNumber, output));
160*6df0c486Skasunath     // Add the format.
161*6df0c486Skasunath     RETURN_IF_IERROR(bejEncodeFormat(&node->nodeAttr.format, output));
162*6df0c486Skasunath     // Encode the value length.
163*6df0c486Skasunath     return bejEncodeNnint(node->metaData.vSize, output);
164*6df0c486Skasunath }
165*6df0c486Skasunath 
1660a29193fSkasunath /**
1670a29193fSkasunath  * @brief Encode a BejNull type.
1680a29193fSkasunath  */
bejEncodeBejNull(struct RedfishPropertyLeafNull * node,struct BejEncoderOutputHandler * output)1690a29193fSkasunath int bejEncodeBejNull(struct RedfishPropertyLeafNull* node,
1700a29193fSkasunath                      struct BejEncoderOutputHandler* output)
1710a29193fSkasunath {
1720a29193fSkasunath     // S: Encode Sequence number.
1730a29193fSkasunath     RETURN_IF_IERROR(
1740a29193fSkasunath         bejEncodeNnint(node->leaf.metaData.sequenceNumber, output));
1750a29193fSkasunath     // F: Add the format.
1760a29193fSkasunath     RETURN_IF_IERROR(bejEncodeFormat(&node->leaf.nodeAttr.format, output));
1770a29193fSkasunath     // L: Encode the value length.
1780a29193fSkasunath     return bejEncodeNnint(node->leaf.metaData.vSize, output);
1790a29193fSkasunath }
1800a29193fSkasunath 
1810a29193fSkasunath /**
18299bd6c90Skasunath  * @brief Encode the provided node.
18399bd6c90Skasunath  */
bejEncodeNode(void * node,struct BejEncoderOutputHandler * output)18499bd6c90Skasunath static int bejEncodeNode(void* node, struct BejEncoderOutputHandler* output)
18599bd6c90Skasunath {
18699bd6c90Skasunath     struct RedfishPropertyNode* nodeInfo = node;
18799bd6c90Skasunath     switch (nodeInfo->format.principalDataType)
18899bd6c90Skasunath     {
18999bd6c90Skasunath         case bejSet:
19099bd6c90Skasunath             RETURN_IF_IERROR(bejEncodeBejSetOrArray(node, output));
19199bd6c90Skasunath             break;
1920a29193fSkasunath         case bejArray:
1930a29193fSkasunath             RETURN_IF_IERROR(bejEncodeBejSetOrArray(node, output));
1940a29193fSkasunath             break;
1950a29193fSkasunath         case bejNull:
1960a29193fSkasunath             RETURN_IF_IERROR(bejEncodeBejNull(node, output));
1970a29193fSkasunath             break;
1980a29193fSkasunath         case bejInteger:
1990a29193fSkasunath             RETURN_IF_IERROR(bejEncodeBejInteger(node, output));
2000a29193fSkasunath             break;
2010a29193fSkasunath         case bejEnum:
2020a29193fSkasunath             RETURN_IF_IERROR(bejEncodeBejEnum(node, output));
2030a29193fSkasunath             break;
204*6df0c486Skasunath         case bejString:
205*6df0c486Skasunath             RETURN_IF_IERROR(bejEncodeBejString(node, output));
206*6df0c486Skasunath             break;
207*6df0c486Skasunath         case bejReal:
208*6df0c486Skasunath             RETURN_IF_IERROR(bejEncodeBejReal(node, output));
209*6df0c486Skasunath             break;
210*6df0c486Skasunath         case bejBoolean:
211*6df0c486Skasunath             RETURN_IF_IERROR(bejEncodeBejBool(node, output));
212*6df0c486Skasunath             break;
213*6df0c486Skasunath         case bejPropertyAnnotation:
214*6df0c486Skasunath             RETURN_IF_IERROR(bejEncodeBejProAnno(node, output));
215*6df0c486Skasunath             break;
21699bd6c90Skasunath         default:
21799bd6c90Skasunath             fprintf(stderr, "Unsupported node type: %d\n",
21899bd6c90Skasunath                     nodeInfo->format.principalDataType);
21999bd6c90Skasunath             return -1;
22099bd6c90Skasunath     }
22199bd6c90Skasunath     return 0;
22299bd6c90Skasunath }
22399bd6c90Skasunath 
22499bd6c90Skasunath /**
22599bd6c90Skasunath  * @brief A helper function to add a parent to the stack.
22699bd6c90Skasunath  */
bejPushParentToStack(struct RedfishPropertyParent * parent,struct BejPointerStackCallback * stack)22799bd6c90Skasunath static int bejPushParentToStack(struct RedfishPropertyParent* parent,
22899bd6c90Skasunath                                 struct BejPointerStackCallback* stack)
22999bd6c90Skasunath {
23099bd6c90Skasunath     // Before pushing the parent node, initialize its nextChild as the first
23199bd6c90Skasunath     // child.
23299bd6c90Skasunath     parent->metaData.nextChild = parent->firstChild;
23399bd6c90Skasunath     return stack->stackPush(parent, stack->stackContext);
23499bd6c90Skasunath }
23599bd6c90Skasunath 
23699bd6c90Skasunath /**
23799bd6c90Skasunath  * @brief Process all the child nodes of a parent.
23899bd6c90Skasunath  */
bejProcessChildNodes(struct RedfishPropertyParent * parent,struct BejPointerStackCallback * stack,struct BejEncoderOutputHandler * output)23999bd6c90Skasunath static int bejProcessChildNodes(struct RedfishPropertyParent* parent,
24099bd6c90Skasunath                                 struct BejPointerStackCallback* stack,
24199bd6c90Skasunath                                 struct BejEncoderOutputHandler* output)
24299bd6c90Skasunath {
24399bd6c90Skasunath     // Get the next child of the parent.
24499bd6c90Skasunath     void* childPtr = parent->metaData.nextChild;
24599bd6c90Skasunath 
24699bd6c90Skasunath     while (childPtr != NULL)
24799bd6c90Skasunath     {
24899bd6c90Skasunath         // First encode the current child node.
24999bd6c90Skasunath         RETURN_IF_IERROR(bejEncodeNode(childPtr, output));
25099bd6c90Skasunath         // If this child node has its own children, add it to the stack and
25199bd6c90Skasunath         // return. Because we need to encode the children of the newly added
25299bd6c90Skasunath         // node before continuing to encode the child nodes of the current
25399bd6c90Skasunath         // parent.
25499bd6c90Skasunath         if (bejTreeIsParentType(childPtr))
25599bd6c90Skasunath         {
25699bd6c90Skasunath             RETURN_IF_IERROR(bejPushParentToStack(childPtr, stack));
25799bd6c90Skasunath             // Update the next child of the current parent we need to
25899bd6c90Skasunath             // process.
25999bd6c90Skasunath             bejParentGoToNextChild(parent, childPtr);
26099bd6c90Skasunath             return 0;
26199bd6c90Skasunath         }
26299bd6c90Skasunath         childPtr = bejParentGoToNextChild(parent, childPtr);
26399bd6c90Skasunath     }
26499bd6c90Skasunath     return 0;
26599bd6c90Skasunath }
26699bd6c90Skasunath 
26799bd6c90Skasunath /**
26899bd6c90Skasunath  * @brief Encode the provided JSON tree.
26999bd6c90Skasunath  *
27099bd6c90Skasunath  * The node metadata should be initialized before using this function.
27199bd6c90Skasunath  */
bejEncodeTree(struct RedfishPropertyParent * root,struct BejPointerStackCallback * stack,struct BejEncoderOutputHandler * output)27299bd6c90Skasunath static int bejEncodeTree(struct RedfishPropertyParent* root,
27399bd6c90Skasunath                          struct BejPointerStackCallback* stack,
27499bd6c90Skasunath                          struct BejEncoderOutputHandler* output)
27599bd6c90Skasunath {
27699bd6c90Skasunath     // We need to encode a parent node before its child nodes. So encoding the
27799bd6c90Skasunath     // root first.
27899bd6c90Skasunath     RETURN_IF_IERROR(bejEncodeNode(root, output));
27999bd6c90Skasunath     // Once the root is encoded, push it to the stack used to traverse the child
28099bd6c90Skasunath     // nodes. We need to keep a parent in this stack until all the child nodes
28199bd6c90Skasunath     // of this parent has been encoded. Only then we remove the parent node from
28299bd6c90Skasunath     // the stack.
28399bd6c90Skasunath     RETURN_IF_IERROR(bejPushParentToStack(root, stack));
28499bd6c90Skasunath 
28599bd6c90Skasunath     while (!stack->stackEmpty(stack->stackContext))
28699bd6c90Skasunath     {
28799bd6c90Skasunath         struct RedfishPropertyParent* parent =
28899bd6c90Skasunath             stack->stackPeek(stack->stackContext);
28999bd6c90Skasunath 
29099bd6c90Skasunath         // Encode all the child nodes of the current parent node. If one of
29199bd6c90Skasunath         // these child nodes has its own child nodes, that child node will be
29299bd6c90Skasunath         // encoded and added to the stack and this function will return. The
29399bd6c90Skasunath         // rest of the children of the current parent will be encoded later
29499bd6c90Skasunath         // (after processing all the nodes under the child node added to the
29599bd6c90Skasunath         // stack).
29699bd6c90Skasunath         RETURN_IF_IERROR(bejProcessChildNodes(parent, stack, output));
29799bd6c90Skasunath 
29899bd6c90Skasunath         // If a new node hasn't been added to the stack by
29999bd6c90Skasunath         // bejProcessChildNodes(), we know that this parent's child nodes have
30099bd6c90Skasunath         // been processed. If a new node has been added, then next we need to
30199bd6c90Skasunath         // process the children of the newly added node.
30299bd6c90Skasunath         if (parent != stack->stackPeek(stack->stackContext))
30399bd6c90Skasunath         {
30499bd6c90Skasunath             continue;
30599bd6c90Skasunath         }
30699bd6c90Skasunath         stack->stackPop(stack->stackContext);
30799bd6c90Skasunath     }
30899bd6c90Skasunath     return 0;
30999bd6c90Skasunath }
31099bd6c90Skasunath 
bejEncode(const struct BejDictionaries * dictionaries,uint16_t majorSchemaStartingOffset,enum BejSchemaClass schemaClass,struct RedfishPropertyParent * root,struct BejEncoderOutputHandler * output,struct BejPointerStackCallback * stack)31199bd6c90Skasunath int bejEncode(const struct BejDictionaries* dictionaries,
31299bd6c90Skasunath               uint16_t majorSchemaStartingOffset,
31399bd6c90Skasunath               enum BejSchemaClass schemaClass,
31499bd6c90Skasunath               struct RedfishPropertyParent* root,
31599bd6c90Skasunath               struct BejEncoderOutputHandler* output,
31699bd6c90Skasunath               struct BejPointerStackCallback* stack)
31799bd6c90Skasunath {
31899bd6c90Skasunath     NULL_CHECK(dictionaries, "dictionaries");
31999bd6c90Skasunath     NULL_CHECK(dictionaries->schemaDictionary, "schemaDictionary");
32099bd6c90Skasunath     NULL_CHECK(dictionaries->annotationDictionary, "annotationDictionary");
32199bd6c90Skasunath 
32299bd6c90Skasunath     NULL_CHECK(root, "root");
32399bd6c90Skasunath 
32499bd6c90Skasunath     NULL_CHECK(output, "output");
32599bd6c90Skasunath     NULL_CHECK(stack, "stack");
32699bd6c90Skasunath 
32799bd6c90Skasunath     // Assert root node.
32899bd6c90Skasunath     if (root->nodeAttr.format.principalDataType != bejSet)
32999bd6c90Skasunath     {
33099bd6c90Skasunath         fprintf(stderr, "Invalid root node\n");
33199bd6c90Skasunath         return -1;
33299bd6c90Skasunath     }
33399bd6c90Skasunath 
33499bd6c90Skasunath     // First we need to encode a parent node before its child nodes. But before
33599bd6c90Skasunath     // encoding the parent node, the encoder has to figure out the total size
33699bd6c90Skasunath     // need to encode the parent's child nodes. Therefore first the encoder need
33799bd6c90Skasunath     // to visit the child nodes and calculate the size need to encode them
33899bd6c90Skasunath     // before producing the encoded bytes for the parent node.
33999bd6c90Skasunath     //
34099bd6c90Skasunath     // So first the encoder will visit child nodes and calculate the size need
34199bd6c90Skasunath     // to encode each child node. Then store this information in metadata
34299bd6c90Skasunath     // properties in each node struct.
34399bd6c90Skasunath     // Next the encoder will again visit each node starting from the parent
34499bd6c90Skasunath     // node, and produce the encoded bytes.
34599bd6c90Skasunath 
34699bd6c90Skasunath     // First calculate metadata for encoding each node.
34799bd6c90Skasunath     RETURN_IF_IERROR(bejUpdateNodeMetadata(
34899bd6c90Skasunath         dictionaries, majorSchemaStartingOffset, root, stack));
34999bd6c90Skasunath 
35099bd6c90Skasunath     // Derive the header of the encoded output.
35199bd6c90Skasunath     // BEJ version
35299bd6c90Skasunath     uint32_t version = BEJ_VERSION;
35399bd6c90Skasunath     RETURN_IF_IERROR(
35499bd6c90Skasunath         output->recvOutput(&version, sizeof(uint32_t), output->handlerContext));
35599bd6c90Skasunath     uint16_t reserved = 0;
35699bd6c90Skasunath     RETURN_IF_IERROR(output->recvOutput(&reserved, sizeof(uint16_t),
35799bd6c90Skasunath                                         output->handlerContext));
35899bd6c90Skasunath     RETURN_IF_IERROR(output->recvOutput(&schemaClass, sizeof(uint8_t),
35999bd6c90Skasunath                                         output->handlerContext));
36099bd6c90Skasunath 
36199bd6c90Skasunath     // Produce the encoded bytes for the nodes using the previously calculated
36299bd6c90Skasunath     // metadata.
36399bd6c90Skasunath     return bejEncodeTree(root, stack, output);
36499bd6c90Skasunath }
365