Switch from JetBrains annotations to JSpecify.

Change-Id: Ia04b52c36f9779ab15e688e0dd7434644b3a3f7f
diff --git a/jgvariant-core/pom.xml b/jgvariant-core/pom.xml
index 89ccb6f..e8730a3 100644
--- a/jgvariant-core/pom.xml
+++ b/jgvariant-core/pom.xml
@@ -45,6 +45,11 @@
       <optional>true</optional>
     </dependency>
     <dependency>
+      <groupId>org.jspecify</groupId>
+      <artifactId>jspecify</artifactId>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
       <groupId>org.apiguardian</groupId>
       <artifactId>apiguardian-api</artifactId>
       <optional>true</optional>
diff --git a/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/Decoder.java b/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/Decoder.java
index 74d569d..4f2ae10 100644
--- a/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/Decoder.java
+++ b/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/Decoder.java
@@ -4,12 +4,13 @@
 
 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 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;
 
+import com.google.errorprone.annotations.Immutable;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.lang.reflect.InvocationTargetException;
@@ -24,12 +25,10 @@
 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;
+import org.apiguardian.api.API;
+import org.apiguardian.api.API.Status;
+import org.jspecify.annotations.NonNull;
+import org.jspecify.annotations.Nullable;
 
 /**
  * Type class for decodable types.
@@ -79,7 +78,7 @@
    *     data.
    * @throws IllegalArgumentException if the serialized GVariant is ill-formed
    */
-  public abstract @NotNull T decode(ByteBuffer byteSlice);
+  public abstract @NonNull T decode(ByteBuffer byteSlice);
 
   /**
    * Encodes a value of type {@code T} into a {@link ByteBuffer} holding a serialized GVariant.
@@ -121,7 +120,9 @@
    * @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) {
+  public final <U> Decoder<U> map(
+      Function<@NonNull T, @NonNull U> decodingFunction,
+      Function<@NonNull U, @NonNull T> encodingFunction) {
     return new MappingDecoder<>(decodingFunction, encodingFunction);
   }
 
@@ -396,7 +397,7 @@
     }
 
     @Override
-    public @NotNull List<U> decode(ByteBuffer byteSlice) {
+    public @NonNull List<U> decode(ByteBuffer byteSlice) {
       List<U> elements;
 
       var elementSize = elementDecoder.fixedSize();
@@ -486,7 +487,7 @@
     }
 
     @Override
-    public @NotNull Map<K, V> decode(ByteBuffer byteSlice) {
+    public @NonNull 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) {
@@ -517,7 +518,7 @@
     }
 
     @Override
-    public byte @NotNull [] decode(ByteBuffer byteSlice) {
+    public byte @NonNull [] decode(ByteBuffer byteSlice) {
       // A simple C-style array.
       byte[] elements = new byte[byteSlice.limit() / ELEMENT_SIZE];
       byteSlice.get(elements);
@@ -550,7 +551,7 @@
     }
 
     @Override
-    public @NotNull Optional<U> decode(ByteBuffer byteSlice) {
+    public @NonNull Optional<U> decode(ByteBuffer byteSlice) {
       if (!byteSlice.hasRemaining()) {
         return Optional.empty();
       } else {
@@ -604,7 +605,7 @@
     }
 
     @Override
-    public @NotNull U decode(ByteBuffer byteSlice) {
+    public @NonNull U decode(ByteBuffer byteSlice) {
       Object[] recordConstructorArguments = tupleDecoder.decode(byteSlice);
 
       try {
@@ -674,7 +675,7 @@
     }
 
     @Override
-    public Object @NotNull [] decode(ByteBuffer byteSlice) {
+    public Object @NonNull [] decode(ByteBuffer byteSlice) {
       int framingOffsetSize = byteCount(byteSlice.limit());
 
       var objects = new Object[componentDecoders.length];
@@ -782,7 +783,7 @@
 
     @Override
     @SuppressWarnings("unchecked")
-    public Map.@NotNull Entry<K, V> decode(ByteBuffer byteSlice) {
+    public Map.@NonNull Entry<K, V> decode(ByteBuffer byteSlice) {
       Object[] components = tupleDecoder.decode(byteSlice);
       return Map.entry((K) components[0], (V) components[1]);
     }
@@ -807,7 +808,7 @@
     }
 
     @Override
-    public @NotNull Variant decode(ByteBuffer byteSlice) {
+    public @NonNull Variant decode(ByteBuffer byteSlice) {
       for (int i = byteSlice.limit() - 1; i >= 0; --i) {
         if (byteSlice.get(i) != 0) {
           continue;
@@ -850,7 +851,7 @@
     }
 
     @Override
-    public @NotNull Boolean decode(ByteBuffer byteSlice) {
+    public @NonNull Boolean decode(ByteBuffer byteSlice) {
       return byteSlice.get() != 0;
     }
 
@@ -873,7 +874,7 @@
     }
 
     @Override
-    public @NotNull Byte decode(ByteBuffer byteSlice) {
+    public @NonNull Byte decode(ByteBuffer byteSlice) {
       return byteSlice.get();
     }
 
@@ -896,7 +897,7 @@
     }
 
     @Override
-    public @NotNull Short decode(ByteBuffer byteSlice) {
+    public @NonNull Short decode(ByteBuffer byteSlice) {
       return byteSlice.getShort();
     }
 
@@ -919,7 +920,7 @@
     }
 
     @Override
-    public @NotNull Integer decode(ByteBuffer byteSlice) {
+    public @NonNull Integer decode(ByteBuffer byteSlice) {
       return byteSlice.getInt();
     }
 
@@ -942,7 +943,7 @@
     }
 
     @Override
-    public @NotNull Long decode(ByteBuffer byteSlice) {
+    public @NonNull Long decode(ByteBuffer byteSlice) {
       return byteSlice.getLong();
     }
 
@@ -965,7 +966,7 @@
     }
 
     @Override
-    public @NotNull Double decode(ByteBuffer byteSlice) {
+    public @NonNull Double decode(ByteBuffer byteSlice) {
       return byteSlice.getDouble();
     }
 
@@ -995,7 +996,7 @@
     }
 
     @Override
-    public @NotNull String decode(ByteBuffer byteSlice) {
+    public @NonNull String decode(ByteBuffer byteSlice) {
       byteSlice.limit(byteSlice.limit() - 1);
       return charset.decode(byteSlice).toString();
     }
@@ -1010,10 +1011,12 @@
   @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;
+    private final Function<@NonNull T, @NonNull U> decodingFunction;
+    private final Function<@NonNull U, @NonNull T> encodingFunction;
 
-    MappingDecoder(Function<@NotNull T, @NotNull U> decodingFunction, Function<@NotNull U, @NotNull T> encodingFunction) {
+    MappingDecoder(
+        Function<@NonNull T, @NonNull U> decodingFunction,
+        Function<@NonNull U, @NonNull T> encodingFunction) {
       this.decodingFunction = decodingFunction;
       this.encodingFunction = encodingFunction;
     }
@@ -1029,7 +1032,7 @@
     }
 
     @Override
-    public @NotNull U decode(ByteBuffer byteSlice) {
+    public @NonNull U decode(ByteBuffer byteSlice) {
       return decodingFunction.apply(Decoder.this.decode(byteSlice));
     }
 
@@ -1061,7 +1064,7 @@
     }
 
     @Override
-    public @NotNull T decode(ByteBuffer byteSlice) {
+    public @NonNull T decode(ByteBuffer byteSlice) {
       var transformedBuffer = decodingFunction.apply(byteSlice.asReadOnlyBuffer().order(byteSlice.order()));
       return Decoder.this.decode(transformedBuffer);
     }
@@ -1094,7 +1097,7 @@
     }
 
     @Override
-    public @NotNull T decode(ByteBuffer byteSlice) {
+    public @NonNull T decode(ByteBuffer byteSlice) {
       var newByteSlice = byteSlice.duplicate();
       newByteSlice.order(byteOrder);
       return Decoder.this.decode(newByteSlice);
@@ -1150,7 +1153,7 @@
     }
 
     @Override
-    public @NotNull U decode(ByteBuffer byteSlice) {
+    public @NonNull U decode(ByteBuffer byteSlice) {
       var b = selector.test(byteSlice);
       byteSlice.rewind();
       return b ? thenDecoder.decode(byteSlice) : elseDecoder.decode(byteSlice);
diff --git a/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/Signature.java b/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/Signature.java
index f59b267..1b33151 100644
--- a/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/Signature.java
+++ b/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/Signature.java
@@ -14,7 +14,7 @@
 import java.util.Objects;
 import org.apiguardian.api.API;
 import org.apiguardian.api.API.Status;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
 
 /**
  * A GVariant signature string.
diff --git a/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/package-info.java b/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/package-info.java
index e2e8143..e51c9c4 100644
--- a/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/package-info.java
+++ b/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/package-info.java
@@ -28,4 +28,7 @@
  * List<ExampleRecord> example = decoder.decode(ByteBuffer.wrap(bytes));
  * }
  */
+@NullMarked
 package eu.mulk.jgvariant.core;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/jgvariant-core/src/main/java/module-info.java b/jgvariant-core/src/main/java/module-info.java
index 51c7252..b0b61a7 100644
--- a/jgvariant-core/src/main/java/module-info.java
+++ b/jgvariant-core/src/main/java/module-info.java
@@ -2,6 +2,8 @@
 //
 // SPDX-License-Identifier: LGPL-3.0-or-later
 
+import org.jspecify.annotations.NullMarked;
+
 /**
  * Provides a parser for the <a href="https://docs.gtk.org/glib/struct.Variant.html">GVariant</a>
  * serialization format.
@@ -79,10 +81,12 @@
  * }
  * }
  */
+@NullMarked
 module eu.mulk.jgvariant.core {
   requires static com.google.errorprone.annotations;
   requires static org.apiguardian.api;
   requires static org.jetbrains.annotations;
+  requires static org.jspecify;
 
   exports eu.mulk.jgvariant.core;
 }
diff --git a/jgvariant-ostree/pom.xml b/jgvariant-ostree/pom.xml
index 1007ee1..538630b 100644
--- a/jgvariant-ostree/pom.xml
+++ b/jgvariant-ostree/pom.xml
@@ -52,6 +52,11 @@
       <optional>true</optional>
     </dependency>
     <dependency>
+      <groupId>org.jspecify</groupId>
+      <artifactId>jspecify</artifactId>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
       <groupId>org.apiguardian</groupId>
       <artifactId>apiguardian-api</artifactId>
       <optional>true</optional>
diff --git a/jgvariant-ostree/src/main/java/eu/mulk/jgvariant/ostree/ByteString.java b/jgvariant-ostree/src/main/java/eu/mulk/jgvariant/ostree/ByteString.java
index 3bd8b25..f9309b9 100644
--- a/jgvariant-ostree/src/main/java/eu/mulk/jgvariant/ostree/ByteString.java
+++ b/jgvariant-ostree/src/main/java/eu/mulk/jgvariant/ostree/ByteString.java
@@ -10,7 +10,7 @@
 import java.util.HexFormat;
 import java.util.stream.IntStream;
 import java.util.stream.Stream;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.Nullable;
 
 /**
  * A wrapper for a {@code byte[]} that implements {@link #equals(Object)}, {@link #hashCode()}, and
diff --git a/jgvariant-ostree/src/main/java/eu/mulk/jgvariant/ostree/package-info.java b/jgvariant-ostree/src/main/java/eu/mulk/jgvariant/ostree/package-info.java
index 858a748..63988ce 100644
--- a/jgvariant-ostree/src/main/java/eu/mulk/jgvariant/ostree/package-info.java
+++ b/jgvariant-ostree/src/main/java/eu/mulk/jgvariant/ostree/package-info.java
@@ -116,7 +116,9 @@
  * </dl>
  */
 @API(status = Status.EXPERIMENTAL)
+@NullMarked
 package eu.mulk.jgvariant.ostree;
 
 import org.apiguardian.api.API;
 import org.apiguardian.api.API.Status;
+import org.jspecify.annotations.NullMarked;
diff --git a/jgvariant-ostree/src/main/java/module-info.java b/jgvariant-ostree/src/main/java/module-info.java
index cd5f78c..201901c 100644
--- a/jgvariant-ostree/src/main/java/module-info.java
+++ b/jgvariant-ostree/src/main/java/module-info.java
@@ -2,6 +2,8 @@
 //
 // SPDX-License-Identifier: LGPL-3.0-or-later
 
+import org.jspecify.annotations.NullMarked;
+
 /**
  * {@link eu.mulk.jgvariant.core.Decoder} instances for OSTree repositories.
  *
@@ -78,6 +80,7 @@
  * }
  * }
  */
+@NullMarked
 module eu.mulk.jgvariant.ostree {
   requires transitive eu.mulk.jgvariant.core;
 
@@ -86,6 +89,7 @@
   requires static com.google.errorprone.annotations;
   requires static org.apiguardian.api;
   requires static org.jetbrains.annotations;
+  requires static org.jspecify;
 
   exports eu.mulk.jgvariant.ostree;
 }
diff --git a/jgvariant-parent/pom.xml b/jgvariant-parent/pom.xml
index 1e41527..815dff2 100644
--- a/jgvariant-parent/pom.xml
+++ b/jgvariant-parent/pom.xml
@@ -76,6 +76,7 @@
     <inject-resources.version>0.3.3</inject-resources.version>
     <jetbrains-annotations.version>24.1.0</jetbrains-annotations.version>
     <jqwik.version>1.9.0</jqwik.version>
+    <jspecify.version>1.0.0</jspecify.version>
     <junit-jupiter.version>5.10.3</junit-jupiter.version>
     <nullaway.version>0.11.0</nullaway.version>
     <parsson.version>1.1.6</parsson.version>
@@ -105,6 +106,11 @@
         <version>${jetbrains-annotations.version}</version>
       </dependency>
       <dependency>
+        <groupId>org.jspecify</groupId>
+        <artifactId>jspecify</artifactId>
+        <version>${jspecify.version}</version>
+      </dependency>
+      <dependency>
         <groupId>org.apiguardian</groupId>
         <artifactId>apiguardian-api</artifactId>
         <version>${apiguardian.version}</version>
diff --git a/jgvariant-tool/pom.xml b/jgvariant-tool/pom.xml
index f4026e4..9d764dc 100644
--- a/jgvariant-tool/pom.xml
+++ b/jgvariant-tool/pom.xml
@@ -59,6 +59,12 @@
       <optional>true</optional>
     </dependency>
     <dependency>
+      <groupId>org.jspecify</groupId>
+      <artifactId>jspecify</artifactId>
+      <scope>provided</scope>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
       <groupId>org.apiguardian</groupId>
       <artifactId>apiguardian-api</artifactId>
       <scope>provided</scope>
diff --git a/jgvariant-tool/src/main/java/eu/mulk/jgvariant/tool/MainCommand.java b/jgvariant-tool/src/main/java/eu/mulk/jgvariant/tool/MainCommand.java
index db724dd..9c3e0f9 100644
--- a/jgvariant-tool/src/main/java/eu/mulk/jgvariant/tool/MainCommand.java
+++ b/jgvariant-tool/src/main/java/eu/mulk/jgvariant/tool/MainCommand.java
@@ -29,8 +29,8 @@
 import java.util.*;
 import java.util.logging.Logger;
 import java.util.stream.IntStream;
-import org.jetbrains.annotations.Nullable;
 import org.jetbrains.annotations.VisibleForTesting;
+import org.jspecify.annotations.Nullable;
 import picocli.AutoComplete;
 import picocli.CommandLine;
 import picocli.CommandLine.*;
diff --git a/jgvariant-tool/src/main/java/eu/mulk/jgvariant/tool/package-info.java b/jgvariant-tool/src/main/java/eu/mulk/jgvariant/tool/package-info.java
index 54a4fff..43dd1bf 100644
--- a/jgvariant-tool/src/main/java/eu/mulk/jgvariant/tool/package-info.java
+++ b/jgvariant-tool/src/main/java/eu/mulk/jgvariant/tool/package-info.java
@@ -9,6 +9,8 @@
  * be used to manipulate GVariant-formatted files from the command line.
  */
 @API(status = API.Status.INTERNAL)
+@NullMarked
 package eu.mulk.jgvariant.tool;
 
 import org.apiguardian.api.API;
+import org.jspecify.annotations.NullMarked;
diff --git a/jgvariant-tool/src/main/java/module-info.java b/jgvariant-tool/src/main/java/module-info.java
index 3f38283..c0f413d 100644
--- a/jgvariant-tool/src/main/java/module-info.java
+++ b/jgvariant-tool/src/main/java/module-info.java
@@ -2,6 +2,8 @@
 //
 // SPDX-License-Identifier: GPL-3.0-or-later
 
+import org.jspecify.annotations.NullMarked;
+
 /**
  * The {@code jgvariant} command line tool.
  *
@@ -68,6 +70,7 @@
  * $ jgvariant ostree summary add-static-delta ./jgvariant-ostree/src/test/resources/ostree/summary f481144629474bd88c106e45ac405ebd75b324b0655af1aec14b31786ae1fd61 31c8835d5c9d2c6687a50091c85142d1b2d853ff416a9fb81b4ee30754510d52
  * }
  */
+@NullMarked
 module eu.mulk.jgvariant.tool {
   requires transitive eu.mulk.jgvariant.ostree;
   requires info.picocli;
@@ -77,6 +80,7 @@
   requires static com.google.errorprone.annotations;
   requires static org.apiguardian.api;
   requires static org.jetbrains.annotations;
+  requires static org.jspecify;
 
   opens eu.mulk.jgvariant.tool to
       info.picocli;