Skip to content

Commit

Permalink
Add abillity to use TypeResolvers to recover from errors during parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
TBlueF committed Dec 22, 2024
1 parent 2942f78 commit 67ec5c1
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 14 deletions.
21 changes: 21 additions & 0 deletions src/main/java/de/bluecolored/bluenbt/TypeResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
*/
package de.bluecolored.bluenbt;

import java.io.IOException;

public interface TypeResolver<T, B> {

TypeToken<B> getBaseType();
Expand All @@ -32,4 +34,23 @@ public interface TypeResolver<T, B> {

Iterable<TypeToken<? extends T>> getPossibleTypes();

/**
* Called when the raw type data could be read fine, but parsing it against the base type threw an exception.<br>
* Can be used to recover from errors with some default value.<br>
* 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.<br>
* Can be used to recover from errors with some default value.<br>
* Defaults to calling {@link #onException(IOException)}
*/
default T onException(IOException parseException, B base) throws IOException {
return onException(parseException);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,16 @@ static class TypeResolvingAdapter<T> implements TypeDeserializer<T> {
public TypeResolvingAdapter(TypeToken<T> type, TypeResolver<T, ?> typeResolver, BlueNBT blueNBT) {
this.typeResolver = (TypeResolver<T, Object>) 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<? extends T> resolved : typeResolver.getPossibleTypes())
delegateDeserializers.put(resolved, new DefaultAdapter<>(resolved, blueNBT));
for (TypeToken<? extends T> resolved : typeResolver.getPossibleTypes()) {
delegateDeserializers.put(resolved, resolved.equals(type) ?
new DefaultAdapter<>(resolved, blueNBT) :
blueNBT.getTypeDeserializer(resolved)
);
}
this.fallbackDeserializer = new DefaultAdapter<>(type, blueNBT);
}

Expand All @@ -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<? extends T> resolvedType = typeResolver.resolve(base);
TypeDeserializer<? extends T> deserializer = delegateDeserializers.get(resolvedType);
if (deserializer == null) deserializer = fallbackDeserializer;
// resolve type
TypeToken<? extends T> resolvedType = typeResolver.resolve(base);
TypeDeserializer<? extends T> 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));
}
}

}
Expand Down

0 comments on commit 67ec5c1

Please sign in to comment.