Merge pull request 'Fix #2: Implement Serialization' (#5) from feat/2 into main

Reviewed-on: #5
This commit is contained in:
zontreck 2024-05-05 06:28:45 +00:00
commit 3a3c5f5822
19 changed files with 527 additions and 198 deletions

View file

@ -1,4 +1,18 @@
import 'package:libac_flutter/nbt/impl/ByteArrayTag.dart';
import 'package:libac_flutter/nbt/impl/CompoundTag.dart';
import 'package:libac_flutter/nbt/impl/DoubleTag.dart';
import 'package:libac_flutter/nbt/impl/EndTag.dart';
import 'package:libac_flutter/nbt/impl/FloatTag.dart';
import 'package:libac_flutter/nbt/impl/IntArrayTag.dart';
import 'package:libac_flutter/nbt/impl/IntTag.dart';
import 'package:libac_flutter/nbt/impl/LongTag.dart';
import 'package:libac_flutter/nbt/impl/ShortTag.dart';
import 'Stream.dart';
import 'impl/ByteTag.dart';
import 'impl/ListTag.dart';
import 'impl/LongArrayTag.dart';
import 'impl/StringTag.dart';
enum TagType {
End(0),
@ -17,6 +31,16 @@ enum TagType {
final int byte;
const TagType(this.byte);
static TagType get(int byte) {
for (TagType type in values) {
if (type.byte == byte) {
return type;
}
}
return TagType.End;
}
}
abstract class Tag {
@ -27,4 +51,180 @@ abstract class Tag {
TagType getTagType();
void writeValue(ByteLayer data);
void readValue(ByteLayer data);
String? _key;
String getKey() {
return (_key == null ? "" : _key!);
}
static Tag readNamedTag(ByteLayer data) {
var type = data.readByte();
if (type == 0) {
return EndTag();
} else {
Tag tag = makeTagOfType(TagType.get(type));
tag._key = data.readString();
tag.readValue(data);
return tag;
}
}
static void writeNamedTag(Tag tag, ByteLayer data) {
data.writeByte(tag.getType());
if (tag.getType() != 0) {
data.writeString(tag.getKey());
tag.writeValue(data);
}
}
bool equals(dynamic object) {
if (object == null || object is! Tag) return false;
Tag tag = object;
if (tag.getType() != getType()) return false;
if (!(getKey() == tag.getKey())) return false;
return true;
}
static Tag makeTagOfType(TagType type) {
switch (type) {
case TagType.Byte:
{
return ByteTag();
}
case TagType.ByteArray:
{
return ByteArrayTag();
}
case TagType.Compound:
{
return CompoundTag();
}
case TagType.Double:
{
return DoubleTag();
}
case TagType.End:
{
return EndTag();
}
case TagType.Short:
{
return ShortTag();
}
case TagType.Int:
{
return IntTag();
}
case TagType.Long:
{
return LongTag();
}
case TagType.Float:
{
return FloatTag();
}
case TagType.IntArray:
{
return IntArrayTag();
}
case TagType.LongArray:
{
return LongArrayTag();
}
case TagType.List:
{
return ListTag();
}
case TagType.String:
{
return StringTag();
}
}
}
int asByte() {
if (this is ByteTag) {
return (this as ByteTag).value;
} else {
return 0;
}
}
List<int> asByteArray() {
if (this is ByteArrayTag) {
return (this as ByteArrayTag).value;
} else {
return [];
}
}
double asDouble() {
if (this is DoubleTag) {
return (this as DoubleTag).value;
} else {
return 0.0;
}
}
double asFloat() {
if (this is FloatTag) {
return (this as FloatTag).value;
} else {
return 0.0;
}
}
List<int> asIntArray() {
if (this is IntArrayTag) {
return (this as IntArrayTag).value;
} else {
return [];
}
}
int asInt() {
if (this is IntTag) {
return (this as IntTag).value;
} else {
return 0;
}
}
List<int> asLongArray() {
if (this is LongArrayTag) {
return (this as LongArrayTag).value;
} else {
return [];
}
}
int asLong() {
if (this is LongTag) {
return (this as LongTag).value;
} else {
return 0;
}
}
int asShort() {
if (this is ShortTag) {
return (this as ShortTag).value;
} else {
return 0;
}
}
String asString() {
if (this is StringTag) {
return (this as StringTag).value;
} else {
return "";
}
}
}

View file

@ -0,0 +1,37 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class ByteArrayTag extends Tag {
final List<int> value = [];
ByteArrayTag();
ByteArrayTag._(List<int> value) {
this.value.addAll(value);
}
static ByteArrayTag valueOf(List<int> value) {
return ByteArrayTag._(value);
}
@override
void readValue(ByteLayer data) {
int len = data.readInt();
for (int i = 0; i < len; i++) {
value.add(data.readByte());
}
}
@override
void writeValue(ByteLayer data) {
data.writeInt(value.length);
for (int i in value) {
data.writeByte(i);
}
}
@override
TagType getTagType() {
return TagType.ByteArray;
}
}

View file

@ -2,18 +2,26 @@ import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class ByteTag extends Tag {
final int value;
int value = 0;
ByteTag({required this.value});
ByteTag._(int value) {
this.value = value;
}
ByteTag();
static ByteTag valueOf(int value) {
return ByteTag._(value);
}
@override
void readValue(ByteLayer data) {
// TODO: implement readValue
value = data.readByte();
}
@override
void writeValue(ByteLayer data) {
// TODO: implement writeValue
data.writeByte(value);
}
@override

View file

@ -0,0 +1,60 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class CompoundTag extends Tag {
late final Map<String, Tag> value = {};
CompoundTag();
@override
void readValue(ByteLayer data) {
value.clear();
while (true) {
Tag tag = Tag.readNamedTag(data);
if (tag.getType() == 0) {
return;
}
put(tag.getKey(), tag);
}
}
@override
void writeValue(ByteLayer data) {
Iterator<Tag> it = value.values.iterator;
while (it.moveNext()) {
Tag tag = it.current;
Tag.writeNamedTag(tag, data);
}
data.writeByte(TagType.End.byte);
}
void put(String name, Tag tag) {
value[name] = tag;
}
bool contains(String name) {
return value.containsKey(name);
}
Tag? get(String name) {
if (contains(name)) {
return value[name] as Tag;
} else {
// Does not exist!
return null;
}
}
void remove(String name) {
value.remove(name);
}
@override
TagType getTagType() {
return TagType.Compound;
}
}

View file

@ -1,18 +1,27 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class TagDouble extends Tag {
final double value;
TagDouble({required this.value});
class DoubleTag extends Tag {
double value = 0.0;
DoubleTag();
DoubleTag._(double value) {
this.value = value;
}
static DoubleTag valueOf(double value) {
return DoubleTag._(value);
}
@override
void readValue(ByteLayer data) {
// TODO: implement readValue
value = data.readDouble();
}
@override
void writeValue(ByteLayer data) {
// TODO: implement writeValue
data.writeDouble(value);
}
@override

View file

@ -1,8 +1,8 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class TagEnd extends Tag {
TagEnd();
class EndTag extends Tag {
EndTag();
@override
void readValue(ByteLayer data) {}

View file

@ -1,18 +1,26 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class TagFloat extends Tag {
final double value;
TagFloat({required this.value});
class FloatTag extends Tag {
double value = 0.0;
FloatTag();
FloatTag._(double value) {
this.value = value;
}
static FloatTag valueOf(double value) {
return FloatTag._(value);
}
@override
void readValue(ByteLayer data) {
// TODO: implement readValue
value = data.readFloat();
}
@override
void writeValue(ByteLayer data) {
// TODO: implement writeValue
data.writeFloat(value);
}
@override

View file

@ -0,0 +1,32 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class IntArrayTag extends Tag {
final List<int> value = [];
IntArrayTag();
IntArrayTag._(List<int> value) {
this.value.addAll(value);
}
@override
void readValue(ByteLayer data) {
int count = data.readInt();
for (int i = 0; i < count; i++) {
value.add(data.readInt());
}
}
@override
void writeValue(ByteLayer data) {
data.writeInt(value.length);
for (int i in value) {
data.writeInt(i);
}
}
@override
TagType getTagType() {
return TagType.IntArray;
}
}

View file

@ -1,18 +1,26 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class TagInt extends Tag {
final int value;
TagInt({required this.value});
class IntTag extends Tag {
int value = 0;
IntTag();
IntTag._(int value) {
this.value = value;
}
static IntTag valueOf(int value) {
return IntTag._(value);
}
@override
void readValue(ByteLayer data) {
// TODO: implement readValue
value = data.readInt();
}
@override
void writeValue(ByteLayer data) {
// TODO: implement writeValue
data.writeInt(value);
}
@override

65
lib/nbt/impl/ListTag.dart Normal file
View file

@ -0,0 +1,65 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class ListTag extends Tag {
List<Tag> value = [];
ListTag();
@override
void readValue(ByteLayer data) {
TagType type = TagType.get(data.readByte());
int size = data.readInt();
for (int i = 0; i < size; i++) {
Tag tag = Tag.makeTagOfType(type);
tag.readValue(data);
add(tag);
}
}
@override
void writeValue(ByteLayer data) {
TagType type = TagType.End;
if (size() > 0) {
type = value[0].getTagType();
}
data.writeByte(type.byte);
data.writeInt(size());
for (int i = 0; i < size(); i++) {
value[i].writeValue(data);
}
}
void add(Tag tag) {
TagType type = TagType.End;
if (size() > 0) {
type = value[0].getTagType();
}
if (type == TagType.End || type == tag.getTagType()) {
value.add(tag);
}
}
void remove(Tag tag) {
value.remove(tag);
}
void removeAt(int index) {
value.removeAt(index);
}
int indexOf(Tag tag) {
return value.indexOf(tag);
}
@override
TagType getTagType() {
return TagType.List;
}
int size() {
return value.length;
}
}

View file

@ -0,0 +1,40 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class LongArrayTag extends Tag {
final List<int> value = [];
LongArrayTag();
LongArrayTag._(List<int> lst) {
value.addAll(lst);
}
static LongArrayTag valueOf(List<int> value) {
return LongArrayTag._(value);
}
@override
void readValue(ByteLayer data) {
int count = data.readInt();
for (int i = 0; i < count; i++) {
value.add(data.readLong());
}
}
@override
void writeValue(ByteLayer data) {
data.writeInt(size());
for (int i in value) {
data.writeLong(i);
}
}
int size() {
return value.length;
}
@override
TagType getTagType() {
return TagType.LongArray;
}
}

View file

@ -1,18 +1,26 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class TagLong extends Tag {
final int value;
TagLong({required this.value});
class LongTag extends Tag {
int value = 0;
LongTag();
LongTag._(int value) {
this.value = value;
}
static LongTag valueOf(int value) {
return LongTag._(value);
}
@override
void readValue(ByteLayer data) {
// TODO: implement readValue
value = data.readLong();
}
@override
void writeValue(ByteLayer data) {
// TODO: implement writeValue
data.writeLong(value);
}
@override

View file

@ -1,18 +1,26 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class TagShort extends Tag {
final int value;
TagShort({required this.value});
class ShortTag extends Tag {
int value = 0;
ShortTag();
ShortTag._(int value) {
this.value = value;
}
static ShortTag valueOf(int value) {
return ShortTag._(value);
}
@override
void readValue(ByteLayer data) {
// TODO: implement readValue
value = data.readShort();
}
@override
void writeValue(ByteLayer data) {
// TODO: implement writeValue
data.writeShort(value);
}
@override

View file

@ -1,18 +1,26 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class TagString extends Tag {
final String value;
TagString({required this.value});
class StringTag extends Tag {
String value = "";
StringTag();
StringTag._(String str) {
value = str;
}
static StringTag valueOf(String str) {
return StringTag._(str);
}
@override
void readValue(ByteLayer data) {
// TODO: implement readValue
value = data.readString();
}
@override
void writeValue(ByteLayer data) {
// TODO: implement writeValue
data.writeString(value);
}
@override

View file

@ -1,22 +0,0 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class TagByteArray extends Tag {
final List<int> value;
TagByteArray({required this.value});
@override
void readValue(ByteLayer data) {
// TODO: implement readValue
}
@override
void writeValue(ByteLayer data) {
// TODO: implement writeValue
}
@override
TagType getTagType() {
return TagType.ByteArray;
}
}

View file

@ -1,46 +0,0 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class TagCompound extends Tag {
late final Map<String, Tag> _value;
TagCompound() {
_value = new Map();
}
@override
void readValue(ByteLayer data) {
// TODO: implement readValue
}
@override
void writeValue(ByteLayer data) {
// TODO: implement writeValue
}
void put(String name, Tag tag) {
_value[name] = tag;
}
bool contains(String name) {
return _value.containsKey(name);
}
Tag? get(String name) {
if (contains(name))
return _value[name] as Tag;
else {
// Does not exist!
return null;
}
}
void remove(String name) {
_value.remove(name);
}
@override
TagType getTagType() {
return TagType.Compound;
}
}

View file

@ -1,22 +0,0 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class TagIntArray extends Tag {
final List<int> value;
TagIntArray({required this.value});
@override
void readValue(ByteLayer data) {
// TODO: implement readValue
}
@override
void writeValue(ByteLayer data) {
// TODO: implement writeValue
}
@override
TagType getTagType() {
return TagType.IntArray;
}
}

View file

@ -1,50 +0,0 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class TagList extends Tag {
late final List<Tag> _value;
TagType _internalType = TagType.End;
TagList() {
_value = List.empty(growable: true);
}
@override
void readValue(ByteLayer data) {
// TODO: implement readValue
}
@override
void writeValue(ByteLayer data) {
// TODO: implement writeValue
}
void add(Tag tag) {
if (_internalType == TagType.End) {
_value.clear();
_value.add(tag);
_internalType = tag.getTagType();
} else {
if (_internalType == tag.getTagType()) {
_value.add(tag);
}
}
}
void remove(Tag tag) {
_value.remove(tag);
}
void removeAt(int index) {
_value.removeAt(index);
}
int indexOf(Tag tag) {
return _value.indexOf(tag);
}
@override
TagType getTagType() {
return TagType.List;
}
}

View file

@ -1,22 +0,0 @@
import 'package:libac_flutter/nbt/Stream.dart';
import 'package:libac_flutter/nbt/Tag.dart';
class TagLongArray extends Tag {
final List<int> value;
TagLongArray({required this.value});
@override
void readValue(ByteLayer data) {
// TODO: implement readValue
}
@override
void writeValue(ByteLayer data) {
// TODO: implement writeValue
}
@override
TagType getTagType() {
return TagType.LongArray;
}
}