mirror of
https://github.com/italicsjenga/valence.git
synced 2024-12-23 22:41:30 +11:00
Support NBT lists of type TAG_End (#181)
In NBT, lists are allowed to have the element type TAG_End iff their length is zero. This adds an explicit `List::End` enum variant to valence_nbt.
This commit is contained in:
parent
2597e92b8f
commit
c9aeda7dbd
|
@ -158,7 +158,7 @@ impl DecodeState<'_, '_> {
|
||||||
fn read_any_list(&mut self) -> Result<List> {
|
fn read_any_list(&mut self) -> Result<List> {
|
||||||
match self.read_tag()? {
|
match self.read_tag()? {
|
||||||
Tag::End => match self.read_int()? {
|
Tag::End => match self.read_int()? {
|
||||||
0 => Ok(List::Byte(vec![])),
|
0 => Ok(List::End),
|
||||||
len => Err(Error::new_owned(format!(
|
len => Err(Error::new_owned(format!(
|
||||||
"TAG_End list with nonzero length of {len}"
|
"TAG_End list with nonzero length of {len}"
|
||||||
))),
|
))),
|
||||||
|
|
|
@ -130,6 +130,7 @@ fn example_compound() -> Compound {
|
||||||
"bar".to_owned(),
|
"bar".to_owned(),
|
||||||
"baz".to_owned()
|
"baz".to_owned()
|
||||||
]),
|
]),
|
||||||
|
"list_of_end" => List::End,
|
||||||
"string" => "aé日",
|
"string" => "aé日",
|
||||||
"compound" => inner(),
|
"compound" => inner(),
|
||||||
"list_of_compound" => List::Compound(vec![
|
"list_of_compound" => List::Compound(vec![
|
||||||
|
|
|
@ -23,7 +23,7 @@ pub fn to_binary_writer<W: Write>(writer: W, compound: &Compound, root_name: &st
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn written_size(compound: &Compound, root_name: &str) -> usize {
|
pub(crate) fn written_size(compound: &Compound, root_name: &str) -> usize {
|
||||||
fn value_len(val: &Value) -> usize {
|
fn value_size(val: &Value) -> usize {
|
||||||
match val {
|
match val {
|
||||||
Value::Byte(_) => 1,
|
Value::Byte(_) => 1,
|
||||||
Value::Short(_) => 2,
|
Value::Short(_) => 2,
|
||||||
|
@ -32,16 +32,17 @@ pub(crate) fn written_size(compound: &Compound, root_name: &str) -> usize {
|
||||||
Value::Float(_) => 4,
|
Value::Float(_) => 4,
|
||||||
Value::Double(_) => 8,
|
Value::Double(_) => 8,
|
||||||
Value::ByteArray(ba) => 4 + ba.len(),
|
Value::ByteArray(ba) => 4 + ba.len(),
|
||||||
Value::String(s) => string_len(s),
|
Value::String(s) => string_size(s),
|
||||||
Value::List(l) => list_len(l),
|
Value::List(l) => list_size(l),
|
||||||
Value::Compound(c) => compound_len(c),
|
Value::Compound(c) => compound_size(c),
|
||||||
Value::IntArray(ia) => 4 + ia.len() * 4,
|
Value::IntArray(ia) => 4 + ia.len() * 4,
|
||||||
Value::LongArray(la) => 4 + la.len() * 8,
|
Value::LongArray(la) => 4 + la.len() * 8,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn list_len(l: &List) -> usize {
|
fn list_size(l: &List) -> usize {
|
||||||
let elems_len = match l {
|
let elems_size = match l {
|
||||||
|
List::End => 0,
|
||||||
List::Byte(b) => b.len(),
|
List::Byte(b) => b.len(),
|
||||||
List::Short(s) => s.len() * 2,
|
List::Short(s) => s.len() * 2,
|
||||||
List::Int(i) => i.len() * 4,
|
List::Int(i) => i.len() * 4,
|
||||||
|
@ -49,28 +50,28 @@ pub(crate) fn written_size(compound: &Compound, root_name: &str) -> usize {
|
||||||
List::Float(f) => f.len() * 4,
|
List::Float(f) => f.len() * 4,
|
||||||
List::Double(d) => d.len() * 8,
|
List::Double(d) => d.len() * 8,
|
||||||
List::ByteArray(ba) => ba.iter().map(|b| 4 + b.len()).sum(),
|
List::ByteArray(ba) => ba.iter().map(|b| 4 + b.len()).sum(),
|
||||||
List::String(s) => s.iter().map(|s| string_len(s)).sum(),
|
List::String(s) => s.iter().map(|s| string_size(s)).sum(),
|
||||||
List::List(l) => l.iter().map(list_len).sum(),
|
List::List(l) => l.iter().map(list_size).sum(),
|
||||||
List::Compound(c) => c.iter().map(compound_len).sum(),
|
List::Compound(c) => c.iter().map(compound_size).sum(),
|
||||||
List::IntArray(i) => i.iter().map(|i| 4 + i.len() * 4).sum(),
|
List::IntArray(i) => i.iter().map(|i| 4 + i.len() * 4).sum(),
|
||||||
List::LongArray(l) => l.iter().map(|l| 4 + l.len() * 8).sum(),
|
List::LongArray(l) => l.iter().map(|l| 4 + l.len() * 8).sum(),
|
||||||
};
|
};
|
||||||
|
|
||||||
1 + 4 + elems_len
|
1 + 4 + elems_size
|
||||||
}
|
}
|
||||||
|
|
||||||
fn string_len(s: &str) -> usize {
|
fn string_size(s: &str) -> usize {
|
||||||
2 + modified_utf8::encoded_len(s)
|
2 + modified_utf8::encoded_len(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compound_len(c: &Compound) -> usize {
|
fn compound_size(c: &Compound) -> usize {
|
||||||
c.iter()
|
c.iter()
|
||||||
.map(|(k, v)| 1 + string_len(k) + value_len(v))
|
.map(|(k, v)| 1 + string_size(k) + value_size(v))
|
||||||
.sum::<usize>()
|
.sum::<usize>()
|
||||||
+ 1
|
+ 1
|
||||||
}
|
}
|
||||||
|
|
||||||
1 + string_len(root_name) + compound_len(compound)
|
1 + string_size(root_name) + compound_size(compound)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EncodeState<W> {
|
struct EncodeState<W> {
|
||||||
|
@ -166,6 +167,12 @@ impl<W: Write> EncodeState<W> {
|
||||||
|
|
||||||
fn write_any_list(&mut self, list: &List) -> Result<()> {
|
fn write_any_list(&mut self, list: &List) -> Result<()> {
|
||||||
match list {
|
match list {
|
||||||
|
List::End => {
|
||||||
|
self.write_tag(Tag::End)?;
|
||||||
|
// Length
|
||||||
|
self.writer.write_i32::<BigEndian>(0)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
List::Byte(bl) => {
|
List::Byte(bl) => {
|
||||||
self.write_tag(Tag::Byte)?;
|
self.write_tag(Tag::Byte)?;
|
||||||
|
|
||||||
|
@ -204,7 +211,7 @@ impl<W: Write> EncodeState<W> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_list<T, F>(&mut self, list: &Vec<T>, elem_type: Tag, mut write_elem: F) -> Result<()>
|
fn write_list<T, F>(&mut self, list: &[T], elem_type: Tag, mut write_elem: F) -> Result<()>
|
||||||
where
|
where
|
||||||
F: FnMut(&mut Self, &T) -> Result<()>,
|
F: FnMut(&mut Self, &T) -> Result<()>,
|
||||||
{
|
{
|
||||||
|
|
|
@ -33,6 +33,8 @@ pub enum Value {
|
||||||
/// heterogeneous lists are unrepresentable.
|
/// heterogeneous lists are unrepresentable.
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
pub enum List {
|
pub enum List {
|
||||||
|
/// The list with the element type of `TAG_End` and length of zero.
|
||||||
|
End,
|
||||||
Byte(Vec<i8>),
|
Byte(Vec<i8>),
|
||||||
Short(Vec<i16>),
|
Short(Vec<i16>),
|
||||||
Int(Vec<i32>),
|
Int(Vec<i32>),
|
||||||
|
@ -51,6 +53,7 @@ impl List {
|
||||||
/// Returns the length of this list.
|
/// Returns the length of this list.
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
|
List::End => 0,
|
||||||
List::Byte(l) => l.len(),
|
List::Byte(l) => l.len(),
|
||||||
List::Short(l) => l.len(),
|
List::Short(l) => l.len(),
|
||||||
List::Int(l) => l.len(),
|
List::Int(l) => l.len(),
|
||||||
|
|
Loading…
Reference in a new issue