Skip to content

Commit 33c9c4b

Browse files
committed
refactor: rename PackedIntegerType to IntPacking and update references across the codebase
1 parent 7998059 commit 33c9c4b

File tree

8 files changed

+80
-79
lines changed

8 files changed

+80
-79
lines changed

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ Minimal example using the default `EncodedFormat` (Base62 + PackedFormat):
5151
```kotlin
5252
@Serializable
5353
data class Payload(
54-
@PackedType(PackedIntegerType.DEFAULT) val id: ULong, // low numbers are compacted
55-
@PackedType(PackedIntegerType.SIGNED) val delta: Int, // zigzagged to compact small negatives
54+
@PackedType(IntPacking.VARINT) val id: ULong, // low numbers are compacted
55+
@PackedType(IntPacking.ZIGZAG) val delta: Int, // zigzagged to compact small negatives
5656
val urgent: Boolean, // Packed into bitset
5757
val handled: Instant?, // Nullability tracked via bitset
5858
val type: PayloadType
@@ -76,8 +76,8 @@ payloads for Kotlin classes by moving structural metadata into a compact header.
7676

7777
* Bit-Packing: Booleans and nullability markers are stored in a single
7878
bit-header (about 1 bit per field).
79-
* VarInts: Int/Long fields can be optimized using `@PackedType(PackedIntegerType.DEFAULT)`
80-
(unsigned varint) or `@PackedType(PackedIntegerType.SIGNED)` (ZigZag) annotations.
79+
* VarInts: Int/Long fields can be optimized using `@PackedType(IntPacking.VARINT)`
80+
(unsigned varint) or `@PackedType(IntPacking.ZIGZAG)` (ZigZag) annotations.
8181
If you already use `kotlinx-serialization-protobuf`, `@ProtoType` annotations are
8282
recognized automatically as a fallback.
8383
* Full Graph Support: Handles nested objects, lists, maps, and polymorphism
@@ -87,7 +87,7 @@ payloads for Kotlin classes by moving structural metadata into a compact header.
8787

8888
```kotlin
8989
val compactFormat = PackedFormat {
90-
defaultEncoding = PackedIntegerType.SIGNED
90+
defaultEncoding = IntPacking.ZIGZAG
9191
serializersModule = myCustomModule
9292
}
9393
val bytes = compactFormat.encodeToByteArray(payload)

src/commonMain/kotlin/com/eignex/kencode/Annotations.kt

Lines changed: 16 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -8,63 +8,38 @@ import kotlinx.serialization.protobuf.ProtoIntegerType as KxProtoIntegerType
88
import kotlinx.serialization.protobuf.ProtoType as KxProtoType
99

1010
/**
11-
* Specifies the integer encoding strategy for `Int` and `Long` fields in [PackedFormat].
11+
* Integer encoding strategy for `Int` and `Long` fields in [PackedFormat].
1212
*
13-
* Mirrors [kotlinx.serialization.protobuf.ProtoIntegerType].
13+
* Compatible with [kotlinx.serialization.protobuf.ProtoIntegerType] as a fallback (see [PackedType]).
1414
*/
15-
enum class PackedIntegerType {
15+
enum class IntPacking {
1616
/** Unsigned variable-length (LEB128). Compact for small non-negative values. */
17-
DEFAULT,
17+
VARINT,
1818
/** ZigZag variable-length. Compact for small signed values. */
19-
SIGNED,
19+
ZIGZAG,
2020
/** Fixed-width. 4 bytes for `Int`, 8 bytes for `Long`. */
2121
FIXED
2222
}
2323

2424
/**
25-
* Marks an `Int` or `Long` field with an explicit encoding strategy in [PackedFormat].
26-
*
27-
* Mirrors [kotlinx.serialization.protobuf.ProtoType]:
28-
* - [PackedIntegerType.DEFAULT]: unsigned variable-length (LEB128)
29-
* - [PackedIntegerType.SIGNED]: ZigZag variable-length
30-
* - [PackedIntegerType.FIXED]: fixed-width (4 / 8 bytes)
31-
*
32-
* Usage:
33-
* ```
34-
* @Serializable
35-
* data class Example(
36-
* @PackedType(PackedIntegerType.DEFAULT) val id: Long, // compact for small positive values
37-
* @PackedType(PackedIntegerType.SIGNED) val delta: Int, // compact for small signed values
38-
* @PackedType(PackedIntegerType.FIXED) val hash: Int // always 4 bytes
39-
* )
40-
* ```
41-
*
42-
* Takes precedence over [kotlinx.serialization.protobuf.ProtoType] when both are present.
43-
* Has no effect for types outside [PackedFormat].
25+
* Overrides the integer encoding strategy for an `Int` or `Long` field in [PackedFormat].
26+
* Falls back to [kotlinx.serialization.protobuf.ProtoType] if present, then [PackedConfiguration.defaultEncoding].
4427
*/
4528
@SerialInfo
4629
@Target(AnnotationTarget.PROPERTY)
4730
@Retention(AnnotationRetention.SOURCE)
48-
annotation class PackedType(val type: PackedIntegerType)
49-
50-
internal enum class IntEncoding { FIXED, VARINT, ZIGZAG }
51-
52-
private fun PackedIntegerType.toIntEncoding(): IntEncoding = when (this) {
53-
PackedIntegerType.DEFAULT -> IntEncoding.VARINT
54-
PackedIntegerType.SIGNED -> IntEncoding.ZIGZAG
55-
PackedIntegerType.FIXED -> IntEncoding.FIXED
56-
}
31+
annotation class PackedType(val type: IntPacking)
5732

58-
private fun KxProtoIntegerType.toIntEncoding(): IntEncoding = when (this) {
59-
KxProtoIntegerType.DEFAULT -> IntEncoding.VARINT
60-
KxProtoIntegerType.SIGNED -> IntEncoding.ZIGZAG
61-
KxProtoIntegerType.FIXED -> IntEncoding.FIXED
33+
private fun KxProtoIntegerType.toIntPacking(): IntPacking = when (this) {
34+
KxProtoIntegerType.DEFAULT -> IntPacking.VARINT
35+
KxProtoIntegerType.SIGNED -> IntPacking.ZIGZAG
36+
KxProtoIntegerType.FIXED -> IntPacking.FIXED
6237
}
6338

64-
internal fun resolveIntEncoding(anns: List<Annotation>, config: PackedConfiguration): IntEncoding {
65-
anns.filterIsInstance<PackedType>().firstOrNull()?.let { return it.type.toIntEncoding() }
39+
internal fun resolveIntEncoding(anns: List<Annotation>, config: PackedConfiguration): IntPacking {
40+
anns.filterIsInstance<PackedType>().firstOrNull()?.let { return it.type }
6641
try {
67-
anns.filterIsInstance<KxProtoType>().firstOrNull()?.let { return it.type.toIntEncoding() }
42+
anns.filterIsInstance<KxProtoType>().firstOrNull()?.let { return it.type.toIntPacking() }
6843
} catch (_: Throwable) { }
69-
return config.defaultEncoding.toIntEncoding()
44+
return config.defaultEncoding
7045
}

src/commonMain/kotlin/com/eignex/kencode/PackedDecoder.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -228,16 +228,16 @@ class PackedDecoder internal constructor(
228228

229229
override fun decodeIntElement(descriptor: SerialDescriptor, index: Int): Int =
230230
when (resolveIntEncoding(descriptor.getElementAnnotations(index), config)) {
231-
IntEncoding.ZIGZAG -> PackedUtils.zigZagDecodeInt(readVarInt())
232-
IntEncoding.VARINT -> readVarInt()
233-
IntEncoding.FIXED -> readIntPos()
231+
IntPacking.ZIGZAG -> PackedUtils.zigZagDecodeInt(readVarInt())
232+
IntPacking.VARINT -> readVarInt()
233+
IntPacking.FIXED -> readIntPos()
234234
}
235235

236236
override fun decodeLongElement(descriptor: SerialDescriptor, index: Int): Long =
237237
when (resolveIntEncoding(descriptor.getElementAnnotations(index), config)) {
238-
IntEncoding.ZIGZAG -> PackedUtils.zigZagDecodeLong(readVarLong())
239-
IntEncoding.VARINT -> readVarLong()
240-
IntEncoding.FIXED -> readLongPos()
238+
IntPacking.ZIGZAG -> PackedUtils.zigZagDecodeLong(readVarLong())
239+
IntPacking.VARINT -> readVarLong()
240+
IntPacking.FIXED -> readLongPos()
241241
}
242242

243243
override fun decodeFloatElement(descriptor: SerialDescriptor, index: Int): Float =

src/commonMain/kotlin/com/eignex/kencode/PackedEncoder.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -203,17 +203,17 @@ class PackedEncoder internal constructor(
203203

204204
override fun encodeIntElement(descriptor: SerialDescriptor, index: Int, value: Int) {
205205
when (resolveIntEncoding(descriptor.getElementAnnotations(index), config)) {
206-
IntEncoding.ZIGZAG -> PackedUtils.writeVarInt(PackedUtils.zigZagEncodeInt(value), dataBuffer)
207-
IntEncoding.VARINT -> PackedUtils.writeVarInt(value, dataBuffer)
208-
IntEncoding.FIXED -> PackedUtils.writeInt(value, dataBuffer)
206+
IntPacking.ZIGZAG -> PackedUtils.writeVarInt(PackedUtils.zigZagEncodeInt(value), dataBuffer)
207+
IntPacking.VARINT -> PackedUtils.writeVarInt(value, dataBuffer)
208+
IntPacking.FIXED -> PackedUtils.writeInt(value, dataBuffer)
209209
}
210210
}
211211

212212
override fun encodeLongElement(descriptor: SerialDescriptor, index: Int, value: Long) {
213213
when (resolveIntEncoding(descriptor.getElementAnnotations(index), config)) {
214-
IntEncoding.ZIGZAG -> PackedUtils.writeVarLong(PackedUtils.zigZagEncodeLong(value), dataBuffer)
215-
IntEncoding.VARINT -> PackedUtils.writeVarLong(value, dataBuffer)
216-
IntEncoding.FIXED -> PackedUtils.writeLong(value, dataBuffer)
214+
IntPacking.ZIGZAG -> PackedUtils.writeVarLong(PackedUtils.zigZagEncodeLong(value), dataBuffer)
215+
IntPacking.VARINT -> PackedUtils.writeVarLong(value, dataBuffer)
216+
IntPacking.FIXED -> PackedUtils.writeLong(value, dataBuffer)
217217
}
218218
}
219219

src/commonMain/kotlin/com/eignex/kencode/PackedFormat.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ import kotlinx.serialization.modules.SerializersModule
88
* Holds the configuration for a [PackedFormat] instance.
99
*
1010
* @property defaultEncoding The encoding applied to all `Int` and `Long` fields that carry no
11-
* [PackedType] annotation. Defaults to [PackedIntegerType.FIXED] (4 / 8 raw bytes).
11+
* [PackedType] annotation. Defaults to [IntPacking.FIXED] (4 / 8 raw bytes).
1212
*/
1313
data class PackedConfiguration(
14-
val defaultEncoding: PackedIntegerType = PackedIntegerType.FIXED
14+
val defaultEncoding: IntPacking = IntPacking.FIXED
1515
)
1616

1717
/**
@@ -76,17 +76,17 @@ class PackedFormatBuilder {
7676

7777
/**
7878
* The encoding applied to all `Int` and `Long` fields that carry no [PackedType] annotation.
79-
* Defaults to [PackedIntegerType.FIXED].
79+
* Defaults to [IntPacking.FIXED].
8080
*/
81-
var defaultEncoding: PackedIntegerType = PackedIntegerType.FIXED
81+
var defaultEncoding: IntPacking = IntPacking.FIXED
8282
}
8383

8484
/**
8585
* Creates a customized [PackedFormat] instance.
8686
*
8787
* ```
8888
* val format = PackedFormat {
89-
* defaultEncoding = PackedIntegerType.SIGNED
89+
* defaultEncoding = Packing.ZIGZAG
9090
* serializersModule = myCustomModule
9191
* }
9292
* ```

src/commonTest/kotlin/com/eignex/kencode/PackedFormatTest.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ class PackedFormatTest {
265265

266266
val standardFormat = PackedFormat.Default
267267
val optimizedFormat =
268-
PackedFormat { defaultEncoding = PackedIntegerType.DEFAULT }
268+
PackedFormat { defaultEncoding = IntPacking.VARINT }
269269

270270
val standardBytes = standardFormat.encodeToByteArray(
271271
UnannotatedPayload.serializer(),
@@ -296,9 +296,9 @@ class PackedFormatTest {
296296

297297
val standardFormat = PackedFormat.Default
298298
val varIntFormat =
299-
PackedFormat { defaultEncoding = PackedIntegerType.DEFAULT }
299+
PackedFormat { defaultEncoding = IntPacking.VARINT }
300300
val zigZagFormat =
301-
PackedFormat { defaultEncoding = PackedIntegerType.SIGNED }
301+
PackedFormat { defaultEncoding = IntPacking.ZIGZAG }
302302

303303
// Standard: 12 bytes
304304
assertEquals(
@@ -337,7 +337,7 @@ class PackedFormatTest {
337337
val payload = InversePayload(5, -10L, 6u, 7uL)
338338

339339
val optimizedFormat =
340-
PackedFormat { defaultEncoding = PackedIntegerType.SIGNED }
340+
PackedFormat { defaultEncoding = IntPacking.ZIGZAG }
341341

342342
val bytes = optimizedFormat.encodeToByteArray(
343343
InversePayload.serializer(),

src/commonTest/kotlin/com/eignex/kencode/TestClasses.kt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,10 @@ data class StringHeavyPayload(
7575

7676
@Serializable
7777
data class VarIntVarUIntPayload(
78-
@PackedType(PackedIntegerType.SIGNED) val signedIntVar: Int,
79-
@PackedType(PackedIntegerType.SIGNED) val signedLongVar: Long,
80-
@PackedType(PackedIntegerType.DEFAULT) val unsignedIntVar: Int,
81-
@PackedType(PackedIntegerType.DEFAULT) val unsignedLongVar: Long,
78+
@PackedType(IntPacking.ZIGZAG) val signedIntVar: Int,
79+
@PackedType(IntPacking.ZIGZAG) val signedLongVar: Long,
80+
@PackedType(IntPacking.VARINT) val unsignedIntVar: Int,
81+
@PackedType(IntPacking.VARINT) val unsignedLongVar: Long,
8282
val plainInt: Int,
8383
val plainLong: Long
8484
)
@@ -638,8 +638,8 @@ data class UnannotatedPayload(val x: Int, val y: Long)
638638

639639
@Serializable
640640
data class InversePayload(
641-
@PackedType(PackedIntegerType.FIXED) val fixedX: Int,
642-
@PackedType(PackedIntegerType.FIXED) val fixedY: Long,
643-
@PackedType(PackedIntegerType.FIXED) val fixedUX: UInt,
644-
@PackedType(PackedIntegerType.FIXED) val fixedUY: ULong
641+
@PackedType(IntPacking.FIXED) val fixedX: Int,
642+
@PackedType(IntPacking.FIXED) val fixedY: Long,
643+
@PackedType(IntPacking.FIXED) val fixedUX: UInt,
644+
@PackedType(IntPacking.FIXED) val fixedUY: ULong
645645
)

src/jvmTest/kotlin/com/eignex/kencode/Examples.kt

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ class Examples {
2222
data class Payload(
2323

2424
// only uses as many bytes as needed
25-
@PackedType(PackedIntegerType.DEFAULT)
25+
@PackedType(IntPacking.VARINT)
2626
val id: ULong,
2727

28-
@PackedType(PackedIntegerType.SIGNED) // zig-zag encodes small negatives efficiently
28+
@PackedType(IntPacking.ZIGZAG) // zig-zag encodes small negatives efficiently
2929
val delta: Int,
3030

3131
// these are packed into a bitset along with nullability flags
@@ -42,6 +42,30 @@ class Examples {
4242
TYPE1, TYPE2, TYPE3
4343
}
4444

45+
@Test
46+
fun `blog post example`() {
47+
@Serializable
48+
data class JobState(
49+
val clientId: Int,
50+
val batchId: Int,
51+
val retryCount: Int?,
52+
val isPriority: Boolean
53+
)
54+
55+
val state = JobState(119, 210, null, true)
56+
val encodedFormat = EncodedFormat {
57+
binaryFormat =
58+
PackedFormat { defaultEncoding = IntPacking.VARINT }
59+
}
60+
val encodedState = encodedFormat.encodeToString(state)
61+
println(encodedState)
62+
// This encodes the object into the string:
63+
// 02waa1a8
64+
65+
val decodedState =
66+
encodedFormat.decodeFromString<JobState>(encodedState)
67+
}
68+
4569
@Test
4670
fun `example serialization`() {
4771
val payload = Payload(
@@ -120,10 +144,12 @@ class Examples {
120144
val secureFormat = EncodedFormat { transform = xteaTransform }
121145

122146
val payload = SensitiveData(random.nextLong())
123-
val token = secureFormat.encodeToString(SensitiveData.serializer(), payload)
147+
val token =
148+
secureFormat.encodeToString(SensitiveData.serializer(), payload)
124149
println(token)
125150

126-
val result = secureFormat.decodeFromString(SensitiveData.serializer(), token)
151+
val result =
152+
secureFormat.decodeFromString(SensitiveData.serializer(), token)
127153
println(result)
128154

129155
assertEquals(payload, result)

0 commit comments

Comments
 (0)