Decode dictionary entry arrays as dictionaries.

Change-Id: If31659887dcd2d219d421f78e50cdeb1be3709a9
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 8297d79..33b0480 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
@@ -198,6 +198,7 @@
    *   <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>
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 6a4d01d..c697730 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
@@ -91,23 +91,37 @@
       case 's', 'o', 'g' -> Decoder.ofString(StandardCharsets.UTF_8);
       case 'v' -> Decoder.ofVariant();
       case 'm' -> Decoder.ofMaybe(parseSignature(signature));
-      case 'a' -> Decoder.ofArray(parseSignature(signature));
       case '(' -> Decoder.ofStructure(parseTupleTypes(signature).toArray(new Decoder<?>[0]));
-      case '{' -> {
-        var tupleTypes = parseTupleTypes(signature);
-        if (tupleTypes.size() != 2) {
-          throw new ParseException(
-              String.format(
-                  "dictionary entry type with %d components, expected 2", tupleTypes.size()),
-              signature.position());
+      case 'a' -> {
+        char elementC = (char) signature.get(signature.position());
+        if (elementC == '{') {
+          signature.get();
+          List<Decoder<?>> entryTypes = parseDictionaryEntryTypes(signature);
+          yield Decoder.ofDictionary(entryTypes.get(0), entryTypes.get(1));
+        } else {
+          yield Decoder.ofArray(parseSignature(signature));
         }
-        yield Decoder.ofDictionaryEntry(tupleTypes.get(0), tupleTypes.get(1));
+      }
+      case '{' -> {
+        List<Decoder<?>> entryTypes = parseDictionaryEntryTypes(signature);
+        yield Decoder.ofDictionaryEntry(entryTypes.get(0), entryTypes.get(1));
       }
       default -> throw new ParseException(
           String.format("encountered unknown signature byte '%c'", c), signature.position());
     };
   }
 
+  private static List<Decoder<?>> parseDictionaryEntryTypes(ByteBuffer signature)
+      throws ParseException {
+    var tupleTypes = parseTupleTypes(signature);
+    if (tupleTypes.size() != 2) {
+      throw new ParseException(
+          String.format("dictionary entry type with %d components, expected 2", tupleTypes.size()),
+          signature.position());
+    }
+    return tupleTypes;
+  }
+
   private static List<Decoder<?>> parseTupleTypes(ByteBuffer signature) throws ParseException {
     List<Decoder<?>> decoders = new ArrayList<>();
 
diff --git a/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/Variant.java b/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/Variant.java
index 34d3945..d9e13dd 100644
--- a/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/Variant.java
+++ b/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/Variant.java
@@ -18,6 +18,7 @@
  *   <li>{@link java.util.Optional} (a GVariant {@code Maybe} type)
  *   <li>{@link java.util.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>