// We use big-endian as DataOutputStream does sclass ByteHead /*is DataOutput*/ { settable bool readMode; settable bool writeMode; settable InputStream inputStream; settable OutputStream outputStream; *() {} *(InputStream *inputStream) { readMode(true); } *(OutputStream *outputStream) { writeMode(true); } void writeLong(long l) { writeInt((int) (l >> 32)); writeInt((int) l); } void writeInt(int i) { write(i >> 24); write(i >> 16); write(i >> 8); write(i); } void writeShort(int i) { write(i >> 8); write(i); } void writeByte aka write(int i) ctex { ensureWriteMode(); outputStream?.write(i); } long readLong() { long i = readInt() << 32; ret i | (readInt() & 0xFFFFFFFFL); } int readInt() { int i = read() << 24; i |= read() << 16; i |= read() << 8; ret (short) (i | read()); } short readShort() { int i = read() << 8; ret (short) (i | read()); } // -1 for EOF int readByte aka read() ctex { ensureReadMode(); ret inputStream.read(); } void ensureReadMode { if (!readMode) fail("Not in read mode"); } void ensureWriteMode { if (!writeMode) fail("Not in write mode"); } // exchange = read or write depending on mode void exchangeShort(IF0 getter, IVF1 setter) { if (writeMode()) writeShort(getter!); if (readMode()) setter.get(readShort()); } void exchangeLong(IVar var) { exchangeLong(var.getter(), var.setter()); } void exchangeLong(IF0 getter, IVF1 setter) { if (writeMode()) writeLong(getter!); if (readMode()) setter.get(readLong()); } void exchangeInt(int i) { exchangeInt(-> i, j -> assertEquals(i, j)); } void exchangeInt(IF0 getter, IVF1 setter) { if (writeMode()) writeInt(getter!); if (readMode()) setter.get(readInt()); } void exchange(ByteIO writable) { if (writable != null) writable.readWrite(this); } void exchangeAll(Iterable writables) { if (writables != null) for (writable : writables) exchange(writable); } }