case ID_NULL: {
return null;
}
case ID_REPEAT_OBJECT_FAR: {
if (unshared) {
throw new InvalidObjectException("Attempt to read a backreference as unshared");
}
final int index = readInt();
try {
final Object obj = instanceCache.get(index);
if (obj != null) return obj;
} catch (IndexOutOfBoundsException e) {
}
throw new InvalidObjectException("Attempt to read a backreference with an invalid ID (absolute " + index + ")");
}
case ID_REPEAT_OBJECT_NEAR: {
if (unshared) {
throw new InvalidObjectException("Attempt to read a backreference as unshared");
}
final int index = readByte() | 0xffffff00;
try {
final Object obj = instanceCache.get(index + instanceCache.size());
if (obj != null) return obj;
} catch (IndexOutOfBoundsException e) {
}
throw new InvalidObjectException("Attempt to read a backreference with an invalid ID (relative near " + index + ")");
}
case ID_REPEAT_OBJECT_NEARISH: {
if (unshared) {
throw new InvalidObjectException("Attempt to read a backreference as unshared");
}
final int index = readShort() | 0xffff0000;
try {
final Object obj = instanceCache.get(index + instanceCache.size());
if (obj != null) return obj;
} catch (IndexOutOfBoundsException e) {
}
throw new InvalidObjectException("Attempt to read a backreference with an invalid ID (relative nearish " + index + ")");
}
case ID_NEW_OBJECT:
case ID_NEW_OBJECT_UNSHARED: {
if (unshared != (leadByte == ID_NEW_OBJECT_UNSHARED)) {
throw sharedMismatch();
}
return replace(doReadNewObject(readUnsignedByte(), unshared));
}
// v2 string types
case ID_STRING_EMPTY: {
return "";
}
case ID_STRING_SMALL: {
// ignore unshared setting
int length = readUnsignedByte();
final String s = UTFUtils.readUTFBytes(this, length == 0 ? 0x100 : length);
instanceCache.add(s);
return s;
}
case ID_STRING_MEDIUM: {
// ignore unshared setting
int length = readUnsignedShort();
final String s = UTFUtils.readUTFBytes(this, length == 0 ? 0x10000 : length);
instanceCache.add(s);
return s;
}
case ID_STRING_LARGE: {
// ignore unshared setting
int length = readInt();
if (length <= 0) {
throw new StreamCorruptedException("Invalid length value for string in stream (" + length + ")");
}
final String s = UTFUtils.readUTFBytes(this, length);
instanceCache.add(s);
return s;
}
case ID_ARRAY_EMPTY:
case ID_ARRAY_EMPTY_UNSHARED: {
if (unshared != (leadByte == ID_ARRAY_EMPTY_UNSHARED)) {
throw sharedMismatch();
}
final ArrayList<Object> instanceCache = this.instanceCache;
final int idx = instanceCache.size();
instanceCache.add(null);
final Object obj = Array.newInstance(doReadClassDescriptor(readUnsignedByte()).getType(), 0);
instanceCache.set(idx, obj);
final Object resolvedObject = objectResolver.readResolve(obj);
if (unshared) {
instanceCache.set(idx, null);
} else if (obj != resolvedObject) {
instanceCache.set(idx, resolvedObject);
}
return replace(obj);
}
case ID_ARRAY_SMALL:
case ID_ARRAY_SMALL_UNSHARED: {
if (unshared != (leadByte == ID_ARRAY_SMALL_UNSHARED)) {
throw sharedMismatch();
}
final int len = readUnsignedByte();
return replace(doReadArray(len == 0 ? 0x100 : len, unshared));
}
case ID_ARRAY_MEDIUM:
case ID_ARRAY_MEDIUM_UNSHARED: {
if (unshared != (leadByte == ID_ARRAY_MEDIUM_UNSHARED)) {
throw sharedMismatch();
}
final int len = readUnsignedShort();
return replace(doReadArray(len == 0 ? 0x10000 : len, unshared));
}
case ID_ARRAY_LARGE:
case ID_ARRAY_LARGE_UNSHARED: {
if (unshared != (leadByte == ID_ARRAY_LARGE_UNSHARED)) {
throw sharedMismatch();
}
final int len = readInt();
if (len <= 0) {
throw new StreamCorruptedException("Invalid length value for array in stream (" + len + ")");
}
return replace(doReadArray(len, unshared));
}
case ID_PREDEFINED_OBJECT: {
if (unshared) {
throw new InvalidObjectException("Attempt to read a predefined object as unshared");
}
return objectTable.readObject(this);
}
case ID_BOOLEAN_OBJECT_TRUE: {
return replace(objectResolver.readResolve(Boolean.TRUE));