diff --git a/src/main/java/io/kaitai/struct/WriteOnlyByteListKaitaiStream.java b/src/main/java/io/kaitai/struct/WriteOnlyByteListKaitaiStream.java
new file mode 100644
index 0000000..ac0520a
--- /dev/null
+++ b/src/main/java/io/kaitai/struct/WriteOnlyByteListKaitaiStream.java
@@ -0,0 +1,385 @@
+/**
+ * Copyright 2015-2023 Kaitai Project: MIT license
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+package io.kaitai.struct;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Implementation of {@link KaitaiStream} for serialization only.
+ */
+public class WriteOnlyByteListKaitaiStream extends KaitaiStream {
+
+ private static final byte DEFAULT_BYTE_VALUE = (byte) 0;
+ private final List LIST;
+ int position = 0;
+
+ public WriteOnlyByteListKaitaiStream(List list) {
+ LIST = list;
+ }
+
+ public WriteOnlyByteListKaitaiStream() {
+ LIST = new ArrayList<>();
+ }
+
+ public List getList() {
+ return LIST;
+ }
+
+ private void setOrAdd(byte value) {
+ /*
+ Example:
+ Let LIST.size be 4, so the list indexes are 0, 1, 2, 3.
+ - If position is 3, we want to set the value at index 3,
+ so call LIST.set(position, value).
+ - If position is 4, we need to add an item to the list.
+ Call LIST .add(value) to add the item. The newly added
+ item will have index 4.
+ - If position is 5, we need to:
+ - First call LIST.add(0) once to fill index 4 with the
+ default byte value.
+ - Then call LIST.add(value) to add the item. The newly
+ added item will have index 5.
+ */
+ if (position < LIST.size()) {
+ LIST.set(position, value);
+ } else {
+ while (position > LIST.size()) {
+ LIST.add(DEFAULT_BYTE_VALUE);
+ }
+ LIST.add(value);
+ }
+ position++;
+ }
+
+ @Override
+ public void close() throws IOException {
+ try {
+ if (bitsWriteMode) {
+ writeAlignToByte();
+ }
+ } catch (Exception e) {
+ throw e;
+ } finally {
+ alignToByte();
+ }
+ }
+
+ //region Stream positioning
+ @Override
+ public boolean isEof() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void seek(int newPos) {
+ if (bitsWriteMode) {
+ writeAlignToByte();
+ } else {
+ alignToByte();
+ }
+ position = newPos;
+ }
+
+ @Override
+ public void seek(long newPos) {
+ if (newPos > Integer.MAX_VALUE) {
+ throw new IllegalArgumentException("Java List can't be seeked past Integer.MAX_VALUE");
+ }
+ seek((int) newPos);
+ }
+
+ @Override
+ public int pos() {
+ return position + ((bitsWriteMode && bitsLeft > 0) ? 1 : 0);
+ }
+
+ @Override
+ public long size() {
+ throw new UnsupportedOperationException();
+ }
+
+ //endregion
+ //region Reading
+ //region Integer numbers
+ //region Signed
+ @Override
+ public byte readS1() {
+ throw new UnsupportedOperationException();
+ }
+
+ //region Big-endian
+ @Override
+ public short readS2be() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int readS4be() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long readS8be() {
+ throw new UnsupportedOperationException();
+ }
+
+ //endregion
+ //region Little-endian
+ @Override
+ public short readS2le() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int readS4le() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long readS8le() {
+ throw new UnsupportedOperationException();
+ }
+
+ //endregion
+ //endregion
+ //region Unsigned
+ @Override
+ public int readU1() {
+ throw new UnsupportedOperationException();
+ }
+
+ //region Big-endian
+ @Override
+ public int readU2be() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long readU4be() {
+ throw new UnsupportedOperationException();
+ }
+
+ //endregion
+ //region Little-endian
+ @Override
+ public int readU2le() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long readU4le() {
+ throw new UnsupportedOperationException();
+ }
+
+ //endregion
+ //endregion
+ //endregion
+ //region Floating point numbers
+ //region Big-endian
+ @Override
+ public float readF4be() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public double readF8be() {
+ throw new UnsupportedOperationException();
+ }
+
+ //endregion
+ //region Little-endian
+ @Override
+ public float readF4le() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public double readF8le() {
+ throw new UnsupportedOperationException();
+ }
+
+ //endregion
+ //endregion
+ //region Byte arrays
+ @Override
+ protected byte[] readBytesNotAligned(long n) {
+ throw new UnsupportedOperationException();
+
+ }
+
+ @Override
+ public byte[] readBytesFull() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public byte[] readBytesTerm(byte term, boolean includeTerm, boolean consumeTerm, boolean eosError) {
+ throw new UnsupportedOperationException();
+ }
+
+ //endregion
+ //endregion
+ //region Writing
+ //region Integer numbers
+ //region Signed
+
+ /**
+ * Writes one signed 1-byte integer.
+ */
+ @Override
+ public void writeS1(byte v) {
+ writeAlignToByte();
+ setOrAdd(v);
+ }
+
+ /*
+ Example from Wikipedia:
+ The value to write is 0A0B0C0D.
+
+ Big endian:
+ index 0 1 2 3
+ contents [0A, 0B, 0C, 0D]
+ */
+ //region Big-endian
+ @Override
+ public void writeS2be(short v) {
+ writeAlignToByte();
+ setOrAdd((byte) (v >> 8));
+ setOrAdd((byte) v);
+ }
+
+ @Override
+ public void writeS4be(int v) {
+ writeAlignToByte();
+ setOrAdd((byte) (v >> (8 * 3)));
+ setOrAdd((byte) (v >> (8 * 2)));
+ setOrAdd((byte) (v >> (8 * 1)));
+ setOrAdd((byte) v);
+ }
+
+ @Override
+ public void writeS8be(long v) {
+ writeAlignToByte();
+ setOrAdd((byte) (v >> (8 * 7)));
+ setOrAdd((byte) (v >> (8 * 6)));
+ setOrAdd((byte) (v >> (8 * 5)));
+ setOrAdd((byte) (v >> (8 * 4)));
+ setOrAdd((byte) (v >> (8 * 3)));
+ setOrAdd((byte) (v >> (8 * 2)));
+ setOrAdd((byte) (v >> (8 * 1)));
+ setOrAdd((byte) v);
+ }
+
+ //endregion
+ //region Little-endian
+
+ /*
+ Example from wikipedia:
+ The value to write is 0A0B0C0D.
+
+ Little endian:
+ index 0 1 2 3
+ contents [0D, 0C, 0B, 0A]
+ */
+ @Override
+ public void writeS2le(short v) {
+ writeAlignToByte();
+ setOrAdd((byte) v);
+ setOrAdd((byte) (v >> 8));
+ }
+
+ @Override
+ public void writeS4le(int v) {
+ writeAlignToByte();
+ setOrAdd((byte) v);
+ setOrAdd((byte) (v >> (8 * 1)));
+ setOrAdd((byte) (v >> (8 * 2)));
+ setOrAdd((byte) (v >> (8 * 3)));
+ }
+
+ @Override
+ public void writeS8le(long v) {
+ writeAlignToByte();
+ setOrAdd((byte) v);
+ setOrAdd((byte) (v >> (8 * 1)));
+ setOrAdd((byte) (v >> (8 * 2)));
+ setOrAdd((byte) (v >> (8 * 3)));
+ setOrAdd((byte) (v >> (8 * 4)));
+ setOrAdd((byte) (v >> (8 * 5)));
+ setOrAdd((byte) (v >> (8 * 6)));
+ setOrAdd((byte) (v >> (8 * 7)));
+ }
+
+ //endregion
+ //endregion
+ //endregion
+ //region Floating point numbers
+ //region Big-endian
+ @Override
+ public void writeF4be(float v) {
+ writeAlignToByte();
+ writeS4be(Float.floatToIntBits(v));
+ }
+
+ @Override
+ public void writeF8be(double v) {
+ writeAlignToByte();
+ writeS8be(Double.doubleToLongBits(v));
+ }
+
+ //endregion
+ //region Little-endian
+ @Override
+ public void writeF4le(float v) {
+ writeAlignToByte();
+ writeS4le(Float.floatToIntBits(v));
+ }
+
+ @Override
+ public void writeF8le(double v) {
+ writeAlignToByte();
+ writeS8le(Double.doubleToLongBits(v));
+ }
+
+ //endregion
+ //endregion
+ //region Byte arrays
+ @Override
+ protected void writeBytesNotAligned(byte[] buf) {
+ /*
+ In ByteBufferKaitaiStream, this method calls bytebuffer.put().
+ Javadoc for the ByteBuffer.put(byte[]) method says:
+ "This method transfers the entire content of the given source byte array into this buffer.
+ An invocation of this method of the form dst.put(a) behaves in exactly the same way as the
+ invocation dst.put(a, 0, a.length)."
+ */
+ for (byte b : buf) {
+ setOrAdd(b);
+ }
+ }
+
+ //endregion
+ //endregion
+}