• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

CyclopsMC / CyclopsCore / #479033853

06 Nov 2026 12:50PM UTC coverage: 23.052% (+0.005%) from 23.047%
#479033853

Pull #259

github

claude
Log packet encoding and decoding errors

When a packet fails to encode or decode, vanilla disconnects with
"Internal Exception" but only logs the cause at debug level, so it is
missing from latest.log. Log the full stack trace at error level, so
these disconnects can be diagnosed from regular logs.

The decoding error now names the packet class instead of a fresh
instance's toString, which also avoids an NPE when construction failed.

Related to #258

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UeSuG8Sp4V22VPUqWFGwM7
Pull Request #259: Fix packets failing to decode when a map is modified while encoding, and log codec errors

2 of 6 new or added lines in 2 files covered. (33.33%)

28 existing lines in 1 file now uncovered.

2444 of 10602 relevant lines covered (23.05%)

0.23 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

67.83
/src/main/java/org/cyclops/cyclopscore/network/PacketCodec.java
1
package org.cyclops.cyclopscore.network;
2

3
import com.google.common.collect.Lists;
4
import com.google.common.collect.Maps;
5
import net.minecraft.core.BlockPos;
6
import net.minecraft.core.Direction;
7
import net.minecraft.core.Vec3i;
8
import net.minecraft.nbt.CompoundTag;
9
import net.minecraft.nbt.Tag;
10
import net.minecraft.network.FriendlyByteBuf;
11
import net.minecraft.resources.ResourceKey;
12
import net.minecraft.resources.ResourceLocation;
13
import net.minecraft.world.item.ItemStack;
14
import net.minecraft.world.phys.Vec3;
15
import net.minecraftforge.fluids.FluidStack;
16
import org.apache.commons.lang3.ClassUtils;
17
import org.apache.commons.lang3.tuple.Pair;
18
import org.cyclops.cyclopscore.datastructure.DimPos;
19
import org.cyclops.cyclopscore.datastructure.SingleCache;
20
import org.cyclops.cyclopscore.inventory.ItemLocation;
21
import org.joml.Vector3d;
22

23
import javax.annotation.Nullable;
24
import java.lang.reflect.Field;
25
import java.util.Arrays;
26
import java.util.Collections;
27
import java.util.Comparator;
28
import java.util.List;
29
import java.util.Map;
30
import java.util.Objects;
31

32
/**
33
 * Packet with automatic coding and decoding of basic fields annotated with {@link CodecField}.
34
 * @author rubensworks
35
 *
36
 */
37
public abstract class PacketCodec extends PacketBase {
1 ✔
38

39
    public static final int READ_STRING_MAX_LENGTH = 32767;
40

41
    private static Map<Class<?>, ICodecAction> codecActions = Maps.newHashMap();
1 ✔
42
    static {
43
        codecActions.put(String.class, new ICodecAction() {
1 ✔
44

45
            @Override
46
            public void encode(Object object, FriendlyByteBuf output) {
47
                output.writeUtf((String) object);
1 ✔
48
            }
1 ✔
49

50
            @Override
51
            public Object decode(FriendlyByteBuf input) {
52
                return input.readUtf(32767); // The arg-less version is client-side only, so we copy its implementation.
1 ✔
53
            }
54
        });
55

56
        codecActions.put(double.class, new ICodecAction() {
1 ✔
57

58
            @Override
59
            public void encode(Object object, FriendlyByteBuf output) {
60
                output.writeDouble((Double) object);
1 ✔
61
            }
1 ✔
62

63
            @Override
64
            public Object decode(FriendlyByteBuf input) {
65
                return input.readDouble();
1 ✔
66
            }
67
        });
68

69
        codecActions.put(int.class, new ICodecAction() {
1 ✔
70

71
            @Override
72
            public void encode(Object object, FriendlyByteBuf output) {
73
                output.writeInt((int) object);
1 ✔
74
            }
1 ✔
75

76
            @Override
77
            public Object decode(FriendlyByteBuf input) {
78
                return input.readInt();
1 ✔
79
            }
80
        });
81

82
        codecActions.put(long.class, new ICodecAction() {
1 ✔
83

84
            @Override
85
            public void encode(Object object, FriendlyByteBuf output) {
86
                output.writeLong((long) object);
1 ✔
87
            }
1 ✔
88

89
            @Override
90
            public Object decode(FriendlyByteBuf input) {
91
                return input.readLong();
1 ✔
92
            }
93
        });
94

95
        codecActions.put(short.class, new ICodecAction() {
1 ✔
96

97
            @Override
98
            public void encode(Object object, FriendlyByteBuf output) {
99
                output.writeShort((Short) object);
1 ✔
100
            }
1 ✔
101

102
            @Override
103
            public Object decode(FriendlyByteBuf input) {
104
                return input.readShort();
1 ✔
105
            }
106
        });
107

108
        codecActions.put(boolean.class, new ICodecAction() {
1 ✔
109

110
            @Override
111
            public void encode(Object object, FriendlyByteBuf output) {
112
                output.writeBoolean((Boolean) object);
1 ✔
113
            }
1 ✔
114

115
            @Override
116
            public Object decode(FriendlyByteBuf input) {
117
                return input.readBoolean();
1 ✔
118
            }
119
        });
120

121
        codecActions.put(float.class, new ICodecAction() {
1 ✔
122

123
            @Override
124
            public void encode(Object object, FriendlyByteBuf output) {
125
                output.writeFloat((Float) object);
1 ✔
126
            }
1 ✔
127

128
            @Override
129
            public Object decode(FriendlyByteBuf input) {
130
                return input.readFloat();
1 ✔
131
            }
132
        });
133

134
        codecActions.put(Vector3d.class, new ICodecAction() {
1 ✔
135
            @Override
136
            public void encode(Object object, FriendlyByteBuf output) {
137
                Vector3d v = (Vector3d)object;
1 ✔
138
                output.writeDouble(v.x);
1 ✔
139
                output.writeDouble(v.y);
1 ✔
140
                output.writeDouble(v.z);
1 ✔
141
            }
1 ✔
142

143
            @Override
144
            public Object decode(FriendlyByteBuf input) {
145
                double x = input.readDouble();
1 ✔
146
                double y = input.readDouble();
1 ✔
147
                double z = input.readDouble();
1 ✔
148
                return new Vector3d(x, y, z);
1 ✔
149
            }
150
        });
151

152
        codecActions.put(Vec3i.class, new ICodecAction() {
1 ✔
153
            @Override
154
            public void encode(Object object, FriendlyByteBuf output) {
155
                Vec3i v = (Vec3i)object;
×
156
                output.writeInt(v.getX());
×
157
                output.writeInt(v.getY());
×
158
                output.writeInt(v.getZ());
×
159
            }
×
160

161
            @Override
162
            public Object decode(FriendlyByteBuf input) {
163
                int x = input.readInt();
×
164
                int y = input.readInt();
×
165
                int z = input.readInt();
×
166
                return new Vec3i(x, y, z);
×
167
            }
168
        });
169

170
        codecActions.put(Vec3.class, new ICodecAction() {
1 ✔
171
            @Override
172
            public void encode(Object object, FriendlyByteBuf output) {
173
                Vec3 v = (Vec3)object;
×
174
                output.writeDouble(v.x);
×
175
                output.writeDouble(v.y);
×
176
                output.writeDouble(v.z);
×
177
            }
×
178

179
            @Override
180
            public Object decode(FriendlyByteBuf input) {
181
                double x = input.readDouble();
×
182
                double y = input.readDouble();
×
183
                double z = input.readDouble();
×
184
                return new Vec3(x, y, z);
×
185
            }
186
        });
187

188
        codecActions.put(Map.class, new ICodecAction() {
1 ✔
189

190
            // Packet structure:
191
            // Map length (int)
192
            // --- end if length == 0
193
            // Key class name (UTF)
194
            // Value class name (UTF)
195
            // for length
196
            //   key
197
            //   value
198

199
            @SuppressWarnings({ "rawtypes", "unchecked" })
200
            @Override
201
            public void encode(Object object, FriendlyByteBuf output) {
202
                Map map = (Map) object;
1 ✔
203
                // Snapshot, so the written size matches the written entries if the map is modified concurrently.
204
                List<Map.Entry> entries = Lists.newArrayList(map.entrySet());
1 ✔
205
                output.writeInt(entries.size());
1 ✔
206
                ICodecAction keyAction = null;
1 ✔
207
                ICodecAction valueAction = null;
1 ✔
208
                for(Map.Entry entry : entries) {
1 ✔
209
                    if(keyAction == null) {
1 ✔
210
                        keyAction = getAction(entry.getKey().getClass());
1 ✔
211
                        output.writeUtf(entry.getKey().getClass().getName());
1 ✔
212
                    }
213
                    if(valueAction == null) {
1 ✔
214
                        valueAction = getAction(entry.getValue().getClass());
1 ✔
215
                        output.writeUtf(entry.getValue().getClass().getName());
1 ✔
216
                    }
217
                    keyAction.encode(entry.getKey(), output);
1 ✔
218
                    valueAction.encode(entry.getValue(), output);
1 ✔
219
                }
1 ✔
220
            }
1 ✔
221

222
            @SuppressWarnings({ "rawtypes", "unchecked" })
223
            @Override
224
            public Object decode(FriendlyByteBuf input) {
225
                Map map = Maps.newHashMap();
1 ✔
226
                int size = input.readInt();
1 ✔
227
                if(size == 0) {
1 ✔
228
                    return map;
1 ✔
229
                }
230
                try {
231
                    ICodecAction keyAction = getAction(Class.forName(input.readUtf(READ_STRING_MAX_LENGTH)));
1 ✔
232
                    ICodecAction valueAction = getAction(Class.forName(input.readUtf(READ_STRING_MAX_LENGTH)));
1 ✔
233
                    for(int i = 0; i < size; i++) {
1 ✔
234
                        Object key = keyAction.decode(input);
1 ✔
235
                        Object value = valueAction.decode(input);
1 ✔
236
                        map.put(key, value);
1 ✔
237
                    }
238
                } catch (ClassNotFoundException e) {
×
UNCOV
239
                    e.printStackTrace();
×
240
                }
1 ✔
241
                return map;
1 ✔
242
            }
243
        });
244

245
        codecActions.put(CompoundTag.class, new ICodecAction() {
1 ✔
246

247
            @Override
248
            public void encode(Object object, FriendlyByteBuf output) {
249
                output.writeNbt((CompoundTag) object);
1 ✔
250
            }
1 ✔
251

252
            @Override
253
            public Object decode(FriendlyByteBuf input) {
254
                return input.readNbt();
1 ✔
255
            }
256
        });
257

258
        codecActions.put(Tag.class, new ICodecAction() {
1 ✔
259

260
            @Override
261
            public void encode(Object object, FriendlyByteBuf output) {
262
                CompoundTag tag = new CompoundTag();
×
263
                tag.put("v", (Tag) object);
×
264
                output.writeNbt(tag);
×
UNCOV
265
            }
×
266

267
            @Override
268
            public Object decode(FriendlyByteBuf input) {
269
                CompoundTag tag = input.readNbt();
×
UNCOV
270
                return tag.get("v");
×
271
            }
272
        });
273

274
        codecActions.put(ItemStack.class, new ICodecAction() {
1 ✔
275

276
            @Override
277
            public void encode(Object object, FriendlyByteBuf output) {
278
                output.writeItem((ItemStack) object);
×
UNCOV
279
            }
×
280

281
            @Override
282
            public Object decode(FriendlyByteBuf input) {
UNCOV
283
                return input.readItem();
×
284
            }
285
        });
286

287
        codecActions.put(FluidStack.class, new ICodecAction() {
1 ✔
288

289
            @Override
290
            public void encode(Object object, FriendlyByteBuf output) {
291
                output.writeNbt(((FluidStack) object).writeToNBT(new CompoundTag()));
×
UNCOV
292
            }
×
293

294
            @Override
295
            public Object decode(FriendlyByteBuf input) {
UNCOV
296
                return FluidStack.loadFluidStackFromNBT(input.readNbt());
×
297
            }
298
        });
299

300
        codecActions.put(Direction.class, new ICodecAction() {
1 ✔
301

302
            @Override
303
            public void encode(Object object, FriendlyByteBuf output) {
304
                output.writeInt(((Direction) object).ordinal());
1 ✔
305
            }
1 ✔
306

307
            @Override
308
            public Object decode(FriendlyByteBuf input) {
309
                return Direction.values()[input.readInt()];
1 ✔
310
            }
311
        });
312

313
        codecActions.put(BlockPos.class, new ICodecAction() {
1 ✔
314

315
            @Override
316
            public void encode(Object object, FriendlyByteBuf output) {
317
                output.writeBlockPos((BlockPos) object);
1 ✔
318
            }
1 ✔
319

320
            @Override
321
            public Object decode(FriendlyByteBuf input) {
322
                return input.readBlockPos();
1 ✔
323
            }
324
        });
325

326
        codecActions.put(ResourceKey.class, new ICodecAction() {
1 ✔
327

328
            @Override
329
            public void encode(Object object, FriendlyByteBuf output) {
330
                output.writeUtf(((ResourceKey) object).registry().toString());
×
331
                output.writeUtf(((ResourceKey) object).location().toString());
×
UNCOV
332
            }
×
333

334
            @Override
335
            public Object decode(FriendlyByteBuf input) {
336
                return ResourceKey.create(
×
337
                        ResourceKey.createRegistryKey(new ResourceLocation(input.readUtf(READ_STRING_MAX_LENGTH))),
×
UNCOV
338
                        new ResourceLocation(input.readUtf(READ_STRING_MAX_LENGTH)));
×
339
            }
340
        });
341

342
        codecActions.put(DimPos.class, new ICodecAction() {
1 ✔
343

344
            @Override
345
            public void encode(Object object, FriendlyByteBuf output) {
346
                write(output, ((DimPos) object).getLevelKey());
×
347
                write(output, ((DimPos) object).getBlockPos());
×
UNCOV
348
            }
×
349

350
            @Override
351
            public Object decode(FriendlyByteBuf input) {
352
                ResourceKey dimensionType = read(input, ResourceKey.class);
×
353
                BlockPos blockPos = read(input, BlockPos.class);
×
UNCOV
354
                return DimPos.of(dimensionType, blockPos);
×
355
            }
356
        });
357

358
        codecActions.put(List.class, new ICodecAction() {
1 ✔
359

360
            // Packet structure:
361
            // list length (int)
362
            // --- end if length == 0
363
            // Value class name (UTF)
364
            //         id + value
365
            // -1
366

367
            @Override
368
            public void encode(Object object, FriendlyByteBuf output) {
369
                List<?> list = (List<?>) object;
1 ✔
370
                output.writeInt(list.size());
1 ✔
371
                if(list.size() == 0) return;
1 ✔
372
                ICodecAction valueAction = null;
1 ✔
373
                for(int i = 0; i < list.size(); i++) {
1 ✔
374
                    Object value = list.get(i);
1 ✔
375
                    if(value != null) {
1 ✔
376
                        if (valueAction == null) {
1 ✔
377
                            valueAction = getAction(value.getClass());
1 ✔
378
                            output.writeUtf(value.getClass().getName());
1 ✔
379
                        }
380
                        output.writeInt(i);
1 ✔
381
                        valueAction.encode(value, output);
1 ✔
382
                    }
383
                }
384
                if(valueAction == null) {
1 ✔
UNCOV
385
                    output.writeUtf("__noclass");
×
386
                } else {
387
                    output.writeInt(-1);
1 ✔
388
                }
389
            }
1 ✔
390

391
            @SuppressWarnings({ "rawtypes", "unchecked" })
392
            @Override
393
            public Object decode(FriendlyByteBuf input) {
394
                List list;
395
                int size = input.readInt();
1 ✔
396
                if(size == 0) {
1 ✔
397
                    return Collections.emptyList();
1 ✔
398
                } else {
399
                    list = Lists.newArrayListWithExpectedSize(size);
1 ✔
400
                }
401
                try {
402
                    String className = input.readUtf(READ_STRING_MAX_LENGTH);
1 ✔
403
                    if(!className.equals("__noclass")) {
1 ✔
404
                        ICodecAction valueAction = getAction(Class.forName(className));
1 ✔
405
                        int i, currentLength = 0;
1 ✔
406
                        while((i = input.readInt()) >= 0) {
1 ✔
407
                            while(currentLength < i) {
1 ✔
408
                                list.add(null);
1 ✔
409
                                currentLength++;
1 ✔
410
                            }
411
                            Object value = valueAction.decode(input);
1 ✔
412
                            list.add(value);
1 ✔
413
                            currentLength++;
1 ✔
414
                        }
1 ✔
415
                        while(currentLength < size) {
1 ✔
416
                            list.add(null);
1 ✔
417
                            currentLength++;
1 ✔
418
                        }
419
                    } else {
1 ✔
420
                        for (int i = 0; i < size; i++) {
×
UNCOV
421
                            list.add(null);
×
422
                        }
423
                    }
424
                } catch (ClassNotFoundException e) {
×
UNCOV
425
                    e.printStackTrace();
×
426
                }
1 ✔
427
                return list;
1 ✔
428
            }
429
        });
430

431
        codecActions.put(Pair.class, new ICodecAction() {
1 ✔
432

433
            @Override
434
            public void encode(Object object, FriendlyByteBuf output) {
435
                output.writeUtf(((Pair) object).getLeft().getClass().getName());
×
436
                output.writeUtf(((Pair) object).getRight().getClass().getName());
×
437
                write(output, ((Pair) object).getLeft());
×
438
                write(output, ((Pair) object).getRight());
×
UNCOV
439
            }
×
440

441
            @Override
442
            public Object decode(FriendlyByteBuf input) {
443
                try {
444
                    ICodecAction keyAction = getAction(Class.forName(input.readUtf(READ_STRING_MAX_LENGTH)));
×
445
                    ICodecAction valueAction = getAction(Class.forName(input.readUtf(READ_STRING_MAX_LENGTH)));
×
446
                    Object key = keyAction.decode(input);
×
447
                    Object value = valueAction.decode(input);
×
448
                    return Pair.of(key, value);
×
449
                } catch (ClassNotFoundException e) {
×
UNCOV
450
                    e.printStackTrace();
×
451
                }
UNCOV
452
                return Pair.of(null, null);
×
453
            }
454
        });
455

456
        codecActions.put(ItemLocation.class, new ICodecAction() {
1 ✔
457

458
            @Override
459
            public void encode(Object object, FriendlyByteBuf output) {
460
                ItemLocation.writeToPacketBuffer(output, (ItemLocation) object);
×
UNCOV
461
            }
×
462

463
            @Override
464
            public Object decode(FriendlyByteBuf input) {
UNCOV
465
                return ItemLocation.readFromPacketBuffer(input);
×
466
            }
467
        });
468
    }
1 ✔
469

470
    /**
471
     * Register a new coded action.
472
     * @param clazz A class type.
473
     * @param action A codec action for the given type.
474
     */
475
    public static void addCodedAction(Class<?> clazz, ICodecAction action) {
476
        codecActions.put(clazz, action);
×
UNCOV
477
    }
×
478

479
    protected SingleCache<Void, List<Field>> fieldCache = new SingleCache<Void, List<Field>>(
1 ✔
480
            new SingleCache.ICacheUpdater<Void, List<Field>>() {
1 ✔
481

482
        @Override
483
        public List<Field> getNewValue(Void key) {
484
            List<Field> fieldList = Lists.newLinkedList();
1 ✔
485

486
            Class<?> clazz = PacketCodec.this.getClass();
1 ✔
487
            for (; clazz != PacketCodec.class && clazz != null; clazz = clazz.getSuperclass()) {
1 ✔
488
                Field[] fields = clazz.getDeclaredFields();
1 ✔
489

490
                // Sort this because the Java API tells us that getDeclaredFields()
491
                // does not deterministically define the order of the fields in the array.
492
                // Otherwise we might get nasty class cast exceptions when running in SMP.
493
                Arrays.sort(fields, new Comparator<Field>() {
1 ✔
494

495
                    @Override
496
                    public int compare(Field o1, Field o2) {
497
                        return o1.getName().compareTo(o2.getName());
1 ✔
498
                    }
499

500
                });
501

502
                for (final Field field : fields) {
1 ✔
503
                    if (field.isAnnotationPresent(CodecField.class)) {
1 ✔
504
                        fieldList.add(field);
1 ✔
505
                    }
506
                }
507
            }
508

509
            return fieldList;
1 ✔
510
        }
511

512
        @Override
513
        public boolean isKeyEqual(Void cacheKey, Void newKey) {
UNCOV
514
            return true;
×
515
        }
516

517
    });
518

519
    @Nullable
520
    protected static ICodecAction getActionSuper(Class<?> clazz) {
521
        if(ClassUtils.isPrimitiveWrapper(clazz)) {
1 ✔
522
            clazz = ClassUtils.wrapperToPrimitive(clazz);
1 ✔
523
        }
524
        ICodecAction action = codecActions.get(clazz);
1 ✔
525
        if(action == null) {
1 ✔
526
            for (Class<?> iface : clazz.getInterfaces()) {
1 ✔
527
                action = codecActions.get(iface);
1 ✔
528
                if (action != null) {
1 ✔
529
                    return action;
1 ✔
530
                }
531
            }
532
            Class<?> superClass = clazz.getSuperclass();
×
533
            if (superClass != null) {
×
UNCOV
534
                return getActionSuper(superClass);
×
535
            } else {
UNCOV
536
                return null;
×
537
            }
538
        }
539
        return action;
1 ✔
540
    }
541

542
    public static ICodecAction getAction(Class<?> clazz) {
543
        ICodecAction action = getActionSuper(clazz);
1 ✔
544
        if(action == null) {
1 ✔
UNCOV
545
            System.err.println("No ICodecAction was found for " + clazz
×
546
                    + ". You should add one in PacketCodec.");
547
        }
548
        return action;
1 ✔
549
    }
550

551
    private void loopCodecFields(ICodecRunnable runnable) {
552
        for (Field field : fieldCache.get(null)) {
1 ✔
553
            Class<?> clazz = field.getType();
1 ✔
554
            ICodecAction action = getAction(clazz);
1 ✔
555

556
            // Make private fields temporarily accessible.
557
            boolean accessible = field.isAccessible();
1 ✔
558
            if (!accessible) {
1 ✔
559
                field.setAccessible(true);
1 ✔
560
            }
561
            runnable.run(field, action);
1 ✔
562
        }
1 ✔
563
    }
1 ✔
564

565
    @Override
566
    public void encode(final FriendlyByteBuf output) {
567
        loopCodecFields((field, action) -> {
1 ✔
568
            Object object = null;
1 ✔
569
            try {
570
                object = field.get(PacketCodec.this);
1 ✔
571
            } catch (IllegalArgumentException | IllegalAccessException e) {
×
UNCOV
572
                e.printStackTrace();
×
573
            }
1 ✔
574
            action.encode(object, output);
1 ✔
575
        });
1 ✔
576
    }
1 ✔
577

578
    @Override
579
    public void decode(final FriendlyByteBuf input) {
580
        loopCodecFields((field, action) -> {
1 ✔
581
            Object object = action.decode(input);
1 ✔
582
            try {
583
                field.set(PacketCodec.this, object);
1 ✔
584
            } catch (IllegalArgumentException | IllegalAccessException e) {
×
UNCOV
585
                e.printStackTrace();
×
586
            }
1 ✔
587
        });
1 ✔
588
    }
1 ✔
589

590
    /**
591
     * Write the given object into the packet buffer.
592
     * @param packetBuffer A packet buffer.
593
     * @param object An object.
594
     */
595
    public static void write(FriendlyByteBuf packetBuffer, Object object) {
596
        ICodecAction action = Objects.requireNonNull(getActionSuper(object.getClass()),
×
597
                "No codec action was registered for " + object.getClass().getName());
×
598
        action.encode(object, packetBuffer);
×
UNCOV
599
    }
×
600

601
    /**
602
     * Read the an object of the given type from the packet buffer.
603
     * @param packetBuffer A packet buffer.
604
     * @param clazz The class type to read.
605
     * @param <T> The type of object.
606
     * @return The read object.
607
     */
608
    public static <T> T read(FriendlyByteBuf packetBuffer, Class<T> clazz) {
609
        ICodecAction action = Objects.requireNonNull(getActionSuper(clazz));
×
UNCOV
610
        return (T) action.decode(packetBuffer);
×
611
    }
612

613
    public static interface ICodecAction {
614

615
        /**
616
         * Encode the given object.
617
         * @param object The object to encode into the output.
618
         * @param output The byte array to encode to.
619
         */
620
        public void encode(Object object, FriendlyByteBuf output);
621

622
        /**
623
         * Decode from the input.
624
         * @param input The byte array to decode from.
625
         * @return The object to return after reading it from the input.
626
         */
627
        public Object decode(FriendlyByteBuf input);
628

629
    }
630

631
    public static interface ICodecRunnable {
632

633
        /**
634
         * Run a type of codec.
635
         * @param field The field annotated with {@link CodecField}.
636
         * @param action The action that must be applied to the field.
637
         */
638
        public void run(Field field, ICodecAction action);
639

640
    }
641

642
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc