99
1010package org .elasticsearch .ingest ;
1111
12+ import org .elasticsearch .common .io .stream .StreamInput ;
1213import org .elasticsearch .xcontent .DeprecationHandler ;
1314import org .elasticsearch .xcontent .NamedXContentRegistry ;
1415import org .elasticsearch .xcontent .Text ;
4445public class ESONXContentParser extends AbstractXContentParser {
4546
4647 private final ESONSource .ESONObject root ;
48+ private final ESONSource .Values values ;
4749 private final XContentType xContentType ;
4850
4951 // Parsing state
@@ -95,6 +97,7 @@ public ESONXContentParser(
9597 ) {
9698 super (registry , deprecationHandler );
9799 this .root = root ;
100+ this .values = root .objectValues ().get ();
98101 // Start with the root object context
99102 this .currentContext = new ParseContext (root );
100103 this .xContentType = xContentType ;
@@ -268,36 +271,16 @@ private Object materializeValue() {
268271 } else if (esonType instanceof ESONSource .ESONArray arr ) {
269272 return arr ;
270273 } else if (esonType instanceof ESONSource .FixedValue fixedVal ) {
271- return fixedVal .getValue (getValuesFromContext () );
274+ return fixedVal .getValue (values );
272275 } else if (esonType instanceof ESONSource .VariableValue varVal ) {
273- return varVal .getValue (getValuesFromContext () );
276+ return varVal .getValue (values );
274277 } else if (esonType instanceof ESONSource .Mutation mutation ) {
275278 return mutation .object ();
276279 } else {
277280 throw new IllegalStateException ("Unknown ESON type: " + esonType .getClass ());
278281 }
279282 }
280283
281- // Helper to get Values instance from current context
282- private ESONSource .Values getValuesFromContext () {
283- if (currentContext != null && currentContext .rawObject instanceof ESONSource .ESONObject esonObj ) {
284- return esonObj .objectValues ().get ();
285- } else if (currentContext != null && currentContext .rawObject instanceof ESONSource .ESONArray esonArr ) {
286- return esonArr .arrayValues ().get ();
287- }
288-
289- // Try to find an ancestor context with Values (arrays inherit from parent objects)
290- for (ParseContext ctx : contextStack ) {
291- if (ctx .rawObject instanceof ESONSource .ESONObject esonObj ) {
292- return esonObj .objectValues ().get ();
293- } else if (ctx .rawObject instanceof ESONSource .ESONArray esonArr ) {
294- return esonArr .arrayValues ().get ();
295- }
296- }
297-
298- throw new IllegalStateException ("Cannot find Values instance in context stack" );
299- }
300-
301284 @ Override
302285 public void skipChildren () throws IOException {
303286 if (currentToken == Token .START_OBJECT || currentToken == Token .START_ARRAY ) {
@@ -339,17 +322,21 @@ public String text() throws IOException {
339322 public XContentString optimizedText () throws IOException {
340323 // For strings, try to access raw bytes directly without materializing the string
341324 if (currentEsonType instanceof ESONSource .VariableValue varValue && varValue .valueType () == ESONSource .ValueType .STRING ) {
342- try {
343- ESONSource .Values values = getValuesFromContext ();
344- if (values .data ().hasArray ()) {
345- // Return XContentString with direct byte access (lazy string conversion)
346- byte [] rawBytes = values .data ().array ();
347- int offset = values .data ().arrayOffset () + varValue .position ();
348- return new Text (new XContentString .UTF8Bytes (rawBytes , offset , varValue .length ()));
349- }
350- } catch (Exception e ) {
351- // Fall back to materialized string
325+ // Return XContentString with direct byte access (lazy string conversion)
326+ byte [] rawBytes ;
327+ int offset ;
328+ int length = varValue .length ();
329+ if (values .data ().hasArray ()) {
330+ rawBytes = values .data ().array ();
331+ offset = values .data ().arrayOffset () + varValue .position ();
332+ } else {
333+ rawBytes = new byte [Math .toIntExact (length )];
334+ offset = 0 ;
335+ StreamInput streamInput = values .data ().streamInput ();
336+ streamInput .skip (varValue .position ());
337+ streamInput .read (rawBytes );
352338 }
339+ return new Text (new XContentString .UTF8Bytes (rawBytes , offset , length ));
353340 }
354341
355342 // Fallback: materialize value and convert to bytes
@@ -364,9 +351,8 @@ public XContentString optimizedText() throws IOException {
364351 public boolean optimizedText (OutputStream out ) throws IOException {
365352 // For strings, try to write raw bytes directly without materializing the string
366353 if (currentEsonType instanceof ESONSource .VariableValue varValue && varValue .valueType () == ESONSource .ValueType .STRING ) {
367-
368354 try {
369- ESONSource . Values values = getValuesFromContext ();
355+ // TODO: Can optimize more. Just not sure if this method needs to stay.
370356 if (values .data ().hasArray ()) {
371357 // Write directly from the raw bytes
372358 byte [] rawBytes = values .data ().array ();
0 commit comments