19
19
import java .io .IOException ;
20
20
import java .io .ObjectInput ;
21
21
import java .io .ObjectOutput ;
22
+ import java .util .Map .Entry ;
22
23
import java .util .NavigableMap ;
23
24
import java .util .Objects ;
24
25
import java .util .TreeMap ;
25
26
26
- import saker .build .thirdparty .saker .util .io . SerialUtils ;
27
+ import saker .build .thirdparty .saker .util .ImmutableUtils ;
27
28
28
29
public abstract class AbiUsageImpl implements Externalizable , AbiUsage {
29
30
private static final long serialVersionUID = 1L ;
@@ -266,36 +267,96 @@ public boolean isInheritesFromClass(String canonicalname) {
266
267
267
268
@ Override
268
269
public void writeExternal (ObjectOutput out ) throws IOException {
269
- SerialUtils .writeExternalMap (out , referenceInfos , ObjectOutput ::writeUTF , (o , info ) -> info .writeExternal (o ));
270
+ if (referenceInfos == null ) {
271
+ out .writeInt (-1 );
272
+ return ;
273
+ }
274
+ int size = referenceInfos .size ();
275
+ out .writeInt (size );
276
+ byte [] flags = new byte [size ];
277
+ int i = 0 ;
278
+ for (Entry <String , ReferenceInfo > entry : referenceInfos .entrySet ()) {
279
+ out .writeUTF (entry .getKey ());
280
+ flags [i ++] = entry .getValue ().getSerializationFlags ();
281
+ }
282
+
283
+ out .write (flags );
284
+ i = 0 ;
285
+ for (ReferenceInfo ri : referenceInfos .values ()) {
286
+ ri .writeForFlags (flags [i ++], out );
287
+ }
270
288
}
271
289
272
290
@ Override
273
291
public void readExternal (ObjectInput in ) throws IOException , ClassNotFoundException {
274
- referenceInfos = SerialUtils .readExternalSortedImmutableNavigableMap (in , ObjectInput ::readUTF , i -> {
292
+ int size = in .readInt ();
293
+ if (size < 0 ) {
294
+ //nothing to read
295
+ return ;
296
+ }
297
+ byte [] flags = new byte [size ];
298
+ String [] names = new String [size ];
299
+ ReferenceInfo [] infos = new ReferenceInfo [size ];
300
+
301
+ for (int i = 0 ; i < names .length ; i ++) {
302
+ names [i ] = in .readUTF ();
303
+ }
304
+
305
+ in .readFully (flags );
306
+
307
+ for (int i = 0 ; i < infos .length ; i ++) {
275
308
ReferenceInfo ri = new ReferenceInfo ();
276
- ri .readExternal (i );
277
- presentSimpleFlags |= ri .flags ;
278
- return ri ;
279
- });
309
+ ri .readForFlags (flags [i ], in );
310
+ infos [i ] = ri ;
311
+
312
+ this .presentSimpleFlags |= ri .flags ;
313
+ }
314
+
315
+ this .referenceInfos = ImmutableUtils .unmodifiableNavigableMap (names , infos );
280
316
}
281
317
282
318
protected static void writeStringByteMap (ObjectOutput out , NavigableMap <String , Byte > map ) throws IOException {
283
- SerialUtils .writeExternalMap (out , map , ObjectOutput ::writeUTF , (ObjectOutput o , Byte b ) -> o .writeByte (b ));
319
+ //this serialization probably saves us some bytes in the output as we don't write the byte flags individually
320
+ if (map == null ) {
321
+ out .writeInt (-1 );
322
+ return ;
323
+ }
324
+ int size = map .size ();
325
+ out .writeInt (size );
326
+ int i = 0 ;
327
+ byte [] bytes = new byte [size ];
328
+ for (Entry <String , Byte > entry : map .entrySet ()) {
329
+ out .writeUTF (entry .getKey ());
330
+ bytes [i ++] = entry .getValue ();
331
+ }
332
+ out .write (bytes );
284
333
}
285
334
286
- protected static NavigableMap <String , Byte > readStringByteMap (ObjectInput in )
287
- throws ClassNotFoundException , IOException {
288
- return SerialUtils .readExternalSortedImmutableNavigableMap (in , ObjectInput ::readUTF , i -> i .readByte ());
335
+ protected static NavigableMap <String , Byte > readStringByteMap (ObjectInput in ) throws IOException {
336
+ int size = in .readInt ();
337
+ if (size < 0 ) {
338
+ return null ;
339
+ }
340
+ String [] keys = new String [size ];
341
+ byte [] valbytes = new byte [size ];
342
+ for (int i = 0 ; i < keys .length ; i ++) {
343
+ keys [i ] = in .readUTF ();
344
+ }
345
+ in .readFully (valbytes );
346
+ Byte [] vals = new Byte [size ];
347
+ for (int i = 0 ; i < valbytes .length ; i ++) {
348
+ vals [i ] = valbytes [i ];
349
+ }
350
+
351
+ return ImmutableUtils .unmodifiableNavigableMap (keys , vals );
289
352
}
290
353
291
354
@ Override
292
355
public String toString () {
293
356
return getClass ().getSimpleName () + "[" + referenceInfos + "]" ;
294
357
}
295
358
296
- private static final class ReferenceInfo implements Externalizable {
297
- private static final long serialVersionUID = 1L ;
298
-
359
+ private static final class ReferenceInfo {
299
360
protected byte flags ;
300
361
protected NavigableMap <String , Byte > memberFlags ;
301
362
@@ -324,7 +385,29 @@ public NavigableMap<String, Byte> getMemberFlagsCreate() {
324
385
return map ;
325
386
}
326
387
327
- @ Override
388
+ protected byte getSerializationFlags () {
389
+ if (memberFlags == null ) {
390
+ return flags ;
391
+ }
392
+ return (byte ) (flags | FLAGS_RESERVED );
393
+ }
394
+
395
+ protected void writeForFlags (byte flags , ObjectOutput out ) throws IOException {
396
+ if ((flags & FLAGS_RESERVED ) != 0 ) {
397
+ writeStringByteMap (out , memberFlags );
398
+ }
399
+ }
400
+
401
+ protected void readForFlags (byte flags , ObjectInput in ) throws IOException {
402
+ if ((flags & FLAGS_RESERVED ) != 0 ) {
403
+ this .flags = (byte ) (flags & ~FLAGS_RESERVED );
404
+ memberFlags = readStringByteMap (in );
405
+ } else {
406
+ this .flags = flags ;
407
+ }
408
+
409
+ }
410
+
328
411
public void writeExternal (ObjectOutput out ) throws IOException {
329
412
if (memberFlags == null ) {
330
413
//use the reserved flag to convey the presence of the member map, this lets us write a few bytes less to the output
@@ -335,7 +418,6 @@ public void writeExternal(ObjectOutput out) throws IOException {
335
418
}
336
419
}
337
420
338
- @ Override
339
421
public void readExternal (ObjectInput in ) throws IOException , ClassNotFoundException {
340
422
flags = in .readByte ();
341
423
if ((flags & FLAGS_RESERVED ) != 0 ) {
0 commit comments