Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,17 @@ private sealed interface WriteState {
record List(int remainingValues) implements WriteState {
}

record Compound(boolean hasPrevious) implements WriteState {
enum Compound implements WriteState {
DEFAULT,
/**
* Indicates that an entry was just finished, so when a new name is encountered, a comma should be emitted
* first.
*/
HAS_PREVIOUS_ENTRY,
}

record WritingArray() implements WriteState {
enum WritingArray implements WriteState {
INSTANCE
}
}

Expand Down Expand Up @@ -72,13 +79,14 @@ public void write(Appendable output, LinStream tokens) throws IOException {
}
switch (token) {
case LinToken.Name(String name, Optional<LinTagId> id) -> {
if (!(state instanceof WriteState.Compound compound)) {
if (!(state instanceof WriteState.Compound)) {
throw new NbtWriteException("Names can only appear inside compounds");
}
if (compound.hasPrevious) {
if (state == WriteState.Compound.HAS_PREVIOUS_ENTRY) {
output.append(',');
// Kill the previous flag
replaceLast(new WriteState.Compound(false));
stateStack.removeLast();
stateStack.addLast(WriteState.Compound.DEFAULT);
}
output.append(Elusion.escapeIfNeeded(name)).append(':');
}
Expand All @@ -87,7 +95,7 @@ public void write(Appendable output, LinStream tokens) throws IOException {
if (state instanceof WriteState.WritingArray) {
output.append(',');
} else {
stateStack.addLast(new WriteState.WritingArray());
stateStack.addLast(WriteState.WritingArray.INSTANCE);
}
while (buffer.hasRemaining()) {
output.append(String.valueOf(buffer.get())).append('B');
Expand All @@ -112,7 +120,7 @@ public void write(Appendable output, LinStream tokens) throws IOException {
case LinToken.CompoundStart compoundStart -> {
output.append('{');

stateStack.addLast(new WriteState.Compound(false));
stateStack.addLast(WriteState.Compound.DEFAULT);
}
case LinToken.CompoundEnd compoundEnd -> {
output.append('}');
Expand All @@ -135,7 +143,7 @@ public void write(Appendable output, LinStream tokens) throws IOException {
if (state instanceof WriteState.WritingArray) {
output.append(',');
} else {
stateStack.addLast(new WriteState.WritingArray());
stateStack.addLast(WriteState.WritingArray.INSTANCE);
}
while (buffer.hasRemaining()) {
output.append(String.valueOf(buffer.get()));
Expand Down Expand Up @@ -173,7 +181,7 @@ public void write(Appendable output, LinStream tokens) throws IOException {
if (state instanceof WriteState.WritingArray) {
output.append(',');
} else {
stateStack.addLast(new WriteState.WritingArray());
stateStack.addLast(WriteState.WritingArray.INSTANCE);
}
while (buffer.hasRemaining()) {
output.append(String.valueOf(buffer.get())).append('L');
Expand Down Expand Up @@ -221,13 +229,9 @@ private void handleValueEnd(Appendable output) throws IOException {
output.append(',');
}
}
case WriteState.Compound compound -> stateStack.addLast(new WriteState.Compound(true));
case WriteState.Compound compound -> stateStack.addLast(WriteState.Compound.HAS_PREVIOUS_ENTRY);
default -> throw new NbtWriteException("Unexpected state: " + state);
}
}

private void replaceLast(WriteState state) {
stateStack.removeLast();
stateStack.addLast(state);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ private sealed interface State {
* The cursor should either point to a comma or a closing brace.
* </p>
*/
record InCompound() implements State {
enum InCompound implements State {
INSTANCE
}

/**
Expand All @@ -60,7 +61,8 @@ record InCompound() implements State {
* After this, the cursor will be one character after the colon.
* </p>
*/
record CompoundEntryName() implements State {
enum CompoundEntryName implements State {
INSTANCE
}

/**
Expand All @@ -70,7 +72,8 @@ record CompoundEntryName() implements State {
* The cursor should either point to a comma or a closing bracket.
* </p>
*/
record InList() implements State {
enum InList implements State {
INSTANCE
}

/**
Expand All @@ -80,7 +83,8 @@ record InList() implements State {
* The cursor should always point to the start of a value.
* </p>
*/
record InByteArray() implements State {
enum InByteArray implements State {
INSTANCE
}

/**
Expand All @@ -90,7 +94,8 @@ record InByteArray() implements State {
* The cursor should always point to the start of a value.
* </p>
*/
record InIntArray() implements State {
enum InIntArray implements State {
INSTANCE
}

/**
Expand All @@ -100,14 +105,17 @@ record InIntArray() implements State {
* The cursor should always point to the start of a value.
* </p>
*/
record InLongArray() implements State {
enum InLongArray implements State {
INSTANCE
}

/**
* We need to read a value. Usually, we'll just return the value, and not push a new state, unless we need to
* read a complex value such as a compound or list.
*/
record ReadValue(boolean mustBeCompound) implements State {
enum ReadValue implements State {
ANY,
COMPOUND_ONLY,
}
}

Expand Down Expand Up @@ -135,7 +143,7 @@ record ReadValue(boolean mustBeCompound) implements State {
*/
public LinSnbtReader(Iterator<? extends SnbtTokenWithMetadata> input) {
this.input = input;
this.stateStack = new ArrayDeque<>(List.of(new State.ReadValue(true)));
this.stateStack = new ArrayDeque<>(List.of(State.ReadValue.COMPOUND_ONLY));
this.tokenQueue = new ArrayDeque<>();
this.readAgainStack = new ArrayDeque<>();
}
Expand Down Expand Up @@ -182,7 +190,7 @@ private NbtParseException unexpectedTokenSpecificError(SnbtToken token, String e

private void fillTokenStack(State state) {
switch (state) {
case State.ReadValue(boolean mustBeCompound) -> readValue(mustBeCompound);
case State.ReadValue readValue -> readValue(readValue);
case State.InCompound inCompound -> advanceCompound();
case State.CompoundEntryName compoundEntryName -> readName();
case State.InList inList -> advanceList();
Expand Down Expand Up @@ -211,18 +219,18 @@ private void fillTokenStack(State state) {
}
}

private void readValue(boolean mustBeCompound) {
private void readValue(State.ReadValue readValue) {
// Remove the ReadValue
stateStack.removeLast();
var token = read().token();
if (token instanceof SnbtToken.CompoundStart) {
stateStack.addLast(new State.InCompound());
stateStack.addLast(new State.CompoundEntryName());
stateStack.addLast(State.InCompound.INSTANCE);
stateStack.addLast(State.CompoundEntryName.INSTANCE);
tokenQueue.addLast(new LinToken.CompoundStart());
return;
}

if (mustBeCompound) {
if (readValue == State.ReadValue.COMPOUND_ONLY) {
throw unexpectedTokenSpecificError(token, SnbtToken.CompoundStart.INSTANCE.toString());
}

Expand All @@ -243,7 +251,7 @@ private void advanceCompound() {
stateStack.removeLast();
tokenQueue.addLast(new LinToken.CompoundEnd());
}
case SnbtToken.Separator separator -> stateStack.addLast(new State.CompoundEntryName());
case SnbtToken.Separator separator -> stateStack.addLast(State.CompoundEntryName.INSTANCE);
default -> throw unexpectedTokenError(token);
}
}
Expand All @@ -259,7 +267,7 @@ private void readName() {
if (!(token instanceof SnbtToken.EntrySeparator)) {
throw unexpectedTokenSpecificError(token, SnbtToken.EntrySeparator.INSTANCE.toString());
}
stateStack.addLast(new State.ReadValue(false));
stateStack.addLast(State.ReadValue.ANY);
tokenQueue.addLast(new LinToken.Name(text.content()));
}

Expand All @@ -270,7 +278,7 @@ private void advanceList() {
stateStack.removeLast();
tokenQueue.addLast(new LinToken.ListEnd());
}
case SnbtToken.Separator separator -> stateStack.addLast(new State.ReadValue(false));
case SnbtToken.Separator separator -> stateStack.addLast(State.ReadValue.ANY);
default -> throw unexpectedTokenError(token);
}
}
Expand Down Expand Up @@ -324,23 +332,23 @@ private <T extends Buffer, L extends LinToken> void advanceArray(
private void prepareListLike() {
int initialCharIndex = charIndex;
var typing = read();
if (typing.token() instanceof SnbtToken.Text text && !text.quoted() && text.content().length() == 1) {
if (typing.token() instanceof SnbtToken.Text(boolean quoted, String content) && !quoted && content.length() == 1) {
var separatorCheck = read();
if (separatorCheck.token() instanceof SnbtToken.ListTypeSeparator) {
switch (text.content().charAt(0)) {
switch (content.charAt(0)) {
case 'B' -> {
stateStack.addLast(new State.InByteArray());
stateStack.addLast(State.InByteArray.INSTANCE);
tokenQueue.addLast(new LinToken.ByteArrayStart());
}
case 'I' -> {
stateStack.addLast(new State.InIntArray());
stateStack.addLast(State.InIntArray.INSTANCE);
tokenQueue.addLast(new LinToken.IntArrayStart());
}
case 'L' -> {
stateStack.addLast(new State.InLongArray());
stateStack.addLast(State.InLongArray.INSTANCE);
tokenQueue.addLast(new LinToken.LongArrayStart());
}
default -> throw new NbtParseException(errorPrefix() + "Invalid array type: " + text.content());
default -> throw new NbtParseException(errorPrefix() + "Invalid array type: " + content);
}
return;
}
Expand All @@ -349,8 +357,8 @@ private void prepareListLike() {
readAgainStack.addFirst(typing);
charIndex = initialCharIndex;

stateStack.addLast(new State.InList());
stateStack.addLast(new State.ReadValue(false));
stateStack.addLast(State.InList.INSTANCE);
stateStack.addLast(State.ReadValue.ANY);
tokenQueue.addLast(new LinToken.ListStart());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,19 +114,22 @@ private sealed interface State {
/**
* We need to initialize and return the root name.
*/
record Initial() implements State {
enum Initial implements State {
INSTANCE
}

/**
* We need to return {@link LinToken.CompoundStart}.
*/
record CompoundStart() implements State {
enum CompoundStart implements State {
INSTANCE
}

/**
* We need to give the name of the next entry. We'll load the ID here too.
*/
record CompoundEntryName() implements State {
enum CompoundEntryName implements State {
INSTANCE
}

/**
Expand Down Expand Up @@ -247,7 +250,7 @@ public String decode() throws CharacterCodingException {
*/
public LinNbtReader(DataInput input, LinReadOptions options) {
this.input = input;
this.stateStack = new ArrayDeque<>(List.of(new State.Initial()));
this.stateStack = new ArrayDeque<>(List.of(State.Initial.INSTANCE));
// We only need to check strings if we're allowing normal UTF-8 encoding.
this.stringEncoding = options.allowNormalUtf8Encoding()
? StringEncoding.UNKNOWN : StringEncoding.MODIFIED_UTF_8;
Expand All @@ -262,11 +265,11 @@ public LinNbtReader(DataInput input, LinReadOptions options) {
if (input.readUnsignedByte() != LinTagId.COMPOUND.id()) {
throw new NbtParseException("NBT stream does not start with a compound tag");
}
stateStack.addLast(new State.CompoundStart());
stateStack.addLast(State.CompoundStart.INSTANCE);
yield new LinToken.Name(readUtf(), LinTagId.COMPOUND);
}
case State.CompoundStart compoundStart -> {
stateStack.addLast(new State.CompoundEntryName());
stateStack.addLast(State.CompoundEntryName.INSTANCE);
yield new LinToken.CompoundStart();
}
case State.CompoundEntryName compoundEntryName -> {
Expand All @@ -276,7 +279,7 @@ public LinNbtReader(DataInput input, LinReadOptions options) {
}

// After we read the value, we'll be back at reading the name.
stateStack.addLast(new State.CompoundEntryName());
stateStack.addLast(State.CompoundEntryName.INSTANCE);
stateStack.addLast(new State.ReadValue(id));
yield new LinToken.Name(readUtf(), id);
}
Expand Down Expand Up @@ -345,7 +348,7 @@ private LinToken handleReadValue(LinTagId id) throws IOException {
yield new LinToken.ListStart(size, elementId);
}
case COMPOUND -> {
stateStack.addLast(new State.CompoundEntryName());
stateStack.addLast(State.CompoundEntryName.INSTANCE);
yield new LinToken.CompoundStart();
}
case INT_ARRAY -> {
Expand Down
Loading