diff --git a/src/main/java/de/bluecolored/bluenbt/TypeResolver.java b/src/main/java/de/bluecolored/bluenbt/TypeResolver.java index c4b331d..479b655 100644 --- a/src/main/java/de/bluecolored/bluenbt/TypeResolver.java +++ b/src/main/java/de/bluecolored/bluenbt/TypeResolver.java @@ -24,6 +24,8 @@ */ package de.bluecolored.bluenbt; +import java.io.IOException; + public interface TypeResolver { TypeToken getBaseType(); @@ -32,4 +34,23 @@ public interface TypeResolver { Iterable> getPossibleTypes(); + /** + * Called when the raw type data could be read fine, but parsing it against the base type threw an exception.
+ * Can be used to recover from errors with some default value.
+ * Defaults to just rethrowing the exception. + */ + default T onException(IOException parseException) throws IOException { + throw parseException; + } + + /** + * Called when the raw type data could be read fine, the base type could also be parsed, + * but parsing it against the resolved type threw an exception.
+ * Can be used to recover from errors with some default value.
+ * Defaults to calling {@link #onException(IOException)} + */ + default T onException(IOException parseException, B base) throws IOException { + return onException(parseException); + } + } diff --git a/src/main/java/de/bluecolored/bluenbt/adapter/DefaultDeserializerFactory.java b/src/main/java/de/bluecolored/bluenbt/adapter/DefaultDeserializerFactory.java index 4a55e0e..c8f3e5c 100644 --- a/src/main/java/de/bluecolored/bluenbt/adapter/DefaultDeserializerFactory.java +++ b/src/main/java/de/bluecolored/bluenbt/adapter/DefaultDeserializerFactory.java @@ -68,10 +68,16 @@ static class TypeResolvingAdapter implements TypeDeserializer { public TypeResolvingAdapter(TypeToken type, TypeResolver typeResolver, BlueNBT blueNBT) { this.typeResolver = (TypeResolver) typeResolver; this.baseType = this.typeResolver.getBaseType(); - this.baseDeserializer = new DefaultAdapter<>(baseType, blueNBT); + this.baseDeserializer = baseType.equals(type) ? + new DefaultAdapter<>(baseType, blueNBT) : + blueNBT.getTypeDeserializer(baseType); this.delegateDeserializers = new HashMap<>(); - for (TypeToken resolved : typeResolver.getPossibleTypes()) - delegateDeserializers.put(resolved, new DefaultAdapter<>(resolved, blueNBT)); + for (TypeToken resolved : typeResolver.getPossibleTypes()) { + delegateDeserializers.put(resolved, resolved.equals(type) ? + new DefaultAdapter<>(resolved, blueNBT) : + blueNBT.getTypeDeserializer(resolved) + ); + } this.fallbackDeserializer = new DefaultAdapter<>(type, blueNBT); } @@ -81,20 +87,35 @@ public T read(NBTReader reader) throws IOException { // read next element as raw data byte[] data = reader.raw(); - // parse data first into base object - Object base = baseDeserializer.read(new NBTReader(data)); + try { + + // parse data first into base object + Object base = baseDeserializer.read(new NBTReader(data)); + + try { - // resolve type - TypeToken resolvedType = typeResolver.resolve(base); - TypeDeserializer deserializer = delegateDeserializers.get(resolvedType); - if (deserializer == null) deserializer = fallbackDeserializer; + // resolve type + TypeToken resolvedType = typeResolver.resolve(base); + TypeDeserializer deserializer = delegateDeserializers.get(resolvedType); + if (deserializer == null) deserializer = fallbackDeserializer; - // shortcut if resolved type == base type - if (resolvedType.equals(baseType)) - return (T) base; + // shortcut if resolved type == base type + if (resolvedType.equals(baseType)) + return (T) base; - // parse data into final type - return deserializer.read(new NBTReader(data)); + // parse data into final type + return deserializer.read(new NBTReader(data)); + + } catch (IOException ex) { + return typeResolver.onException(ex, base); + } catch (Exception ex) { + return typeResolver.onException(new IOException(ex), base); + } + } catch (IOException ex) { + return typeResolver.onException(ex); + } catch (Exception ex) { + return typeResolver.onException(new IOException(ex)); + } } }