// SPDX-FileCopyrightText: © 2021 Matthias Andreas Benkard <code@mail.matthias.benkard.de>
//
// SPDX-License-Identifier: LGPL-3.0-or-later

package eu.mulk.jgvariant.core;

import com.google.errorprone.annotations.Immutable;
import org.apiguardian.api.API;
import org.apiguardian.api.API.Status;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.RecordComponent;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.Channels;
import java.nio.charset.Charset;
import java.text.ParseException;
import java.util.*;
import java.util.Map.Entry;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;

import static java.lang.Math.max;
import static java.nio.ByteOrder.BIG_ENDIAN;
import static java.nio.ByteOrder.LITTLE_ENDIAN;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Objects.requireNonNullElse;

/**
 * Type class for decodable types.
 *
 * <p>Use the {@code of*} family of constructor methods to acquire a suitable {@link Decoder} for
 * the type you wish to decode.
 *
 * <p><strong>Example</strong>
 *
 * <p>To parse a GVariant of type {@code "a(si)"}, which is an array of pairs of {@link String} and
 * {@code int}, you can use the following code:
 *
 * {@snippet lang="java" :
 * record ExampleRecord(String s, int i) {}
 *
 * var decoder =
 *   Decoder.ofArray(
 *     Decoder.ofStructure(
 *       ExampleRecord.class,
 *       Decoder.ofString(UTF_8),
 *       Decoder.ofInt().withByteOrder(LITTLE_ENDIAN)));
 *
 * byte[] bytes;
 * List<ExampleRecord> example = decoder.decode(ByteBuffer.wrap(bytes));
 * }
 *
 * @param <T> the type that the {@link Decoder} can decode.
 */
@API(status = Status.EXPERIMENTAL)
@Immutable
@SuppressWarnings({"ImmutableListOf", "InvalidInlineTag", "java:S1610", "UnescapedEntity"})
public abstract class Decoder<T> {

  private Decoder() {}

  /**
   * Decodes a {@link ByteBuffer} holding a serialized GVariant into a value of type {@code T}.
   *
   * <p><strong>Note:</strong> Due to the way the GVariant serialization format works, it is
   * important that the start and end boundaries of the passed byte slice correspond to the actual
   * start and end of the serialized value. The format does generally not allow for the dynamic
   * discovery of the end of the data structure.
   *
   * @param byteSlice a byte slice holding a serialized GVariant.
   * @return the deserialized value.
   * @throws java.nio.BufferUnderflowException if the byte buffer is shorter than the requested
   *     data.
   * @throws IllegalArgumentException if the serialized GVariant is ill-formed
   */
  public abstract @NotNull T decode(ByteBuffer byteSlice);

  /**
   * Encodes a value of type {@code T} into a {@link ByteBuffer} holding a serialized GVariant.
   *
   * @param value the value to serialize.
   * @return a {@link ByteBuffer} holding the serialized value.
   */
  public final ByteBuffer encode(T value) {
    var byteWriter = new ByteWriter();
    encode(value, byteWriter);
    return byteWriter.toByteBuffer();
  }

  abstract byte alignment();

  abstract @Nullable Integer fixedSize();

  abstract void encode(T value, ByteWriter byteWriter);

  final boolean hasFixedSize() {
    return fixedSize() != null;
  }

  /**
   * Switches the input {@link ByteBuffer} to a given {@link ByteOrder} before reading from it.
   *
   * @param byteOrder the byte order to use.
   * @return a new, decorated {@link Decoder}.
   */
  public final Decoder<T> withByteOrder(ByteOrder byteOrder) {
    return new ByteOrderFixingDecoder(byteOrder);
  }

  /**
   * Creates a new {@link Decoder} from an existing one by applying a function to the result.
   *
   * @param decodingFunction the function to apply when decoding.
   * @param encodingFunction the function to apply when encoding.
   * @return a new, decorated {@link Decoder}.
   * @see java.util.stream.Stream#map
   */
  public final <U> Decoder<U> map(Function<@NotNull T, @NotNull U> decodingFunction, Function<@NotNull U, @NotNull T> encodingFunction) {
    return new MappingDecoder<>(decodingFunction, encodingFunction);
  }

  /**
   * Creates a new {@link Decoder} from an existing one by applying a function to the input.
   *
   * @param decodingFunction the function to apply when decoding.
   * @param encodingFunction the function to apply when encoding.
   * @return a new, decorated {@link Decoder}.
   * @see java.util.stream.Stream#map
   */
  public final Decoder<T> contramap(UnaryOperator<ByteBuffer> decodingFunction, UnaryOperator<ByteBuffer> encodingFunction) {
    return new ContramappingDecoder(decodingFunction, encodingFunction);
  }

  /**
   * Creates a new {@link Decoder} that delegates to one of two other {@link Decoder}s based on a
   * condition on the input {@link ByteBuffer}.
   *
   * @param selector the predicate to use to determine the decoder to use.
   * @return a new {@link Decoder}.
   */
  public static <U> Decoder<U> ofPredicate(
      Predicate<ByteBuffer> selector, Decoder<U> thenDecoder, Decoder<U> elseDecoder) {
    return new PredicateDecoder<>(selector, thenDecoder, elseDecoder);
  }

  /**
   * Creates a {@link Decoder} for an {@code Array} type.
   *
   * @param elementDecoder a {@link Decoder} for the elements of the array.
   * @param <U> the element type.
   * @return a new {@link Decoder}.
   */
  public static <U> Decoder<List<U>> ofArray(Decoder<U> elementDecoder) {
    return new ArrayDecoder<>(elementDecoder);
  }

  /**
   * Creates a {@link Decoder} for a {@code Dictionary} type.
   *
   * @param keyDecoder a {@link Decoder} for the key component of the dictionary entry.
   * @param valueDecoder a {@link Decoder} for the value component of the dictionary entry.
   * @return a new {@link Decoder}.
   */
  public static <K, V> Decoder<Map<K, V>> ofDictionary(
      Decoder<K> keyDecoder, Decoder<V> valueDecoder) {
    return new DictionaryDecoder<>(keyDecoder, valueDecoder);
  }

  /**
   * Creates a {@link Decoder} for an {@code Array} type of element type {@code byte} into a
   * primitive {@code byte[]} array.
   *
   * @return a new {@link Decoder}.
   */
  public static Decoder<byte[]> ofByteArray() {
    return new ByteArrayDecoder();
  }

  /**
   * Creates a {@link Decoder} for a {@code Maybe} type.
   *
   * @param elementDecoder a {@link Decoder} for the contained element.
   * @param <U> the element type.
   * @return a new {@link Decoder}.
   */
  public static <U> Decoder<Optional<U>> ofMaybe(Decoder<U> elementDecoder) {
    return new MaybeDecoder<>(elementDecoder);
  }

  /**
   * Creates a {@link Decoder} for a {@code Structure} type, decoding into a {@link Record}.
   *
   * @param recordType the {@link Record} type that represents the components of the structure.
   * @param componentDecoders a {@link Decoder} for each component of the structure.
   * @param <U> the {@link Record} type that represents the components of the structure.
   * @return a new {@link Decoder}.
   */
  public static <U extends Record> Decoder<U> ofStructure(
      Class<U> recordType, Decoder<?>... componentDecoders) {
    return new StructureDecoder<>(recordType, componentDecoders);
  }

  /**
   * Creates a {@link Decoder} for a {@code Structure} type, decoding into a {@link List}.
   *
   * <p>Prefer {@link #ofStructure(Class, Decoder[])} if possible, which is both more type-safe and
   * more convenient.
   *
   * @param componentDecoders a {@link Decoder} for each component of the structure.
   * @return a new {@link Decoder}.
   */
  public static Decoder<Object[]> ofStructure(Decoder<?>... componentDecoders) {
    return new TupleDecoder(componentDecoders);
  }

  /**
   * Creates a {@link Decoder} for a {@code Dictionary Entry} type, decoding into a {@link
   * Map.Entry}.
   *
   * @param keyDecoder a {@link Decoder} for the key component of the dictionary entry.
   * @param valueDecoder a {@link Decoder} for the value component of the dictionary entry.
   * @return a new {@link Decoder}.
   */
  public static <K, V> Decoder<Map.Entry<K, V>> ofDictionaryEntry(
      Decoder<K> keyDecoder, Decoder<V> valueDecoder) {
    return new DictionaryEntryDecoder<>(keyDecoder, valueDecoder);
  }

  /**
   * Creates a {@link Decoder} for the {@link Variant} type.
   *
   * <p>The contained {@link Object} can be of one of the following types:
   *
   * <ul>
   *   <li>{@link Boolean}
   *   <li>{@link Byte}
   *   <li>{@link Short}
   *   <li>{@link Integer}
   *   <li>{@link Long}
   *   <li>{@link String}
   *   <li>{@link Optional} (a GVariant {@code Maybe} type)
   *   <li>{@link List} (a GVariant array)
   *   <li>{@code Object[]} (a GVariant structure)
   *   <li>{@link java.util.Map} (a dictionary)
   *   <li>{@link java.util.Map.Entry} (a dictionary entry)
   *   <li>{@link Variant} (a nested variant)
   * </ul>
   *
   * @return a new {@link Decoder}.
   */
  public static Decoder<Variant> ofVariant() {
    return new VariantDecoder();
  }

  /**
   * Creates a {@link Decoder} for the {@code boolean} type.
   *
   * @return a new {@link Decoder}.
   */
  public static Decoder<Boolean> ofBoolean() {
    return new BooleanDecoder();
  }

  /**
   * Creates a {@link Decoder} for the 8-bit {@code byte} type.
   *
   * <p><strong>Note:</strong> It is often useful to apply {@link #withByteOrder(ByteOrder)} to the
   * result of this method.
   *
   * @return a new {@link Decoder}.
   */
  public static Decoder<Byte> ofByte() {
    return new ByteDecoder();
  }

  /**
   * Creates a {@link Decoder} for the 16-bit {@code short} type.
   *
   * <p><strong>Note:</strong> It is often useful to apply {@link #withByteOrder(ByteOrder)} to the
   * result of this method.
   *
   * @return a new {@link Decoder}.
   */
  public static Decoder<Short> ofShort() {
    return new ShortDecoder();
  }

  /**
   * Creates a {@link Decoder} for the 32-bit {@code int} type.
   *
   * <p><strong>Note:</strong> It is often useful to apply {@link #withByteOrder(ByteOrder)} to the
   * result of this method.
   *
   * @return a new {@link Decoder}.
   */
  public static Decoder<Integer> ofInt() {
    return new IntegerDecoder();
  }

  /**
   * Creates a {@link Decoder} for the 64-bit {@code long} type.
   *
   * <p><strong>Note:</strong> It is often useful to apply {@link #withByteOrder(ByteOrder)} to the
   * result of this method.
   *
   * @return a new {@link Decoder}.
   */
  public static Decoder<Long> ofLong() {
    return new LongDecoder();
  }

  /**
   * Creates a {@link Decoder} for the {@code double} type.
   *
   * @return a new {@link Decoder}.
   */
  public static Decoder<Double> ofDouble() {
    return new DoubleDecoder();
  }

  /**
   * Creates a {@link Decoder} for the {@link String} type.
   *
   * <p><strong>Note:</strong> While GVariant does not prescribe any particular encoding, {@link
   * java.nio.charset.StandardCharsets#UTF_8} is the most common choice.
   *
   * @param charset the {@link Charset} the string is encoded in.
   * @return a new {@link Decoder}.
   */
  public static Decoder<String> ofString(Charset charset) {
    return new StringDecoder(charset);
  }

  private static int align(int offset, byte alignment) {
    return offset % alignment == 0 ? offset : offset + alignment - (offset % alignment);
  }

  private static int getIntN(ByteBuffer byteSlice) {
    return switch (byteSlice.limit()) {
      case 0 -> 0;
      case 1 ->
        Byte.toUnsignedInt(byteSlice.order(LITTLE_ENDIAN).get());
      case 2 ->
        Short.toUnsignedInt(byteSlice.order(LITTLE_ENDIAN).getShort());
      case 4 ->
        byteSlice.order(LITTLE_ENDIAN).getInt();
      default ->
        throw new IllegalArgumentException("invalid byte count: %d".formatted(byteSlice.limit()));
    };
  }

  @SuppressWarnings("java:S3358")
  private static int byteCount(int n) {
    return n == 0 ? 0 : n < (1 << 8) ? 1 : n < (1 << 16) ? 2 : 4;
  }

  private static int computeFramingOffsetSize(int elementsRelativeEnd, List<Integer> framingOffsets) {
    // Determining the framing offset size requires trial and error.
    int framingOffsetSize;
    for (framingOffsetSize = 0;; framingOffsetSize = max(1, framingOffsetSize << 1)) {
      if (elementsRelativeEnd + (long)framingOffsetSize * framingOffsets.size() >= 1L << (8*framingOffsetSize)) {
        continue;
      }

      if (framingOffsetSize > 4) {
        throw new IllegalArgumentException("too many framing offsets");
      }

      return framingOffsetSize;
    }
  }

  private static class ArrayDecoder<U> extends Decoder<List<U>> {

    private final Decoder<U> elementDecoder;

    ArrayDecoder(Decoder<U> elementDecoder) {
      this.elementDecoder = elementDecoder;
    }

    @Override
    public byte alignment() {
      return elementDecoder.alignment();
    }

    @Override
    @Nullable
    public Integer fixedSize() {
      return null;
    }

    @Override
    public @NotNull List<U> decode(ByteBuffer byteSlice) {
      List<U> elements;

      var elementSize = elementDecoder.fixedSize();
      if (elementSize != null) {
        // A simple C-style array.
        elements = new ArrayList<>(byteSlice.limit() / elementSize);
        for (int i = 0; i < byteSlice.limit(); i += elementSize) {
          var element = elementDecoder.decode(slicePreservingOrder(byteSlice, i, elementSize));
          elements.add(element);
        }
      } else if (byteSlice.limit() == 0) {
        // A degenerate zero-length array of variable width.
        elements = List.of();
      } else {
        // An array with aligned elements and a vector of framing offsets in the end.
        int framingOffsetSize = max(1, byteCount(byteSlice.limit()));
        int lastFramingOffset =
            getIntN(byteSlice.slice(byteSlice.limit() - framingOffsetSize, framingOffsetSize));
        int elementCount = (byteSlice.limit() - lastFramingOffset) / framingOffsetSize;

        elements = new ArrayList<>(elementCount);
        int position = 0;
        for (int i = 0; i < elementCount; i++) {
          int framingOffset =
              getIntN(
                  byteSlice.slice(lastFramingOffset + i * framingOffsetSize, framingOffsetSize));
          elements.add(
              elementDecoder.decode(
                  slicePreservingOrder(byteSlice, position, framingOffset - position)));
          position = align(framingOffset, alignment());
        }
      }

      return elements;
    }

    @Override
    void encode(List<U> value, ByteWriter byteWriter) {
      if (elementDecoder.hasFixedSize()) {
        for (var element : value) {
          elementDecoder.encode(element, byteWriter);
        }
      } else {
        // Variable-width arrays are encoded with a vector of framing offsets in the end.
        ArrayList<Integer> framingOffsets = new ArrayList<>(value.size());
        int startOffset = byteWriter.position();
        for (var element : value) {
          // Align the element.
          var lastRelativeEnd = byteWriter.position() - startOffset;
          byteWriter.write(new byte[align(lastRelativeEnd, alignment()) - lastRelativeEnd]);

          // Encode the element.
          elementDecoder.encode(element, byteWriter);

          // Record the framing offset of the element.
          var relativeEnd = byteWriter.position() - startOffset;
          framingOffsets.add(relativeEnd);
        }

        // Write the framing offsets.
        int framingOffsetSize = max(1, computeFramingOffsetSize(byteWriter.position() - startOffset, framingOffsets));
        for (var framingOffset : framingOffsets) {
          byteWriter.writeIntN(framingOffset, framingOffsetSize);
        }
      }
    }
  }

  private static class DictionaryDecoder<K, V> extends Decoder<Map<K, V>> {

    private final ArrayDecoder<Map.Entry<K, V>> entryArrayDecoder;

    DictionaryDecoder(Decoder<K> keyDecoder, Decoder<V> valueDecoder) {
      this.entryArrayDecoder =
          new ArrayDecoder<>(new DictionaryEntryDecoder<>(keyDecoder, valueDecoder));
    }

    @Override
    public byte alignment() {
      return entryArrayDecoder.alignment();
    }

    @Override
    @Nullable
    public Integer fixedSize() {
      return entryArrayDecoder.fixedSize();
    }

    @Override
    public @NotNull Map<K, V> decode(ByteBuffer byteSlice) {
      List<Map.Entry<K, V>> entries = entryArrayDecoder.decode(byteSlice);
      Map<K, V> result = new LinkedHashMap<>();
      for (var entry : entries) {
        result.put(entry.getKey(), entry.getValue());
      }
      return result;
    }

    @Override
    void encode(Map<K, V> value, ByteWriter byteWriter) {
      entryArrayDecoder.encode(value.entrySet().stream().toList(), byteWriter);
    }
  }

  private static class ByteArrayDecoder extends Decoder<byte[]> {

    private static final int ELEMENT_SIZE = 1;

    @Override
    public byte alignment() {
      return ELEMENT_SIZE;
    }

    @Override
    @Nullable
    Integer fixedSize() {
      return null;
    }

    @Override
    public byte @NotNull [] decode(ByteBuffer byteSlice) {
      // A simple C-style array.
      byte[] elements = new byte[byteSlice.limit() / ELEMENT_SIZE];
      byteSlice.get(elements);
      return elements;
    }

    @Override
    void encode(byte[] value, ByteWriter byteWriter) {
      byteWriter.write(value);
    }
  }

  private static class MaybeDecoder<U> extends Decoder<Optional<U>> {

    private final Decoder<U> elementDecoder;

    MaybeDecoder(Decoder<U> elementDecoder) {
      this.elementDecoder = elementDecoder;
    }

    @Override
    public byte alignment() {
      return elementDecoder.alignment();
    }

    @Override
    @Nullable
    Integer fixedSize() {
      return null;
    }

    @Override
    public @NotNull Optional<U> decode(ByteBuffer byteSlice) {
      if (!byteSlice.hasRemaining()) {
        return Optional.empty();
      } else {
        if (!elementDecoder.hasFixedSize()) {
          // Remove trailing zero byte.
          byteSlice.limit(byteSlice.limit() - 1);
        }

        return Optional.of(elementDecoder.decode(byteSlice));
      }
    }

    @Override
    void encode(Optional<U> value, ByteWriter byteWriter) {
      if (value.isEmpty()) {
        return;
      }

      elementDecoder.encode(value.get(), byteWriter);
      if (!elementDecoder.hasFixedSize()) {
        byteWriter.write((byte) 0);
      }
    }
  }

  private static class StructureDecoder<U extends Record> extends Decoder<U> {

    private final Class<U> recordType;
    private final TupleDecoder tupleDecoder;

    StructureDecoder(Class<U> recordType, Decoder<?>... componentDecoders) {
      var recordComponents = recordType.getRecordComponents();
      if (componentDecoders.length != recordComponents.length) {
        throw new IllegalArgumentException(
            "number of decoders (%d) does not match number of structure components (%d)"
                .formatted(componentDecoders.length, recordComponents.length));
      }

      this.recordType = recordType;
      this.tupleDecoder = new TupleDecoder(componentDecoders);
    }

    @Override
    public byte alignment() {
      return tupleDecoder.alignment();
    }

    @Override
    public @Nullable Integer fixedSize() {
      return tupleDecoder.fixedSize();
    }

    @Override
    public @NotNull U decode(ByteBuffer byteSlice) {
      Object[] recordConstructorArguments = tupleDecoder.decode(byteSlice);

      try {
        var recordComponentTypes =
            Arrays.stream(recordType.getRecordComponents())
                .map(RecordComponent::getType)
                .toArray(Class<?>[]::new);
        var recordConstructor = recordType.getDeclaredConstructor(recordComponentTypes);
        return recordConstructor.newInstance(recordConstructorArguments);
      } catch (NoSuchMethodException
          | InstantiationException
          | IllegalAccessException
          | InvocationTargetException e) {
        throw new IllegalStateException(e);
      }
    }

    @Override
    void encode(U value, ByteWriter byteWriter) {
      try {
        var components = recordType.getRecordComponents();
        List<Object> componentValues = new ArrayList<>(components.length);
        for (var component : components) {
          var accessor = component.getAccessor();
          var componentValue = accessor.invoke(value);
          componentValues.add(componentValue);
        }
        tupleDecoder.encode(componentValues.toArray(), byteWriter);
      } catch (IllegalAccessException | InvocationTargetException e) {
        throw new IllegalStateException(e);
      }
    }
  }

  @SuppressWarnings("Immutable")
  private static class TupleDecoder extends Decoder<Object[]> {

    private final Decoder<?>[] componentDecoders;

    TupleDecoder(Decoder<?>... componentDecoders) {
      this.componentDecoders = componentDecoders;
    }

    @Override
    public byte alignment() {
      return (byte) Arrays.stream(componentDecoders).mapToInt(Decoder::alignment).max().orElse(1);
    }

    @Override
    public @Nullable Integer fixedSize() {
      int position = 0;
      for (var componentDecoder : componentDecoders) {
        var fixedComponentSize = componentDecoder.fixedSize();
        if (fixedComponentSize == null) {
          return null;
        }

        position = align(position, componentDecoder.alignment());
        position += fixedComponentSize;
      }

      if (position == 0) {
        return 1;
      }

      return align(position, alignment());
    }

    @Override
    public Object @NotNull [] decode(ByteBuffer byteSlice) {
      int framingOffsetSize = byteCount(byteSlice.limit());

      var objects = new Object[componentDecoders.length];

      int position = 0;
      int framingOffsetIndex = 0;
      int componentIndex = 0;
      for (var componentDecoder : componentDecoders) {
        position = align(position, componentDecoder.alignment());

        var fixedComponentSize = componentDecoder.fixedSize();
        if (fixedComponentSize != null) {
          objects[componentIndex] =
              componentDecoder.decode(
                  slicePreservingOrder(byteSlice, position, fixedComponentSize));
          position += fixedComponentSize;
        } else {
          if (componentIndex == componentDecoders.length - 1) {
            // The last component never has a framing offset.
            int endPosition = byteSlice.limit() - framingOffsetIndex * framingOffsetSize;
            objects[componentIndex] =
                componentDecoder.decode(
                    slicePreservingOrder(byteSlice, position, endPosition - position));
            position = endPosition;
          } else {
            int framingOffset =
                getIntN(
                    byteSlice.slice(
                        byteSlice.limit() - (1 + framingOffsetIndex) * framingOffsetSize,
                        framingOffsetSize));
            objects[componentIndex] =
                componentDecoder.decode(
                    slicePreservingOrder(byteSlice, position, framingOffset - position));
            position = framingOffset;
            ++framingOffsetIndex;
          }
        }

        ++componentIndex;
      }

      return objects;
    }

    @Override
    @SuppressWarnings("unchecked")
    void encode(Object[] value, ByteWriter byteWriter) {
      // The unit type is encoded as a single zero byte.
      if (value.length == 0) {
        byteWriter.write((byte) 0);
        return;
      }

      int startOffset = byteWriter.position();
      ArrayList<Integer> framingOffsets = new ArrayList<>(value.length);
      for (int i = 0; i < value.length; ++i) {
        var componentDecoder = (Decoder<Object>) componentDecoders[i];

        // Align the element.
        var lastRelativeEnd = byteWriter.position() - startOffset;
        byteWriter.write(new byte[align(lastRelativeEnd, componentDecoder.alignment()) - lastRelativeEnd]);

        // Encode the element.
        componentDecoder.encode(value[i], byteWriter);

        // Record the framing offset of the element if it is of variable size.
        var fixedComponentSize = componentDecoders[i].fixedSize();
        if (fixedComponentSize == null && i < value.length - 1) {
          var relativeEnd = byteWriter.position() - startOffset;
          framingOffsets.add(relativeEnd);
        }
      }

      // Write the framing offsets in reverse order.
      int framingOffsetSize = computeFramingOffsetSize(byteWriter.position() - startOffset, framingOffsets);
      for (int i = framingOffsets.size() - 1; i >= 0; --i) {
        byteWriter.writeIntN(framingOffsets.get(i), framingOffsetSize);
      }

      // Pad the structure to its alignment if it is of fixed size.
      if (fixedSize() != null) {
        var lastRelativeEnd = byteWriter.position() - startOffset;
        byteWriter.write(new byte[align(lastRelativeEnd, alignment()) - lastRelativeEnd]);
      }
    }
  }

  private static class DictionaryEntryDecoder<K, V> extends Decoder<Map.Entry<K, V>> {

    private final TupleDecoder tupleDecoder;

    DictionaryEntryDecoder(Decoder<K> keyDecoder, Decoder<V> valueDecoder) {
      this.tupleDecoder = new TupleDecoder(keyDecoder, valueDecoder);
    }

    @Override
    public byte alignment() {
      return tupleDecoder.alignment();
    }

    @Override
    public @Nullable Integer fixedSize() {
      return tupleDecoder.fixedSize();
    }

    @Override
    @SuppressWarnings("unchecked")
    public Map.@NotNull Entry<K, V> decode(ByteBuffer byteSlice) {
      Object[] components = tupleDecoder.decode(byteSlice);
      return Map.entry((K) components[0], (V) components[1]);
    }

    @Override
    void encode(Entry<K, V> value, ByteWriter byteWriter) {
      tupleDecoder.encode(new Object[] {value.getKey(), value.getValue()}, byteWriter);
    }
  }

  private static class VariantDecoder extends Decoder<Variant> {

    @Override
    public byte alignment() {
      return 8;
    }

    @Override
    @Nullable
    Integer fixedSize() {
      return null;
    }

    @Override
    public @NotNull Variant decode(ByteBuffer byteSlice) {
      for (int i = byteSlice.limit() - 1; i >= 0; --i) {
        if (byteSlice.get(i) != 0) {
          continue;
        }

        var dataBytes = slicePreservingOrder(byteSlice, 0, i);
        var signatureBytes = byteSlice.slice(i + 1, byteSlice.limit() - (i + 1));

        Signature signature;
        try {
          signature = Signature.parse(signatureBytes);
        } catch (ParseException e) {
          throw new IllegalArgumentException(e);
        }

        return new Variant(signature, signature.decoder().decode(dataBytes));
      }

      throw new IllegalArgumentException("variant signature not found");
    }

    @Override
    void encode(Variant value, ByteWriter byteWriter) {
      value.signature().decoder().encode(value.value(), byteWriter);
      byteWriter.write((byte) 0);
      byteWriter.write(value.signature().toString().getBytes(UTF_8));
    }
  }

  private static class BooleanDecoder extends Decoder<Boolean> {

    @Override
    public byte alignment() {
      return 1;
    }

    @Override
    public Integer fixedSize() {
      return 1;
    }

    @Override
    public @NotNull Boolean decode(ByteBuffer byteSlice) {
      return byteSlice.get() != 0;
    }

    @Override
    void encode(Boolean value, ByteWriter byteWriter) {
      byteWriter.write(Boolean.TRUE.equals(value) ? (byte) 1 : (byte) 0);
    }
  }

  private static class ByteDecoder extends Decoder<Byte> {

    @Override
    public byte alignment() {
      return 1;
    }

    @Override
    public Integer fixedSize() {
      return 1;
    }

    @Override
    public @NotNull Byte decode(ByteBuffer byteSlice) {
      return byteSlice.get();
    }

    @Override
    void encode(Byte value, ByteWriter byteWriter) {
      byteWriter.write(value);
    }
  }

  private static class ShortDecoder extends Decoder<Short> {

    @Override
    public byte alignment() {
      return 2;
    }

    @Override
    public Integer fixedSize() {
      return 2;
    }

    @Override
    public @NotNull Short decode(ByteBuffer byteSlice) {
      return byteSlice.getShort();
    }

    @Override
    void encode(Short value, ByteWriter byteWriter) {
      byteWriter.write(value);
    }
  }

  private static class IntegerDecoder extends Decoder<Integer> {

    @Override
    public byte alignment() {
      return 4;
    }

    @Override
    public Integer fixedSize() {
      return 4;
    }

    @Override
    public @NotNull Integer decode(ByteBuffer byteSlice) {
      return byteSlice.getInt();
    }

    @Override
    void encode(Integer value, ByteWriter byteWriter) {
      byteWriter.write(value);
    }
  }

  private static class LongDecoder extends Decoder<Long> {

    @Override
    public byte alignment() {
      return 8;
    }

    @Override
    public Integer fixedSize() {
      return 8;
    }

    @Override
    public @NotNull Long decode(ByteBuffer byteSlice) {
      return byteSlice.getLong();
    }

    @Override
    void encode(Long value, ByteWriter byteWriter) {
      byteWriter.write(value);
    }
  }

  private static class DoubleDecoder extends Decoder<Double> {

    @Override
    public byte alignment() {
      return 8;
    }

    @Override
    public Integer fixedSize() {
      return 8;
    }

    @Override
    public @NotNull Double decode(ByteBuffer byteSlice) {
      return byteSlice.getDouble();
    }

    @Override
    void encode(Double value, ByteWriter byteWriter) {
      byteWriter.write(value);
    }
  }

  private static class StringDecoder extends Decoder<String> {

    private final Charset charset;

    public StringDecoder(Charset charset) {
      this.charset = charset;
    }

    @Override
    public byte alignment() {
      return 1;
    }

    @Override
    @Nullable
    Integer fixedSize() {
      return null;
    }

    @Override
    public @NotNull String decode(ByteBuffer byteSlice) {
      byteSlice.limit(byteSlice.limit() - 1);
      return charset.decode(byteSlice).toString();
    }

    @Override
    void encode(String value, ByteWriter byteWriter) {
      byteWriter.write(charset.encode(value).rewind());
      byteWriter.write((byte) 0);
    }
  }

  @SuppressWarnings("Immutable")
  private class MappingDecoder<U> extends Decoder<U> {

    private final Function<@NotNull T, @NotNull U> decodingFunction;
    private final Function<@NotNull U, @NotNull T> encodingFunction;

    MappingDecoder(Function<@NotNull T, @NotNull U> decodingFunction, Function<@NotNull U, @NotNull T> encodingFunction) {
      this.decodingFunction = decodingFunction;
      this.encodingFunction = encodingFunction;
    }

    @Override
    public byte alignment() {
      return Decoder.this.alignment();
    }

    @Override
    public @Nullable Integer fixedSize() {
      return Decoder.this.fixedSize();
    }

    @Override
    public @NotNull U decode(ByteBuffer byteSlice) {
      return decodingFunction.apply(Decoder.this.decode(byteSlice));
    }

    @Override
    void encode(U value, ByteWriter byteWriter) {
      Decoder.this.encode(encodingFunction.apply(value), byteWriter);
    }
  }

  @SuppressWarnings("Immutable")
  private class ContramappingDecoder extends Decoder<T> {

    private final UnaryOperator<ByteBuffer> decodingFunction;
    private final UnaryOperator<ByteBuffer> encodingFunction;

    ContramappingDecoder(UnaryOperator<ByteBuffer> decodingFunction, UnaryOperator<ByteBuffer> encodingFunction) {
      this.decodingFunction = decodingFunction;
      this.encodingFunction = encodingFunction;
    }

    @Override
    public byte alignment() {
      return Decoder.this.alignment();
    }

    @Override
    public @Nullable Integer fixedSize() {
      return Decoder.this.fixedSize();
    }

    @Override
    public @NotNull T decode(ByteBuffer byteSlice) {
      var transformedBuffer = decodingFunction.apply(byteSlice.asReadOnlyBuffer().order(byteSlice.order()));
      return Decoder.this.decode(transformedBuffer);
    }

    @Override
    void encode(T value, ByteWriter byteWriter) {
      var innerByteWriter = new ByteWriter();
      Decoder.this.encode(value, innerByteWriter);
      var transformedBuffer = encodingFunction.apply(innerByteWriter.toByteBuffer());
      byteWriter.write(transformedBuffer.rewind());
    }
  }

  private class ByteOrderFixingDecoder extends Decoder<T> {

    private final ByteOrder byteOrder;

    ByteOrderFixingDecoder(ByteOrder byteOrder) {
      this.byteOrder = byteOrder;
    }

    @Override
    public byte alignment() {
      return Decoder.this.alignment();
    }

    @Override
    public @Nullable Integer fixedSize() {
      return Decoder.this.fixedSize();
    }

    @Override
    public @NotNull T decode(ByteBuffer byteSlice) {
      var newByteSlice = byteSlice.duplicate();
      newByteSlice.order(byteOrder);
      return Decoder.this.decode(newByteSlice);
    }

    @Override
    protected void encode(T value, ByteWriter byteWriter) {
      var newByteWriter = byteWriter.duplicate();
      newByteWriter.order(byteOrder);
      Decoder.this.encode(value, newByteWriter);
    }
  }

  private static ByteBuffer slicePreservingOrder(ByteBuffer byteSlice, int index, int length) {
    return byteSlice.slice(index, length).order(byteSlice.order());
  }

  @SuppressWarnings("Immutable")
  private static class PredicateDecoder<U> extends Decoder<U> {

    private final Predicate<ByteBuffer> selector;
    private final Decoder<U> thenDecoder;
    private final Decoder<U> elseDecoder;

    PredicateDecoder(
        Predicate<ByteBuffer> selector, Decoder<U> thenDecoder, Decoder<U> elseDecoder) {
      this.selector = selector;
      this.thenDecoder = thenDecoder;
      this.elseDecoder = elseDecoder;
      if (thenDecoder.alignment() != elseDecoder.alignment()) {
        throw new IllegalArgumentException(
            "incompatible alignments in predicate branches: then=%d, else=%d"
                .formatted(thenDecoder.alignment(), elseDecoder.alignment()));
      }

      if (!Objects.equals(thenDecoder.fixedSize(), elseDecoder.fixedSize())) {
        throw new IllegalArgumentException(
            "incompatible sizes in predicate branches: then=%s, else=%s"
                .formatted(
                    requireNonNullElse(thenDecoder.fixedSize(), "(null)"),
                    requireNonNullElse(elseDecoder.fixedSize(), "(null)")));
      }
    }

    @Override
    public byte alignment() {
      return thenDecoder.alignment();
    }

    @Override
    public @Nullable Integer fixedSize() {
      return thenDecoder.fixedSize();
    }

    @Override
    public @NotNull U decode(ByteBuffer byteSlice) {
      var b = selector.test(byteSlice);
      byteSlice.rewind();
      return b ? thenDecoder.decode(byteSlice) : elseDecoder.decode(byteSlice);
    }

    @Override
    public void encode(U value, ByteWriter byteWriter) {
      elseDecoder.encode(value, byteWriter);
    }
  }

  private static class ByteWriter {
    private ByteOrder byteOrder = BIG_ENDIAN;
    private final ByteArrayOutputStream outputStream;

    ByteWriter() {
      this.outputStream = new ByteArrayOutputStream();
    }

    private ByteWriter(ByteArrayOutputStream outputStream) {
      this.outputStream = outputStream;
    }

    void write(byte[] bytes) {
      outputStream.write(bytes, 0, bytes.length);
    }

    @SuppressWarnings("java:S2095")
    void write(ByteBuffer byteBuffer) {
      var channel = Channels.newChannel(outputStream);
      try {
        channel.write(byteBuffer);
      } catch (IOException e) {
        // impossible
        throw new IllegalStateException(e);
      }
    }

    void write(byte value) {
      outputStream.write(value);
    }

    void write(int value) {
      write(ByteBuffer.allocate(4).order(byteOrder).putInt(value).rewind());
    }

    void write(long value) {
      write(ByteBuffer.allocate(8).order(byteOrder).putLong(value).rewind());
    }

    void write(short value) {
      write(ByteBuffer.allocate(2).order(byteOrder).putShort(value).rewind());
    }

    void write(double value) {
      write(ByteBuffer.allocate(8).order(byteOrder).putDouble(value).rewind());
    }

    private void writeIntN(int value, int byteCount) {
      var byteBuffer = ByteBuffer.allocate(byteCount).order(LITTLE_ENDIAN);
        switch (byteCount) {
          case 0 -> {}
          case 1 ->
            byteBuffer.put((byte) value);
          case 2 ->
            byteBuffer.putShort((short) value);
          case 4 ->
            byteBuffer.putInt(value);
          default ->
            throw new IllegalArgumentException("invalid byte count: %d".formatted(byteCount));
        }
      write(byteBuffer.rewind());
    }

    ByteWriter duplicate() {
        var duplicate = new ByteWriter(outputStream);
        duplicate.byteOrder = byteOrder;
        return duplicate;
    }

    ByteBuffer toByteBuffer() {
      return ByteBuffer.wrap(outputStream.toByteArray());
    }

    void order(ByteOrder byteOrder) {
        this.byteOrder = byteOrder;
    }

    int position() {
      return outputStream.size();
    }
  }
}
