Skip to content

Commit 67ec5c1

Browse files
committed
Add abillity to use TypeResolvers to recover from errors during parsing
1 parent 2942f78 commit 67ec5c1

File tree

2 files changed

+56
-14
lines changed

2 files changed

+56
-14
lines changed

src/main/java/de/bluecolored/bluenbt/TypeResolver.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
*/
2525
package de.bluecolored.bluenbt;
2626

27+
import java.io.IOException;
28+
2729
public interface TypeResolver<T, B> {
2830

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

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

37+
/**
38+
* Called when the raw type data could be read fine, but parsing it against the base type threw an exception.<br>
39+
* Can be used to recover from errors with some default value.<br>
40+
* Defaults to just rethrowing the exception.
41+
*/
42+
default T onException(IOException parseException) throws IOException {
43+
throw parseException;
44+
}
45+
46+
/**
47+
* Called when the raw type data could be read fine, the base type could also be parsed,
48+
* but parsing it against the resolved type threw an exception.<br>
49+
* Can be used to recover from errors with some default value.<br>
50+
* Defaults to calling {@link #onException(IOException)}
51+
*/
52+
default T onException(IOException parseException, B base) throws IOException {
53+
return onException(parseException);
54+
}
55+
3556
}

src/main/java/de/bluecolored/bluenbt/adapter/DefaultDeserializerFactory.java

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,16 @@ static class TypeResolvingAdapter<T> implements TypeDeserializer<T> {
6868
public TypeResolvingAdapter(TypeToken<T> type, TypeResolver<T, ?> typeResolver, BlueNBT blueNBT) {
6969
this.typeResolver = (TypeResolver<T, Object>) typeResolver;
7070
this.baseType = this.typeResolver.getBaseType();
71-
this.baseDeserializer = new DefaultAdapter<>(baseType, blueNBT);
71+
this.baseDeserializer = baseType.equals(type) ?
72+
new DefaultAdapter<>(baseType, blueNBT) :
73+
blueNBT.getTypeDeserializer(baseType);
7274
this.delegateDeserializers = new HashMap<>();
73-
for (TypeToken<? extends T> resolved : typeResolver.getPossibleTypes())
74-
delegateDeserializers.put(resolved, new DefaultAdapter<>(resolved, blueNBT));
75+
for (TypeToken<? extends T> resolved : typeResolver.getPossibleTypes()) {
76+
delegateDeserializers.put(resolved, resolved.equals(type) ?
77+
new DefaultAdapter<>(resolved, blueNBT) :
78+
blueNBT.getTypeDeserializer(resolved)
79+
);
80+
}
7581
this.fallbackDeserializer = new DefaultAdapter<>(type, blueNBT);
7682
}
7783

@@ -81,20 +87,35 @@ public T read(NBTReader reader) throws IOException {
8187
// read next element as raw data
8288
byte[] data = reader.raw();
8389

84-
// parse data first into base object
85-
Object base = baseDeserializer.read(new NBTReader(data));
90+
try {
91+
92+
// parse data first into base object
93+
Object base = baseDeserializer.read(new NBTReader(data));
94+
95+
try {
8696

87-
// resolve type
88-
TypeToken<? extends T> resolvedType = typeResolver.resolve(base);
89-
TypeDeserializer<? extends T> deserializer = delegateDeserializers.get(resolvedType);
90-
if (deserializer == null) deserializer = fallbackDeserializer;
97+
// resolve type
98+
TypeToken<? extends T> resolvedType = typeResolver.resolve(base);
99+
TypeDeserializer<? extends T> deserializer = delegateDeserializers.get(resolvedType);
100+
if (deserializer == null) deserializer = fallbackDeserializer;
91101

92-
// shortcut if resolved type == base type
93-
if (resolvedType.equals(baseType))
94-
return (T) base;
102+
// shortcut if resolved type == base type
103+
if (resolvedType.equals(baseType))
104+
return (T) base;
95105

96-
// parse data into final type
97-
return deserializer.read(new NBTReader(data));
106+
// parse data into final type
107+
return deserializer.read(new NBTReader(data));
108+
109+
} catch (IOException ex) {
110+
return typeResolver.onException(ex, base);
111+
} catch (Exception ex) {
112+
return typeResolver.onException(new IOException(ex), base);
113+
}
114+
} catch (IOException ex) {
115+
return typeResolver.onException(ex);
116+
} catch (Exception ex) {
117+
return typeResolver.onException(new IOException(ex));
118+
}
98119
}
99120

100121
}

0 commit comments

Comments
 (0)