Coverage Summary for Class: GhostEmitterConstants (com.ghost.serialization.compiler)
| Class |
Class, %
|
Method, %
|
Branch, %
|
Line, %
|
Instruction, %
|
| GhostEmitterConstants |
100%
(1/1)
|
100%
(1/1)
|
|
100%
(1/1)
|
100%
(14/14)
|
package com.ghost.serialization.compiler
import com.squareup.kotlinpoet.ClassName
/**
* Centralized constants for the deserialization code emitters and generators.
*
* Contains all string literals, templates, and identifiers used during code generation
* to ensure consistency and eliminate magic strings across the emitter modules.
*/
internal object GhostEmitterConstants {
const val STR_DESERIALIZE = "deserialize"
const val STR_KDOC_DESERIALIZE = "Robust deserialization for [%T].\n"
const val DEFAULT_CHUNK_SIZE = 40
const val STR_READER = "reader"
const val TEMPLATE_PEEK_TYPE = "val typeName = reader.peekStringField(%S) ?: reader.throwError(%S)"
const val STR_MISSING_TYPE = "Missing discriminator field for sealed class"
const val STR_WHEN_TYPENAME = "val result = when (typeName)"
const val TEMPLATE_DESERIALIZE_BRANCH = "%S -> %T.deserialize(reader)"
const val STR_UNKNOWN_TYPE = "else -> reader.throwError(\"Unknown type discriminator: \$typeName\")"
const val STR_RETURN_RESULT = "return result"
const val TEMPLATE_RETURN_CONSTRUCTOR = "return %T(%L)"
const val TEMPLATE_CONSTRUCTOR = "%T(%L)"
const val STR_NULL = "null"
const val STR_ZERO = "0"
const val STR_ZERO_L = "0L"
const val STR_ZERO_D = "0.0"
const val STR_ZERO_F = "0.0f"
const val STR_CHAR_NULL_LITERAL = "'\\u0000'"
const val STR_JSON_CHAR_NULL = "\"\\u0000\""
const val VAL_ZERO = 0
const val VAL_ONE = 1
const val VAL_TWO = 2
const val VAL_THREE = 3
const val VAL_FOUR = 4
const val VAL_ZERO_L = 0L
const val VAL_ONE_L = 1L
const val BIT_SHIFT_32 = 32
const val LONG_BYTE_MASK = 0xFFL
const val STR_FALSE = "false"
const val STR_CURLY_OPEN = "{"
const val STR_CURLY_CLOSE = "}"
const val STR_COLON = ":"
const val STR_EMPTY_JSON = "{}"
const val STR_EMPTY_ARRAY = "[]"
const val STR_EMPTY_STRING = "\"\""
const val STR_DOUBLE_QUOTE = "\""
const val STR_BEGIN_OBJECT = "reader.beginObject()"
const val STR_WHILE_TRUE = "while (true)"
const val STR_SELECT_NAME_AND_CONSUME = "val index = reader.selectNameAndConsume(OPTIONS)"
const val STR_SELECT_SUB_NAME = "val %L = reader.selectNameAndConsume(%L)"
const val STR_WHEN_INDEX = "when (index)"
const val STR_WHEN_SUB_INDEX = "when (%L)"
const val STR_ARROW = " ->"
const val STR_UNDERSCORE = "_"
const val TEMPLATE_ASSIGN_L = " = %L"
const val STR_MINUS_ONE_BREAK = "-1 -> break"
const val STR_MINUS_TWO_ARROW = "-2 ->"
const val STR_SKIP_VALUE = "reader.skipValue()"
const val STR_END_OBJECT = "reader.endObject()"
const val TEMPLATE_DESERIALIZE_T = "%T.deserialize(reader)"
const val TEMPLATE_DESERIALIZE_L = "%L.deserialize(reader)"
const val STR_NEXT_INT = "reader.nextInt()"
const val STR_NEXT_BOOLEAN = "reader.nextBoolean()"
const val STR_NEXT_LONG = "reader.nextLong()"
/**
* proto3 JSON mapping: int64/uint64 fields accept both bare numbers and quoted decimal
* strings on read. Temporarily flips `coerceStringsToNumbers` around the read — this works
* on every reader flavor (streaming, flat, string), not just GhostProtoJsonFlatReader.
*/
const val STR_NEXT_LONG_PROTO_COERCED =
"run { val __c = reader.coerceStringsToNumbers; reader.coerceStringsToNumbers = true; val __v = reader.nextLong(); reader.coerceStringsToNumbers = __c; __v }"
const val STR_NEXT_DOUBLE = "reader.nextDouble()"
const val STR_NEXT_FLOAT = "reader.nextFloat()"
const val STR_NEXT_BYTE = "reader.nextInt().toByte()"
const val STR_NEXT_SHORT = "reader.nextInt().toShort()"
const val STR_NEXT_CHAR = "reader.nextChar()"
const val STR_SERIALIZERS_PKG = "com.ghost.serialization.serializers"
const val STR_NEXT_STRING = "reader.nextString()"
const val TEMPLATE_L_READER = "%T.%L(reader)"
const val TEMPLATE_NULL_CHECK_L = "if (reader.isNextNullValue()) { reader.consumeNull(); null } else %L"
const val TEMPLATE_THROW_S = "reader.throwError(%S)"
const val STR_REQ_FIELD_1 = "Required field '"
const val STR_REQ_FIELD_2 = "' missing in JSON"
const val STR_COMMA_SPACE = ", "
const val STR_BANG_BANG = "!!"
const val TEMPLATE_RETURN_T_PAREN = "return %T("
const val STR_PAREN = ")"
const val TEMPLATE_VAL_RESULT = "val result = %T("
const val STR_OR = " || "
const val STR_RETURN_RESULT_COPY = "return result.copy("
const val STR_COMMA = ","
const val STR_EMPTY = ""
const val STR_ELSE = "else"
const val STR_RETURN_RESULT_FINAL = "return result"
const val STR_ERR_INVALID_ENUM_INDEX = "-1 -> reader.throwError(\"Invalid enum value\")"
const val STR_ERR_UNEXPECTED_INDEX = "else -> throw GhostJsonException(\"Unexpected index: \$index\")"
const val STR_FALLBACK_ANNOTATION = "GhostFallback"
const val STR_ELSE_BRANCH = "else ->"
const val STR_ENUM_SELECT_OPTIONS = "val index = reader.selectString(ENUM_OPTIONS)"
const val STR_ENUM_WHEN = "return when (index)"
const val TEMPLATE_ENUM_BRANCH = "%L -> %T.%L"
const val STR_MASK_INIT = "var mask%L = 0L"
const val STR_CTX_CLASS = "DecodingContext"
const val STR_DECODE_CHUNK_PREFIX = "decodeChunk"
const val STR_SERIALIZE_CHUNK_PREFIX = "serializeChunk"
const val STR_READER_VAR = "reader"
const val STR_CTX_VAR = "ctx"
const val STR_INDEX_VAR = "index"
const val STR_WHEN_INDEX_PLAIN = "when (index)"
const val STR_BIT_MASK_MIN_LONG = "Long.MIN_VALUE"
const val TEMPLATE_DECODE_RESILIENT = "reader.decodeResilient { %L }?.let"
const val TEMPLATE_CTX_FIELD_ASSIGN = "ctx.%L = %L"
const val TEMPLATE_CTX_FIELD_SET_IT = "ctx.%L = it"
const val TEMPLATE_CTX_MASK_OR = "ctx.mask%L = ctx.mask%L or %L"
const val STR_CTX_INIT = "val ctx = DecodingContext()"
const val TEMPLATE_CHUNK_CALL = "in %L..%L -> %L(reader, ctx, index)"
const val TEMPLATE_IF_MASK_MISSING = "if ((ctx.mask%L and %L) == 0L)"
const val TEMPLATE_ELSE_IF_MASK_MISSING = "else if ((ctx.mask%L and %L) == 0L)"
const val STR_READ_LIST_TEMPLATE = "reader.readList { %L }"
const val STR_READ_SET_TEMPLATE = "reader.readSet { %L }"
const val STR_READ_MAP_TEMPLATE = "reader.readMap({ reader.nextKey()!! }) { %L }"
const val STR_MASK_BITWISE_OR = "mask%L = mask%L or %L"
const val STR_IF_OPEN = "if ("
const val TEMPLATE_IF_MASK_MATCH_BIT_F = "(ctx.mask%s and %s) != 0L"
const val STR_CLOSE_PAREN_FLOW = ")"
const val TEMPLATE_IF_MASK_NOT_MET = "if ((ctx.mask%L and %L) != %L)"
const val TEMPLATE_MASK_CHECK_MATCH = "(mask%s and %s) != 0L"
const val TEMPLATE_MASK_ALL_MET_SIMPLE = "(mask%s and %s) == %s"
const val STR_GHOST_PKG = "com.ghost.serialization"
const val STR_CONTRACT_PKG = "com.ghost.serialization.contract"
const val STR_GHOST_OBJ = "Ghost"
const val STR_GHOST_SERIALIZER = "GhostSerializer"
const val TEMPLATE_RESOLVE_SERIALIZER = "%T.getSerializer(%T::class)!!"
val BYTE_STRING_CLASS = ClassName("okio", "ByteString")
const val DEFAULT_DISCRIMINATOR_KEY = "key"
const val STR_WRITER_BEGIN_OBJ = "writer.beginObject()"
const val STR_WRITER_NAME_TYPE_VAL = "writer.name(%S).value(%S)"
const val STR_WRITER_WRITE_NAME_VAL = "writer.writeNameRaw(%L)"
const val STR_WRITER_END_OBJ = "writer.endObject()"
const val STR_WRITER_BEGIN_ARR = "writer.beginArray()"
const val STR_WRITER_END_ARR = "writer.endArray()"
const val STR_PARAM_WRITER = "writer"
const val STR_PARAM_VALUE = "value"
const val TEMPLATE_CHUNK_CALL_WRITER = "%N(writer, value)"
const val STR_FUN_SERIALIZE = "serialize"
const val STR_WHEN_VALUE = "when (value)"
const val STR_SERIALIZER_SUFFIX = "Serializer"
const val TEMPLATE_CHUNK_FUN_NAME = "%s%s_%s"
const val TEMPLATE_DECODE_CHUNK_NAME = "%s%s"
const val STR_IS_T_ARROW_T_SERIALIZE = "is %T -> %T.serialize(writer, value)"
const val TEMPLATE_VAR_NAME = "%sValue"
const val TEMPLATE_RESULT_VAR = "result.%s"
const val TEMPLATE_MASK_VAR = "mask%s"
const val TEMPLATE_CTX_VAR = "ctx.%s"
const val TEMPLATE_CTX_MASK_VAR = "ctx.mask%s"
const val TEMPLATE_IF_MASK_RETURN = "if ((%s and %s) != 0L) %s else %s"
const val TEMPLATE_WRAP_TYPE = "%s(%s)"
const val STR_ANNOTATION_SERIALIZATION = "com.ghost.serialization.annotations.GhostSerialization"
const val STR_ANNOTATION_PROTO_SERIALIZATION = "com.ghost.serialization.annotations.GhostProtoSerialization"
const val STR_GENERATED_PKG = "com.ghost.serialization.generated"
const val STR_REGISTRY_PREFIX = "GhostModuleRegistry"
const val STR_LOG_PREFIX = ">>> [GhostSerialization]"
const val OPTION_MODULE_NAME = "ghost.moduleName"
const val STR_DEFAULT_NAME = "Default"
const val STR_DASH = "-"
const val STR_LOG_OPTIMIZED = " Successfully optimized: "
const val STR_LOG_CRITICAL = " Critical error processing "
const val STR_COLON_SPACE = ": "
const val STR_REFLECT_PKG = "kotlin.reflect"
const val STR_KCLASS = "KClass"
const val STR_TYPE_T = "T"
const val STR_COLLECTIONS_PKG = "kotlin.collections"
const val STR_MAP = "Map"
const val STR_FORMAT_S = "%S"
const val STR_MAP_OF = "mapOf(\n"
const val STR_MAP_ENTRY = " %T::class to %T"
const val STR_COMMA_NEWLINE = ",\n"
const val STR_PAREN_CLOSE = ")"
const val STR_PROP_SERIALIZERS_MAP = "serializersByClass"
const val STR_FUN_GET_SERIALIZER = "getSerializer"
const val STR_PARAM_CLAZZ = "clazz"
const val STR_UNCHECKED_CAST = "UNCHECKED_CAST"
const val STR_GHOST_REGISTRY = "GhostRegistry"
const val STR_FUN_PREWARM = "prewarm"
const val STR_SERIALIZERS_SIZE = "serializersByClass.size"
const val STR_FUN_REG_COUNT = "registeredCount"
const val STR_FUN_GET_ALL_SERIALIZERS = "getAllSerializers"
const val STR_RETURN_SERIALIZERS = "return serializersByClass"
const val STR_KDOC_REGISTRY = "Generated Registry for GhostSerialization.\nUses a when-based getSerializer for cold-start-friendly class loading and a lazy map for getAllSerializers."
const val STR_INSTANCE = "INSTANCE"
const val STR_INIT_INSTANCE = "%T()"
const val STR_META_INF_PROGUARD = "META-INF.proguard"
const val STR_GHOST_SERIALIZATION_FILE = "ghost-serialization"
const val STR_EXT_PRO = "pro"
const val STR_LOG_PROGUARD_WARN = " Could not generate ProGuard rules: "
const val STR_SERVICE_REGISTRY = "com.ghost.serialization.contract.GhostRegistry"
const val STR_META_INF_SERVICES = "META-INF.services"
const val STR_LOG_SERVICE_WARN = " Could not generate ServiceLoader file: "
const val STR_LAZY_START = "lazy {\n"
const val STR_WHEN_CLAZZ_START = "return when (clazz) {\n"
const val STR_WHEN_ENTRY = " %T::class -> %T\n"
const val STR_WHEN_ELSE_NULL = " else -> null\n"
const val STR_WHEN_CLOSE_CAST = "} as %T\n"
const val PKG_PARSER = "com.ghost.serialization.parser"
const val STR_RETURN_L = "return %L"
const val REGISTRY_CHUNK_SIZE = 500
const val TEMPLATE_GET_SHARD_MAP_CALL = "getShardMap%L()"
const val STR_PLUS_SPACED = " + "
const val STR_NEWLINE_CLOSE_CURLY = "\n}"
const val TEMPLATE_GET_SHARD_CALL = "getShard%L(clazz)?.let { return it as %T }"
const val STR_RETURN_NULL = "return null"
const val TEMPLATE_SHARD_MAP_NAME = "getShardMap%d"
const val TEMPLATE_SHARD_NAME = "getShard%d"
const val STR_LIST = "List"
const val STR_SET = "Set"
const val STR_INT = "Int"
const val STR_LONG_TYPE = "Long"
const val STR_STRING = "String"
const val STR_DOUBLE = "Double"
const val STR_FLOAT = "Float"
const val STR_BOOLEAN = "Boolean"
const val TEMPLATE_PROGUARD_KEEP = """
# GhostSerialization Robust Keep Rules
-keep class %s.%s {
public static ** INSTANCE;
public *** getSerializer(...);
}
-keep class * implements com.ghost.serialization.contract.GhostSerializer {
*;
}
"""
const val STR_DOT = "."
const val STR_T_SERIALIZE_WRITER_ACC = "%T.serialize(writer, %L)"
const val STR_ENUM_MEMBER_VAL = "%T.%L -> writer.value(%S)"
const val STR_WRITER_VAL_ENUM_NAME = "writer.value(value.name)"
const val K_INT = "kotlin.Int"
const val K_LONG = "kotlin.Long"
const val K_STRING = "kotlin.String"
const val K_BOOLEAN = "kotlin.Boolean"
const val K_DOUBLE = "kotlin.Double"
const val K_FLOAT = "kotlin.Float"
const val K_BYTE = "kotlin.Byte"
const val K_SHORT = "kotlin.Short"
const val K_CHAR = "kotlin.Char"
const val K_UNIT = "kotlin.Unit"
const val K_NOTHING = "kotlin.Nothing"
const val K_ANY = "kotlin.Any"
const val K_BYTE_ARRAY = "kotlin.ByteArray"
const val K_RAW_JSON = "com.ghost.serialization.types.RawJson"
const val PKG_TYPES = "com.ghost.serialization.types"
const val STR_RAW_JSON_TYPE = "RawJson"
const val STR_RAW_JSON_FROM_CAPTURE = "reader.captureRawJson()"
const val STR_WRITER_RAW_VALUE_SLICE = "writer.rawValue(%L.storage, %L.storageOffset, %L.storageLength)"
const val STR_WRITER_RAW_VALUE_RAWJSON = "writer.rawValue(%L)"
const val STR_CAPTURE_RAW_JSON_BYTES = "reader.captureRawJsonBytes()"
const val STR_WRITER_RAW_VALUE_L = "writer.rawValue(%L)"
const val STR_KOTLIN_PREFIX = "kotlin."
const val STR_JAVA_PREFIX = "java."
const val STR_H_VAL_PREFIX = "H_"
const val STR_SERIALIZE_CALL = "%L.serialize(writer, %L)"
const val STR_WRITER_VAL_L = "writer.value(%L)"
const val STR_WRITER_VAL_FLOAT = "writer.value(%L)"
/** proto3 JSON mapping: int64/uint64 fields are quoted decimal strings on the wire. */
const val STR_WRITER_VAL_LONG_AS_STRING = "writer.value(%L.toString())"
/** proto3 JSON mapping: `bytes` fields are Base64 strings on the wire, not inline raw JSON. */
const val STR_WRITER_VAL_BYTES_AS_BASE64 = "writer.value(encodeBase64String(%L))"
const val STR_DECODE_BASE64_STRING_CALL = "decodeBase64String(reader.nextString())"
const val STR_WRITE_FIELD = "writer.writeField(%L, %L)"
const val STR_WRITE_NAME_RAW = "writer.writeNameRaw(%L)"
const val STR_WRITE_NAME_RAW_NULL = "writer.writeNameRaw(%L).nullValue()"
const val STR_CUSTOM_ENCODER_CALL = "%T.%L(writer, %L)"
const val STR_CONTEXTUAL_PREFIX = "contextual_"
const val TEMPLATE_ENCODE_UTF8 = "%S.encodeUtf8()"
const val FMT_JSON_FIELD = "\"%s\":"
// Analyzer Constants
const val STR_ERR_CLASS_1 = "GhostSerialization: @GhostSerialization can only be applied to 'data class', 'sealed class', 'value class' or 'enum class'. "
const val STR_ERR_CLASS_2 = "Class '"
const val STR_ERR_CLASS_3 = "' is not supported."
const val STR_ERR_PRIV_1 = "GhostSerialization: Properties in @GhostSerialization classes cannot be private. "
const val STR_ERR_PRIV_2 = "Please remove 'private' modifier from properties in '"
const val STR_ERR_PRIV_3 = "'."
const val STR_ERR_DUP_1 = "GhostSerialization: Duplicate JSON name '"
const val STR_ERR_DUP_2 = "' found in class '"
const val STR_ERR_DUP_3 = "'. "
const val STR_ERR_DUP_4 = "Problematic properties: "
const val STR_ERR_MAP_1 = "GhostSerialization: Map key must be a String in property '"
const val STR_ERR_MAP_2 = "'. "
const val STR_ERR_MAP_3 = "JSON only supports string-keyed objects."
const val STR_KOTLIN_DOT = "kotlin."
const val STR_TYPE_INT_ARRAY = "kotlin.IntArray"
const val STR_TYPE_LONG_ARRAY = "kotlin.LongArray"
const val STR_TYPE_FLOAT_ARRAY = "kotlin.FloatArray"
const val STR_TYPE_DOUBLE_ARRAY = "kotlin.DoubleArray"
const val STR_TYPE_BOOLEAN_ARRAY = "kotlin.BooleanArray"
const val GHOST_IGNORE = "GhostIgnore"
const val GHOST_NAME = "GhostName"
const val SERIAL_NAME = "SerialName"
const val GHOST_SERIALIZATION = "GhostSerialization"
const val NAME_ARG = "name"
const val LIST_QUALIFIED = "kotlin.collections.List"
const val SET_QUALIFIED = "kotlin.collections.Set"
const val MAP_QUALIFIED = "kotlin.collections.Map"
const val STRING_QUALIFIED = "kotlin.String"
const val STR_VALUE_ARG = "value"
const val STR_SERIAL_NAME_SUFFIX = "SerialName"
const val GHOST_RESILIENT = "GhostResilient"
const val GHOST_DECODER = "GhostDecoder"
const val GHOST_ENCODER = "GhostEncoder"
const val PROVIDER_ARG = "provider"
const val FUNCTION_NAME_ARG = "functionName"
const val GHOST_FLATTEN = "GhostFlatten"
const val GHOST_WRAP = "GhostWrap"
const val GHOST_WRAPPED_KEYS = "GhostWrappedKeys"
const val KEYS_ARG = "keys"
const val OMIT_IF_EMPTY_ARG = "omitIfEmpty"
const val OMIT_IF_ABSENT_ARG = "omitIfAbsent"
const val PATH_ARG = "path"
const val ORDINAL = "ordinal"
const val NAME = "name"
// Generator-specific
const val PKG_WRITER = "com.ghost.serialization.writer"
const val PKG_CONTRACT = "com.ghost.serialization.contract"
const val PKG_EXCEPTION = "com.ghost.serialization.exception"
const val PKG_GHOST = "com.ghost.serialization"
const val OKIO_PACKAGE = "okio"
const val DECODE_RESILIENT = "decodeResilient"
const val STR_GHOST_JSON_WRITER = "GhostJsonWriter"
const val STR_GHOST_JSON_FLAT_WRITER = "GhostJsonFlatWriter"
const val STR_GHOST_JSON_STRING_WRITER = "GhostJsonStringWriter"
const val STR_GHOST_JSON_READER = "GhostJsonReader"
const val STR_GHOST_JSON_FLAT_READER = "GhostJsonFlatReader"
const val STR_GHOST_JSON_STRING_READER = "GhostJsonStringReader"
const val STR_GHOST_JSON_READER_QUALIFIED = "$PKG_PARSER.$STR_GHOST_JSON_READER"
const val STR_GHOST_JSON_FLAT_READER_QUALIFIED = "$PKG_PARSER.$STR_GHOST_JSON_FLAT_READER"
const val STR_GHOST_JSON_STRING_READER_QUALIFIED = "$PKG_PARSER.$STR_GHOST_JSON_STRING_READER"
const val STR_CHAR_TO_BYTE_POSITION = "charToBytePosition"
const val STR_BYTE_TO_CHAR_POSITION = "byteToCharPosition"
const val STR_RESET_TOKEN_BYTE = "RESET_TOKEN_BYTE"
const val STR_ENSURE_UTF8_BYTES = "reader.ensureUtf8Bytes()"
const val STR_CHAR_POSITION_TO_BYTE_POSITION = "reader.charPositionToBytePosition"
const val STR_BYTE_POSITION_TO_CHAR_POSITION = "reader.bytePositionToCharPosition"
const val STR_RAW_DATA_ENCODE_TO_BYTE_ARRAY = STR_ENSURE_UTF8_BYTES
const val STR_OVERRIDE_DESERIALIZE_STRING_READER = "override fun deserialize(reader: GhostJsonStringReader)"
const val STR_OVERRIDE_SERIALIZE_FN = "override fun serialize"
const val STR_KT_SERIALIZER_FILE_SUFFIX = "Serializer.kt"
const val STR_TEST_CUSTOM_DECODER_FN = "decodeHex"
const val STR_TEST_DECODER_UTILS = "DecoderUtils"
const val STR_TEST_CUSTOM_FIELD_MODEL = "CustomFieldModel"
const val STR_TEST_BYTES_RESULT = "bytes"
const val STR_TEST_NATIVE_RESULT = "native"
const val OPTION_TEXT_CHANNEL = "ghost.textChannel"
const val STR_BEGIN_ARRAY = "beginArray"
const val STR_END_ARRAY = "endArray"
const val STR_READ_LIST = "readList"
const val STR_READ_SET = "readSet"
const val STR_READ_MAP = "readMap"
const val STR_NEXT_KEY = "nextKey"
const val STR_SELECT_STRING = "selectString"
const val STR_PEEK_STRING_FIELD = "peekStringField"
const val STR_GHOST_JSON_EXCEPTION = "GhostJsonException"
const val STR_BYTESTRING_IMPORT = "ByteString.Companion.encodeUtf8"
const val STR_KDOC_HIGH_PERF = "High-performance serializer for [%T].\n"
const val STR_KDOC_GENERATED = "Generated by GhostSerialization. Do not modify manually.\n"
const val STR_OPTIONS = "OPTIONS"
const val STR_OPTIONS_PREFIX = "OPTIONS_"
const val STR_OPTIONS_CLASS = "JsonReaderOptions"
const val STR_RESET_TOKEN_BYTE_CALL =
" reader._setNextTokenByte($STR_GHOST_JSON_FLAT_READER_QUALIFIED.$STR_RESET_TOKEN_BYTE)\n"
const val STR_RUN_OPEN = "run {\n"
const val STR_CUSTOM_DECODER_TEMP_READER =
" val temp = $STR_GHOST_JSON_READER_QUALIFIED(reader._getRawData())\n temp._setPosition(reader._getPosition())\n"
const val STR_CUSTOM_DECODER_TEMP_READER_STRING =
" val temp = $STR_GHOST_JSON_READER_QUALIFIED($STR_ENSURE_UTF8_BYTES)\n temp._setPosition($STR_CHAR_POSITION_TO_BYTE_POSITION(reader.position))\n"
const val TEMPLATE_CUSTOM_DECODER_TEMP_CALL = " val res = %T.%L(temp)\n"
const val STR_CUSTOM_DECODER_UPDATE_POS = " reader._setPosition(temp._getPosition())\n"
const val STR_CUSTOM_DECODER_UPDATE_POS_STRING =
" reader.position = $STR_BYTE_POSITION_TO_CHAR_POSITION(temp._getPosition())\n"
const val STR_CUSTOM_DECODER_RETURN_RES = " res\n"
const val STR_RUN_CLOSE = "}"
const val STR_TRY = "try"
const val STR_CATCH_EXCEPTION = "catch (_: Exception)"
const val TEMPLATE_WARM_UP_READER_INIT = "val %L = %T(%S.encodeToByteArray())"
const val TEMPLATE_WARM_UP_STRING_READER_INIT = "val %L = %T(%S)"
const val TEMPLATE_WARM_UP_DESERIALIZE = "deserialize(%L)"
const val STR_READER1 = "reader1"
const val STR_READER2 = "reader2"
const val STR_READER3 = "reader3"
// Import names (raw function names)
const val STR_BEGIN_OBJECT_NAME = "beginObject"
const val STR_END_OBJECT_NAME = "endObject"
const val STR_SELECT_NAME_AND_CONSUME_NAME = "selectNameAndConsume"
const val STR_SKIP_VALUE_NAME = "skipValue"
const val STR_NEXT_INT_NAME = "nextInt"
const val STR_NEXT_LONG_NAME = "nextLong"
const val STR_NEXT_STRING_NAME = "nextString"
const val STR_NEXT_DOUBLE_NAME = "nextDouble"
const val STR_NEXT_FLOAT_NAME = "nextFloat"
const val STR_NEXT_CHAR_NAME = "nextChar"
const val STR_NEXT_BOOLEAN_NAME = "nextBoolean"
const val STR_CAPTURE_RAW_JSON_BYTES_NAME = "captureRawJsonBytes"
const val STR_CAPTURE_RAW_JSON_NAME = "captureRawJson"
const val STR_DECODE_BASE64_STRING_NAME = "decodeBase64String"
const val STR_ENCODE_BASE64_STRING_NAME = "encodeBase64String"
const val STR_BYTE_ARRAY_TYPE = "ByteArray"
const val STR_CONSUME_NULL_NAME = "consumeNull"
const val STR_IS_NEXT_NULL_VALUE_NAME = "isNextNullValue"
const val STR_ENUM_OPTIONS = "ENUM_OPTIONS"
const val STR_WARM_UP = "warmUp"
const val MARKER = "%S"
const val ANNOTATION_GHOST_SERIALIZATION = "GhostSerialization"
const val ANNOTATION_GHOST_PROTO_SERIALIZATION = "GhostProtoSerialization"
/** `@GhostSerialization(textChannel = …)` argument name. */
const val ARG_TEXT_CHANNEL = "textChannel"
const val ARG_DISCRIMINATOR = "discriminator"
const val ARG_INFERRED = "inferred"
const val STR_DEFAULT_DISCRIMINATOR = "type"
const val ARG_NAME = "name"
const val PKG_KOTLIN = "kotlin"
const val STR_OPT_IN = "OptIn"
const val STR_INTERNAL_GHOST_API = "InternalGhostApi"
const val STR_TYPE_NAME_PROP = "typeName"
const val LINT_UNUSED_VARIABLE = "UNUSED_VARIABLE"
const val LINT_UNCHECKED_CAST = "UNCHECKED_CAST"
const val LINT_UNUSED = "unused"
const val HASH_MULTIPLIER_START = 31
const val HASH_MULTIPLIER_LIMIT = 15000
const val HASH_MULTIPLIER_STEP = 2
/** Polynomial multiplier for collision disambiguation. Must match COLLISION_HASH_MULTIPLIER in GhostJsonConstants. */
const val COLLISION_HASH_MULTIPLIER = 31
const val HASH_SHIFT_LIMIT = 16
const val HASH_TABLE_SIZE = 1024
const val HASH_MASK = 1023
const val BYTE_MASK = 0xFF
const val BIT_SHIFT_8 = 8
const val BIT_SHIFT_16 = 16
const val BIT_SHIFT_24 = 24
const val MARKER_CLASS = "%T::class"
const val STR_WRITER_NULL_VAL = "writer.nullValue()"
const val STR_ELIGIBILITY_MASK = "eligibilityMask"
const val STR_SEEN_MASK = "seenMask"
const val STR_REQ_MASK_PREFIX = "reqMask"
const val STR_INSTANCE_VAR = "instance"
const val STR_V_VAR_PREFIX = "v"
const val STR_INFERRED_ERROR_MSG = "Could not infer subclass (eligibilityMask: \$eligibilityMask, seenMask: \$seenMask)"
const val STR_REQUIRED_FIELD_MISSING = "Required field '%s' missing for %s"
const val STR_ERR_NO_SUBCLASSES = "Inferred polymorphism requested but no subclasses found."
const val STR_COPY = "copy"
const val STR_ONE_L = "1L"
const val STR_SHL = "shl"
const val STR_SPACE = " "
const val STR_L_SUFFIX = "L"
const val STR_IS_RESILIENT = "isResilient"
const val STR_IS_PROTO = "isProto"
const val STR_TRUE = "true"
// Templates
const val TEMPLATE_VAR_NULL_DECL = "var %L%L: %T = %L"
const val TEMPLATE_VAR_LONG_INIT = "var %L = %L%L"
const val TEMPLATE_VAR_INIT = "var %L = %L"
const val TEMPLATE_WHEN_BRANCH = "%L ->"
const val TEMPLATE_VAR_ASSIGN = "%L%L = %L"
const val TEMPLATE_MASK_AND_ASSIGN = "%L = %L and %L%L"
const val TEMPLATE_MASK_OR_SHL_ASSIGN = "%L = %L or (%L %L %L)"
const val TEMPLATE_VAL_LONG_INIT = "val %L%L = %L%L"
const val TEMPLATE_RESULT_WHEN = "val result = when"
const val TEMPLATE_INFERRED_DECISION_BRANCH = "(%L and %L%L) != %L && (%L and %L) == %L ->"
const val TEMPLATE_REQUIRED_ARG = "%L = %L ?: throw %T(%S)"
const val TEMPLATE_OPTIONAL_ARG = "%L = %L"
const val TEMPLATE_DATA_CLASS_COPY_INIT = "var %L = %T(%L)"
const val TEMPLATE_IF_NOT_NULL_COPY = "if (%L != null) %L = %L.%L(%L = %L)"
const val TEMPLATE_THROW_EXCEPTION = "throw %T(%S)"
const val TEMPLATE_PEEK_STRING_FIELD = "val typeName = reader.peekStringField(%S)"
const val STR_IT = "it"
const val FMT_LONG_LITERAL = "%dL"
const val MASK_SIZE_BITS = 64L
const val MASK_SIZE_BITS_MINUS_ONE = 63
const val STR_NULL_VAL_CALL = "writer.nullValue()"
// Control Flow Templates
const val TEMPLATE_IF_NULL = "if (%L == null)"
const val TEMPLATE_IF_NOT_NULL = "if (%L != null)"
const val TEMPLATE_IF_L = "if (%L)"
const val TEMPLATE_IS_INSTANCE = "%L is %T"
const val TEMPLATE_CAST = "(%L as %T)"
const val TEMPLATE_FOR_IN = "for (%L in %L)"
const val TEMPLATE_FOR_MAP = "for ((%L, %L) in %L)"
// proto3 default-value-omission conditions (guards a field write with "is not the zero value")
const val TEMPLATE_NEQ_ZERO_INT = "%L != 0"
const val TEMPLATE_NEQ_ZERO_LONG = "%L != 0L"
const val TEMPLATE_NEQ_ZERO_DOUBLE = "%L != 0.0"
const val TEMPLATE_NEQ_ZERO_FLOAT = "%L != 0.0f"
const val TEMPLATE_NEQ_ZERO_SHORT = "%L != 0.toShort()"
const val TEMPLATE_NEQ_ZERO_BYTE = "%L != 0.toByte()"
const val TEMPLATE_IS_NOT_EMPTY = "%L.isNotEmpty()"
const val TEMPLATE_ACCESSOR_L = "%L"
// Writer Templates
const val TEMPLATE_WRITER_VALUE = "writer.value(%L)"
const val TEMPLATE_WRITER_NAME = "writer.name(%L)"
// Misc
const val STR_ITEM_PREFIX = "item"
const val STR_MAP_KEY_PREFIX = "mapKey"
const val STR_MAP_VAL_PREFIX = "mapVal"
const val GHOST_SIGNATURE = "GhostSignature"
const val STR_WARN_CUSTOM_CODER = "Detected custom coder for %s: D=%s, E=%s"
const val TEMPLATE_NAMED_ARG = " %N = %L,"
const val TEMPLATE_ACCESSOR = "%L.%N"
const val TEMPLATE_VARIABLE = "%L"
const val PROPERTY_MAX_SIZE = 40
/**
* Maximum number of default-valued properties for which the compiler
* generates 2^N explicit constructor branches (zero .copy() allocations).
* Classes with more defaults fall back to the val _result + .copy() pattern.
* 3 → max 8 branches; 4 would mean 16 branches (too much code bloat).
*/
const val MAX_DEFAULT_BRANCH_COUNT = 4
const val STR_SRC_TEST = "/src/test/"
const val STR_SRC_ANDROID_TEST = "/src/androidTest/"
const val STR_SRC_TEST_KSP = "/src/testKsp/"
const val STR_TEST_SUFFIX = "_Test"
const val STR_FUN_VALIDATE_FIELDS = "validateRequiredFields"
const val STR_PARAM_MASK0 = "mask0"
const val TEMPLATE_IF_MASK_ZERO_STMT = "if ((mask0 and %L) == 0L)"
const val TEMPLATE_IF_MASK_NOT_MET_STMT = "if ((mask0 and %L) != %L)"
const val TEMPLATE_ELSE_IF_MASK_ZERO_STMT_NEW = "else if ((mask0 and %L) == 0L)"
const val TEMPLATE_VAR_VALUE_DECL = "var %LValue: %T = %L"
const val STR_MASK_INDEX_FMT = "mask%d"
const val TEMPLATE_OPTIONS_OF_SEEDS_START = "%T.of(%L, %L, %L, %L"
const val TEMPLATE_OPTIONS_OF_SEEDS_EXTENDED_START = "%T.of(%L, %L, %L, %L, %L"
const val STR_ERR_TEXT_CHANNEL_DISABLED = "String deserialization is disabled. Please configure arg(\"ghost.textChannel\", \"true\") in your KSP options to use the String parser."
const val STR_HS_PREFIX = "HS_"
const val TEMPLATE_OPTIONS_OF = "%T.of("
const val TEMPLATE_COMMA_FORMAT_S = ", %S"
const val TEMPLATE_CALL_VALIDATION = "%L(%L, %L)"
const val STR_MASK_PREFIX = "MASK_"
const val STR_MASK_REQUIRED_0 = "MASK_REQUIRED_0"
const val STR_MASK_OPTS_PREFIX = "MASK_OPTS_"
const val STR_MASK_DEFAULTS_PREFIX = "MASK_DEFAULTS_"
const val STR_SUB_INDEX_PREFIX = "subIndex"
const val TEMPLATE_L = "%L"
const val STR_ERR_PERFECT_HASH_COLLISION_1 = "Could not find a collision-free perfect hash configuration for fields: "
const val STR_ERR_PERFECT_HASH_COLLISION_2 = ". Please ensure there are no duplicate JSON names or conflicting field names."
// GhostJsonEnvelope
const val STR_GHOST_JSON_ENVELOPE = "GhostJsonEnvelope"
const val STR_GHOST_ENVELOPE_PAYLOAD = "GhostEnvelopePayload"
const val STR_GHOST_ENVELOPE_FALLBACK = "GhostEnvelopeFallback"
const val ARG_ENVELOPE_DISCRIMINATOR = "discriminator"
const val ARG_ENVELOPE_TIME_FIELD = "timeField"
const val ARG_ENVELOPE_DATA_FIELD = "dataField"
const val ARG_ENVELOPE_TARGET = "target"
const val STR_FUN_ROUTE_PAYLOAD = "routePayload"
const val STR_FUN_PARSE_PAYLOAD = "parsePayload"
const val STR_FUN_ROUTE_TYPED = "routeTyped"
const val STR_FUN_PARSE_TYPED = "parseTyped"
const val STR_PARAM_ENVELOPE = "envelope"
const val STR_PARAM_BYTES = "bytes"
const val STR_RAW_JSON_DECODE = "RawJsonDecode"
const val STR_GHOST = "Ghost"
const val STR_TYPE_ANY = "Any"
const val STR_ENVELOPE_RETURN_FIELD = "return envelope.%L"
const val STR_ENVELOPE_ROUTE_WHEN_OPEN = "return when (envelope.%L) {\n"
const val STR_ENVELOPE_ROUTE_CLOSE = "}"
const val STR_ENVELOPE_BRANCH = "%S -> %L\n"
const val STR_ENVELOPE_ELSE_NULL = "else -> null\n"
const val STR_ENVELOPE_ELSE_FALLBACK = "else -> envelope.%L\n"
const val STR_ENVELOPE_ELSE_GENERIC = "else -> envelope.%L\n"
const val STR_ENVELOPE_PARSE_BYTES_ROUTE = "val envelope = deserialize(%T(%L))\nreturn %L(envelope)"
const val STR_ENVELOPE_TARGET_SERIALIZER_SUFFIX = "TargetSerializer"
const val TEMPLATE_ENVELOPE_FIELD_ACCESS = "envelope.%L"
const val TEMPLATE_ENVELOPE_CACHED_SERIALIZER = "%T.getSerializer(%T::class)!!"
const val STR_KDOC_ROUTE_PAYLOAD = "Routes [%T] to its matching opaque JSON payload without re-parsing.\n"
const val STR_KDOC_PARSE_PAYLOAD = "Deserializes [%T] from bytes and routes to payload (zero-copy RawJson slice on flat reader).\n"
const val STR_KDOC_ROUTE_TYPED = "Routes [%T] and decodes annotated payload targets.\n"
const val STR_KDOC_PARSE_TYPED = "Deserializes [%T] from bytes and returns typed payload when configured.\n"
const val TEMPLATE_ENVELOPE_TYPED_SERIALIZER = "envelope.%L?.let { %T.decode(it, %L) }"
const val STR_ERR_ENVELOPE_DISC_1 = "GhostJsonEnvelope: discriminator field '"
const val STR_ERR_ENVELOPE_DISC_2 = "' not found on '"
const val STR_ERR_ENVELOPE_DISC_3 = "'."
const val STR_ERR_ENVELOPE_DISC_TYPE_1 = "GhostJsonEnvelope: discriminator property '"
const val STR_ERR_ENVELOPE_DISC_TYPE_2 = "' must be String."
const val STR_WARN_ENVELOPE_TIME_1 = "GhostJsonEnvelope: timeField '"
const val STR_WARN_ENVELOPE_TIME_2 = "' not found; ignoring."
const val STR_ERR_ENVELOPE_MULTI_FALLBACK = "GhostJsonEnvelope: at most one @GhostEnvelopeFallback property is allowed."
const val STR_ERR_ENVELOPE_DATA_1 = "GhostJsonEnvelope: dataField '"
const val STR_ERR_ENVELOPE_DATA_2 = "' not found on envelope class."
const val STR_WARN_ENVELOPE_UNTAGGED_1 = "GhostJsonEnvelope: opaque field '"
const val STR_WARN_ENVELOPE_UNTAGGED_2 = "' has no @GhostEnvelopePayload and will not be routed."
const val STR_ERR_ENVELOPE_NO_PAYLOADS = "GhostJsonEnvelope: no @GhostEnvelopePayload properties found (fat envelope mode)."
const val STR_ERR_ENVELOPE_DUP_VALUE_1 = "GhostJsonEnvelope: duplicate discriminator value '"
const val STR_ERR_ENVELOPE_DUP_VALUE_2 = "' on properties: "
const val STR_ERR_ENVELOPE_PAYLOAD_TYPE_1 = "GhostJsonEnvelope: payload property '"
const val STR_ERR_ENVELOPE_PAYLOAD_TYPE_2 = "' must be nullable RawJson."
const val STR_ERR_ENVELOPE_PAYLOAD_VALUE = "GhostJsonEnvelope: @GhostEnvelopePayload requires non-empty value."
// @GhostWrappedKeys
const val STR_GHOST_WRAPPED_KEYS_CAPTURE = "GhostWrappedKeysCapture"
const val STR_CAPTURE_WRAPPED_KEY_NAME = "captureWrappedKey"
const val STR_WRAPPED_CAPTURE_PREFIX = "wrappedCapture_"
const val STR_WRAPPED_KEY_LITERALS_PREFIX = "WRAPPED_KEY_LITERALS_"
const val STR_WRAPPED_OMIT_ABSENT_PREFIX = "WRAPPED_OMIT_ABSENT_"
const val STR_WRAPPED_JSON_VAR_PREFIX = "wrappedJson_"
const val STR_JSON_KEY_QUOTE = "\""
const val STR_JSON_KEY_COLON_SUFFIX = "\":"
const val TEMPLATE_CHAINED_MEMBER = "%L.%L"
const val TEMPLATE_WRAPPED_CAPTURE_VAR = "val %L = %T(%L)"
const val TEMPLATE_CAPTURE_WRAPPED_KEY = "reader.captureWrappedKey(%L, %L)"
const val TEMPLATE_WRAPPED_JSON_MATERIALIZE =
"val ${STR_WRAPPED_JSON_VAR_PREFIX}%L = %L.materializeWrappedObject(%L, %L, %L)"
const val TEMPLATE_WRAPPED_JSON_IF_NOT_NULL = "if (${STR_WRAPPED_JSON_VAR_PREFIX}%L != null)"
const val TEMPLATE_WRAPPED_READER_VAR = "val wrappedReader = %T(${STR_WRAPPED_JSON_VAR_PREFIX}%L)"
const val TEMPLATE_DESERIALIZE_WRAPPED_READER = "%T.deserialize(wrappedReader)"
const val TEMPLATE_NULL_ASSIGN = "%L = null"
const val TEMPLATE_ARRAY_OF_OPEN = "arrayOf(\n"
const val TEMPLATE_WRAPPED_KEY_LITERAL_BYTE = " %S.encodeToByteArray()"
const val TEMPLATE_INT_ARRAY_OF = "intArrayOf(%L)"
const val STR_NEWLINE_CLOSE_PAREN = "\n)"
const val STR_ERR_WRAPPED_DUP_KEY_1 = "GhostWrappedKeys: duplicate wire key '"
const val STR_ERR_WRAPPED_DUP_KEY_2 = "' on "
const val STR_ERR_WRAPPED_DUP_KEY_3 = " (properties '"
const val STR_ERR_WRAPPED_DUP_KEY_4 = "' and '"
const val STR_ERR_WRAPPED_DUP_KEY_5 = "')."
const val STR_ERR_WRAPPED_OMIT_IF_EMPTY_1 = "GhostWrappedKeys: omitIfEmpty = true requires nullable property '"
const val STR_ERR_WRAPPED_OMIT_IF_EMPTY_2 = "'."
const val STR_ERR_WRAPPED_COMBINE_1 = "GhostWrappedKeys: property '"
const val STR_ERR_WRAPPED_COMBINE_2 = "' cannot combine @GhostWrappedKeys with @GhostFlatten or @GhostWrap."
const val STR_ERR_WRAPPED_KEY_CONFLICT_1 = "GhostWrappedKeys: wire key '"
const val STR_ERR_WRAPPED_KEY_CONFLICT_2 = "' is both a wrapped source and a regular JSON property on "
const val STR_ERR_WRAPPED_KEY_CONFLICT_3 = "."
const val STR_ERR_WRAPPED_EMPTY_KEYS_1 = "GhostWrappedKeys: keys must not be empty on property '"
const val STR_ERR_WRAPPED_EMPTY_KEYS_2 = "'."
const val STR_WARN_WRAPPED_UNMAPPED_1 = "GhostWrappedKeys: wire key '"
const val STR_WARN_WRAPPED_UNMAPPED_2 = "' does not map to a field on "
// GeneratedSourceTrimmer
const val STR_NEWLINE = "\n"
const val STR_EXT_KT = "kt"
const val REGEX_TRIM_REDUNDANT_KOTLIN_IMPORT =
"""^import kotlin\.(String|Int|Long|Boolean|Double|Float|Byte|Short|Char|Unit|Any|Nothing|Array|OptIn|Suppress)(\..*)?\s*$"""
}