encodeJsonArray encodes the specified |jsonArray| into MySQL's internal JSON encoding and returns the type ID indicating whether this is a small or large array, the encoded array data, and any error encountered. The |largeEncoding| param controls whether this function will use the small array encodi
(jsonArray []any, largeEncoding bool)
| 80 | // - Size: 2 bytes for small encoding, otherwise 4; total size of the encoded array (everything but the Type ID) |
| 81 | // - Value Entries: 1 per value; 1 byte for type ID, variable sized offset (or inlined literal value) |
| 82 | // - Values: 1 per value; encoded value bytes |
| 83 | func encodeJsonArray(jsonArray []any, largeEncoding bool) (typeId byte, encodedArray []byte, err error) { |
| 84 | if !largeEncoding && len(jsonArray) > int(maxOffsetSize) { |
| 85 | return 0, nil, fmt.Errorf( |
| 86 | "too many elements in JSON array (%d) to serialize in small array encoding", len(jsonArray)) |
| 87 | } |
| 88 | |
| 89 | var valueEntriesBuffer []byte |
| 90 | var valuesBuffer []byte |
| 91 | nextValuesOffset := calculateInitialArrayValuesOffset(len(jsonArray), largeEncoding) |
| 92 | |
| 93 | for _, element := range jsonArray { |
| 94 | typeId, encodedValue, err := encodeJsonValue(element) |
| 95 | if err != nil { |
| 96 | return 0, nil, err |
| 97 | } |
| 98 | |
| 99 | // Literals can be inlined in the value-entries section |
| 100 | if typeId == jsonTypeLiteral { |
| 101 | valueEntriesBuffer = append(valueEntriesBuffer, typeId) |
| 102 | if len(encodedValue) != 1 { |
| 103 | return 0, nil, fmt.Errorf("unexpected buffer length") |
| 104 | } |
| 105 | valueEntriesBuffer = appendForEncoding(valueEntriesBuffer, uint32(encodedValue[0]), largeEncoding) |
| 106 | } else { |
| 107 | if !largeEncoding && nextValuesOffset > maxOffsetSize-uint32(len(encodedValue)) { |
| 108 | return 0, nil, fmt.Errorf("offset too large for small array encoding") |
| 109 | } |
| 110 | |
| 111 | valueEntriesBuffer = append(valueEntriesBuffer, typeId) |
| 112 | valueEntriesBuffer = appendForEncoding(valueEntriesBuffer, nextValuesOffset, largeEncoding) |
| 113 | valuesBuffer = append(valuesBuffer, encodedValue...) |
| 114 | nextValuesOffset += uint32(len(encodedValue)) |
| 115 | } |
| 116 | } |
| 117 | |
| 118 | // element count (uint16 for small arrays) |
| 119 | encodedArray = appendForEncoding(encodedArray, uint32(len(jsonArray)), largeEncoding) |
| 120 | |
| 121 | // Grab the total size of the array data from the next offset position pointing to the end of the values buffer |
| 122 | arrayPayloadLength := nextValuesOffset |
| 123 | |
| 124 | encodedArray = appendForEncoding(encodedArray, arrayPayloadLength, largeEncoding) |
| 125 | encodedArray = append(encodedArray, valueEntriesBuffer...) |
| 126 | encodedArray = append(encodedArray, valuesBuffer...) |
| 127 | |
| 128 | if !largeEncoding { |
| 129 | return jsonTypeSmallArray, encodedArray, nil |
| 130 | } else { |
| 131 | return jsonTypeLargeArray, encodedArray, nil |
| 132 | } |
| 133 | } |
| 134 | |
| 135 | // encodeJsonObject encodes the specified |jsonObject| into MySQL's internal JSON encoding and returns |
no test coverage detected