Adjusted API of UnsafeNarrowing to be more useful

UnsafeNarrowing is now loosely coupled with InvalidFormat via UnsafeNarrowing#wrapAndThrow
UnsafeNarrowing can now be passed an optional offset value
This commit is contained in:
Collin Smith
2020-10-03 00:56:58 -07:00
parent 08bc23160f
commit 58d31d0634
5 changed files with 47 additions and 31 deletions

View File

@ -60,65 +60,65 @@ public class BitConstraints {
return _validateSize(Byte.SIZE - 1, Byte.SIZE, bits); return _validateSize(Byte.SIZE - 1, Byte.SIZE, bits);
} }
public static byte safe8u(ByteInput byteInput, short i) { public static byte safe8u(short i) {
if (!BitUtils.isUnsigned(i, Byte.SIZE)) { if (!BitUtils.isUnsigned(i, Byte.SIZE)) {
throw new UnsafeNarrowing(byteInput, i); throw new UnsafeNarrowing(i);
} }
return (byte) i; return (byte) i;
} }
public static short safe16u(ByteInput byteInput, int i) { public static short safe16u(int i) {
if (!BitUtils.isUnsigned(i, Short.SIZE)) { if (!BitUtils.isUnsigned(i, Short.SIZE)) {
throw new UnsafeNarrowing(byteInput, i); throw new UnsafeNarrowing(i);
} }
return (short) i; return (short) i;
} }
public static int safe32u(ByteInput byteInput, long i) { public static int safe32u(long i) {
if (!BitUtils.isUnsigned(i, Integer.SIZE)) { if (!BitUtils.isUnsigned(i, Integer.SIZE)) {
throw new UnsafeNarrowing(byteInput, i); throw new UnsafeNarrowing(i);
} }
return (int) i; return (int) i;
} }
public static long safe64u(ByteInput byteInput, long i) { public static long safe64u(long i) {
if (!BitUtils.isUnsigned(i, Long.SIZE)) { if (!BitUtils.isUnsigned(i, Long.SIZE)) {
throw new UnsafeNarrowing(byteInput, i); throw new UnsafeNarrowing(i);
} }
return (long) i; return (long) i;
} }
public static byte safe8u(BitInput bitInput, short i) { public static byte safe8u(long offset, short i) {
if (!BitUtils.isUnsigned(i, Byte.SIZE)) { if (!BitUtils.isUnsigned(i, Byte.SIZE)) {
throw new UnsafeNarrowing(bitInput.byteInput(), i); throw new UnsafeNarrowing(offset, i);
} }
return (byte) i; return (byte) i;
} }
public static short safe16u(BitInput bitInput, int i) { public static short safe16u(long offset, int i) {
if (!BitUtils.isUnsigned(i, Short.SIZE)) { if (!BitUtils.isUnsigned(i, Short.SIZE)) {
throw new UnsafeNarrowing(bitInput.byteInput(), i); throw new UnsafeNarrowing(offset, i);
} }
return (short) i; return (short) i;
} }
public static int safe32u(BitInput bitInput, long i) { public static int safe32u(long offset, long i) {
if (!BitUtils.isUnsigned(i, Integer.SIZE)) { if (!BitUtils.isUnsigned(i, Integer.SIZE)) {
throw new UnsafeNarrowing(bitInput.byteInput(), i); throw new UnsafeNarrowing(offset, i);
} }
return (int) i; return (int) i;
} }
public static long safe64u(BitInput bitInput, long i) { public static long safe64u(long offset, long i) {
if (!BitUtils.isUnsigned(i, Long.SIZE)) { if (!BitUtils.isUnsigned(i, Long.SIZE)) {
throw new UnsafeNarrowing(bitInput.byteInput(), i); throw new UnsafeNarrowing(offset, i);
} }
return (long) i; return (long) i;

View File

@ -68,6 +68,10 @@ public class BitInput {
return byteInput.numBytes(); return byteInput.numBytes();
} }
public int byteMark() {
return byteInput.mark();
}
public int bitsCached() { public int bitsCached() {
return bitsCached; return bitsCached;
} }
@ -459,7 +463,7 @@ public class BitInput {
public byte readSafe8u() { public byte readSafe8u() {
try { try {
final short value = read8u(); final short value = read8u();
return BitConstraints.safe8u(byteInput, value); return BitConstraints.safe8u(byteMark(), value);
} catch (IndexOutOfBoundsException t) { } catch (IndexOutOfBoundsException t) {
throw new EndOfInput(t); throw new EndOfInput(t);
} }
@ -475,7 +479,7 @@ public class BitInput {
public short readSafe16u() { public short readSafe16u() {
try { try {
final int value = read16u(); final int value = read16u();
return BitConstraints.safe16u(byteInput, value); return BitConstraints.safe16u(byteMark(), value);
} catch (IndexOutOfBoundsException t) { } catch (IndexOutOfBoundsException t) {
throw new EndOfInput(t); throw new EndOfInput(t);
} }
@ -491,7 +495,7 @@ public class BitInput {
public int readSafe32u() { public int readSafe32u() {
try { try {
final long value = read32u(); final long value = read32u();
return BitConstraints.safe32u(byteInput, value); return BitConstraints.safe32u(byteMark(), value);
} catch (IndexOutOfBoundsException t) { } catch (IndexOutOfBoundsException t) {
throw new EndOfInput(t); throw new EndOfInput(t);
} }
@ -507,7 +511,7 @@ public class BitInput {
public long readSafe64u() { public long readSafe64u() {
try { try {
final long value = read64(); final long value = read64();
return BitConstraints.safe64u(byteInput, value); return BitConstraints.safe64u(byteMark(), value);
} catch (IndexOutOfBoundsException t) { } catch (IndexOutOfBoundsException t) {
throw new EndOfInput(t); throw new EndOfInput(t);
} }

View File

@ -401,7 +401,7 @@ public class ByteInput {
assert aligned() : "not aligned"; assert aligned() : "not aligned";
try { try {
final short value = read8u(); // increments bits final short value = read8u(); // increments bits
return BitConstraints.safe8u(this, value); return BitConstraints.safe8u(mark, value);
} catch (IndexOutOfBoundsException t) { } catch (IndexOutOfBoundsException t) {
throw new EndOfInput(t); throw new EndOfInput(t);
} }
@ -418,7 +418,7 @@ public class ByteInput {
assert aligned() : "not aligned"; assert aligned() : "not aligned";
try { try {
final int value = read16u(); // increments bits final int value = read16u(); // increments bits
return BitConstraints.safe16u(this, value); return BitConstraints.safe16u(mark, value);
} catch (IndexOutOfBoundsException t) { } catch (IndexOutOfBoundsException t) {
throw new EndOfInput(t); throw new EndOfInput(t);
} }
@ -435,7 +435,7 @@ public class ByteInput {
assert aligned() : "not aligned"; assert aligned() : "not aligned";
try { try {
final long value = read32u(); // increments bits final long value = read32u(); // increments bits
return BitConstraints.safe32u(this, value); return BitConstraints.safe32u(mark, value);
} catch (IndexOutOfBoundsException t) { } catch (IndexOutOfBoundsException t) {
throw new EndOfInput(t); throw new EndOfInput(t);
} }
@ -452,7 +452,7 @@ public class ByteInput {
assert aligned() : "not aligned"; assert aligned() : "not aligned";
try { try {
final long value = read64(); // increments bits final long value = read64(); // increments bits
return BitConstraints.safe64u(this, value); return BitConstraints.safe64u(mark, value);
} catch (IndexOutOfBoundsException t) { } catch (IndexOutOfBoundsException t) {
throw new EndOfInput(t); throw new EndOfInput(t);
} }

View File

@ -12,8 +12,12 @@ public class InvalidFormat extends RuntimeException {
} }
public InvalidFormat(ByteInput in, String message, Throwable cause) { public InvalidFormat(ByteInput in, String message, Throwable cause) {
super(message + " +0x" + Integer.toHexString(in.mark()), cause); this(in.mark(), message, cause);
this.offset = in.mark(); }
InvalidFormat(long offset, String message, Throwable cause) {
super(message + " +0x" + Long.toHexString(offset), cause);
this.offset = offset;
} }
@Deprecated @Deprecated

View File

@ -1,17 +1,25 @@
package com.riiablo.io; package com.riiablo.io;
public class UnsafeNarrowing extends RuntimeException { public class UnsafeNarrowing extends RuntimeException {
public final ByteInput byteInput; public final long offset;
public final long value; public final long value;
UnsafeNarrowing(ByteInput byteInput, long value) { UnsafeNarrowing(long value) {
this(-1, value);
}
UnsafeNarrowing(long offset, long value) {
super("value(" + value + ") cannot be safely narrowed!"); super("value(" + value + ") cannot be safely narrowed!");
this.byteInput = byteInput; this.offset = offset;
this.value = value; this.value = value;
} }
public ByteInput byteInput() { public <R> R wrapAndThrow() {
return byteInput; if (offset < 0) {
throw this;
} else {
throw new InvalidFormat(offset, "Unsafe narrowing", this);
}
} }
public short u8() { public short u8() {