Coverage Summary for Class: GhostJsonFlatReaderCaptureKt (com.ghost.serialization.parser)

Class Class, % Method, % Branch, % Line, % Instruction, %
GhostJsonFlatReaderCaptureKt 100% (1/1) 100% (4/4) 75.8% (25/33) 96.7% (29/30) 91.3% (167/183)


 @file:OptIn(InternalGhostApi::class)
 
 package com.ghost.serialization.parser
 
 import com.ghost.serialization.InternalGhostApi
 import com.ghost.serialization.parser.GhostJsonConstants as C
 import com.ghost.serialization.types.RawJson
 
 /**
  * Captures the next complete JSON value (object, array, string, number, boolean, null)
  * as a [RawJson] view into this reader's buffer without copying UTF-8 bytes.
  */
 fun GhostJsonFlatReader.captureRawJson(): RawJson {
     skipWhitespace()
     val start = position
     captureJsonValueBytes()
     nextTokenByte = C.RESET_TOKEN_BYTE
     val length = position - start
     return if (materializeRawJsonCaptures) {
         RawJson.fromUtf8Bytes(rawData.copyOfRange(start, position))
     } else {
         RawJson.fromBufferSlice(rawData, start, length)
     }
 }
 
 /**
  * Captures the next complete JSON value (object, array, string, number, boolean, null)
  * as a raw [ByteArray] without decoding any content. The returned bytes are a verbatim
  * copy of the UTF-8 payload that represents the value in the input, including surrounding
  * brackets or quotes.
  *
  * Designed for deferred parsing: capture bytes here, then pass them later to
  * [com.ghost.serialization.Ghost.deserialize] which will create a new flat reader
  * over the captured slice — no intermediate String allocation, no UTF-8→UTF-16 round-trip.
  *
  * Contrast with [com.ghost.serialization.parser.GhostJsonFlatReader.skipValue], which
  * uses the stateful depth/comma machine. This function is a pure byte-level scan that
  * does not touch depth, needsCommaMask, or commaConsumedMask.
  */
 fun GhostJsonFlatReader.captureRawJsonBytes(): ByteArray = captureRawJson().bytes
 
 private fun GhostJsonFlatReader.captureJsonValueBytes() {
     val data = rawData
     val localLimit = limit
     val first = data[position++].toInt() and C.BYTE_MASK
     when (first) {
         C.OPEN_OBJ_INT, C.OPEN_ARR_INT -> {
             // Scan past the entire object/array. A single depth counter works for
             // well-formed JSON: every { or [ increments, every } or ] decrements.
             // Quoted strings are skipped in full to avoid counting brackets inside them.
             var depth = 1
             while (position < localLimit && depth > 0) {
                 when (data[position++].toInt() and C.BYTE_MASK) {
                     C.QUOTE_INT -> captureSkipStringBytes(data, localLimit)
                     C.OPEN_OBJ_INT, C.OPEN_ARR_INT -> depth++
                     C.CLOSE_OBJ_INT, C.CLOSE_ARR_INT -> depth--
                 }
             }
         }
         C.QUOTE_INT -> captureSkipStringBytes(data, localLimit)
         C.TRUE_CHAR_INT -> position += 3   // "rue" (the 't' was already consumed)
         C.FALSE_CHAR_INT -> position += 4  // "alse"
         C.NULL_CHAR_INT -> position += 3   // "ull"
         else -> {
             // Number: advance until a JSON structural delimiter or whitespace
             while (position < localLimit) {
                 val b = data[position].toInt() and C.BYTE_MASK
                 if (b == C.COMMA_INT || b == C.CLOSE_OBJ_INT || b == C.CLOSE_ARR_INT || b <= C.SPACE_INT) break
                 position++
             }
         }
     }
 }
 
 /**
  * Advances [position] past the content of a quoted JSON string whose opening '"' has
  * already been consumed. Handles backslash escapes by skipping the escaped character.
  */
 private fun GhostJsonFlatReader.captureSkipStringBytes(data: ByteArray, localLimit: Int) {
     while (position < localLimit) {
         when (data[position++].toInt() and C.BYTE_MASK) {
             C.QUOTE_INT -> return
             C.BACKSLASH_INT -> if (position < localLimit) position++
         }
     }
 }