使用swift枚举对数据建模

5t7ly7z5  于 2023-02-18  发布在  Swift
关注(0)|答案(1)|浏览(120)

这更多的是一个软件设计而不是编码的问题,但这不总是真正的难题吗?无论如何,我正在尝试建模Minecraft的NBT格式,以读取/写入其保存文件.
我确信使用枚举是最好的选择:只有有限的几种情况是用户不能改变的,所有的情况都需要处理,而且,正如你将在下面看到的,一个有问题的情况是很难用任何其他方式建模的。
当然,NBT数据可以是嵌套的,也可以包含任何一种NBT类型的列表。这包括列表的列表,其中[[Int],[Double]]是法律的的(包含的类型都是列表,NBT不会强制任何超出这一点的类型)。基本上,一个列表只能包含一种标记类型,但是任何类型的列表都被认为是同一类型。
是的,存储某些类型数组的重复方式是规范的一部分。[Int8]可以存储为byteArrayList<Byte>,这是预期的。因此,前面也使用了单词List而不是Array:这是NBT中两个不同但相似的东西。
现在我已经编写了这个代码,它运行得非常好,但我担心可能有一些明显的设计缺陷,我没有足够的经验来注意到:

public enum Tag : Equatable {
    
    case end
    case byte(Int8)
    case short(Int16)
    case int(Int32)
    case long(Int64)
    case float(Float)
    case double(Double)
    case byteArray([Int8])
    case string(String)
    case list(TagList)
    case compound([String : Tag])
    case intArray([Int32])
    case longArray([Int64])
}

public enum TagList : Equatable {

    case end
    case byte([Int8])
    case short([Int16])
    case int([Int32])
    case long([Int64])
    case float([Float])
    case double([Double])
    case byteArray([[Int8]])
    case string([String])
    case list([List])
    case compound([[String : Tag]])
    case intArray([[Int32]])
    case longArray([[Int64]])
}

有没有更明智的方法来做到这一点?我真的不喜欢重复基本相同的枚举两次,但由于Tag.List.list的情况下,他们不能合并(因为有一个列表的列表,列表必须与其余的定义分开)。

gk7wooem

gk7wooem1#

我不太了解这个领域,但你能做一些像这样的事情吗:

public enum TagStyle<T> {
    .value(T)
    .list([T])
}

public enum Tag : Equatable {

    case end
    case byte(TagStyle<Int8>)
    case short(TagStyle<Int16>)
    case int(TagStyle<Int32>)
    case long(TagStyle<Int64>)
    case float(TagStyle<Float>)
    case double(TagStyle<Double>)
    case byteArray(TagStyle<Data>)
    case string(TagStyle<String>)
    case list(TagStyle<List>)
    case compound(TagStyle<[String : Tag]>)
    case intArray(TagStyle<[Int32]>)
    case longArray(TagStyle<[Int64]>)
}

相关问题