1
2
Fork 0
mirror of https://github.com/mat-1/azalea.git synced 2025-08-02 06:16:04 +00:00

vroom vroom

This commit is contained in:
mat 2022-04-22 22:38:42 -05:00
parent 3057ae8b4a
commit 3a6810ca1d
2 changed files with 250 additions and 77 deletions

View file

@ -12,14 +12,171 @@ fn write_string(writer: &mut dyn Write, string: &str) -> Result<(), Error> {
Ok(())
}
// who needs friends when you've got code that runs in nanoseconds?
#[inline]
fn write_compound(writer: &mut dyn Write, value: &HashMap<String, Tag>) -> Result<(), Error> {
fn write_compound(
writer: &mut dyn Write,
value: &HashMap<String, Tag>,
end_tag: bool,
) -> Result<(), Error> {
for (key, tag) in value {
writer.write_u8(tag.id())?;
write_string(writer, key)?;
tag.write_without_end(writer)?;
match tag {
Tag::End => {}
Tag::Byte(value) => {
writer.write_u8(1)?;
write_string(writer, key)?;
writer.write_i8(*value)?
}
Tag::Short(value) => {
writer.write_u8(2)?;
write_string(writer, key)?;
writer.write_i16::<BE>(*value)?
}
Tag::Int(value) => {
writer.write_u8(3)?;
write_string(writer, key)?;
writer.write_i32::<BE>(*value)?
}
Tag::Long(value) => {
writer.write_u8(4)?;
write_string(writer, key)?;
writer.write_i64::<BE>(*value)?
}
Tag::Float(value) => {
writer.write_u8(5)?;
write_string(writer, key)?;
writer.write_f32::<BE>(*value)?
}
Tag::Double(value) => {
writer.write_u8(6)?;
write_string(writer, key)?;
writer.write_f64::<BE>(*value)?
}
Tag::ByteArray(value) => {
writer.write_u8(7)?;
write_string(writer, key)?;
writer.write_i32::<BE>(value.len() as i32)?;
for &byte in value {
writer.write_i8(byte)?;
}
}
Tag::String(value) => {
writer.write_u8(9)?;
write_string(writer, key)?;
write_string(writer, value)?
}
Tag::List(value) => {
writer.write_u8(10)?;
write_string(writer, key)?;
write_list(writer, value)?
}
Tag::Compound(value) => {
writer.write_u8(11)?;
write_string(writer, key)?;
write_compound(writer, value, true)?
}
Tag::IntArray(value) => {
writer.write_u8(12)?;
write_string(writer, key)?;
writer.write_i32::<BE>(value.len() as i32)?;
for &int in value {
writer.write_i32::<BE>(int)?;
}
}
Tag::LongArray(value) => {
writer.write_u8(13)?;
write_string(writer, key)?;
writer.write_i32::<BE>(value.len() as i32)?;
for &long in value {
writer.write_i64::<BE>(long)?;
}
}
}
}
if end_tag {
writer.write_u8(Tag::End.id())?;
}
return Ok(());
}
#[inline]
fn write_list(writer: &mut dyn Write, value: &Vec<Tag>) -> Result<(), Error> {
// we just get the type from the first item, or default the type to END
if value.is_empty() {
writer.write_all(&[0; 5])?;
} else {
let first_tag = &value[0];
writer.write_u8(first_tag.id())?;
writer.write_i32::<BE>(value.len() as i32)?;
match first_tag {
Tag::Int(_) => {
// assert all items are the same variant
// assert_eq!(value.iter().all(|tag| tag.id() == 1), true);
for i in value {
assert!(matches!(i, Tag::Int(_)));
writer.write_i32::<BE>(
*i.as_int().expect("List of Int should only contains Int"),
)?;
}
}
Tag::String(_) => {
for i in value {
assert!(matches!(i, Tag::String(_)));
write_string(
writer,
i.as_string()
.expect("List of String should only contain String"),
)?;
}
}
Tag::Compound(_) => {
for i in value {
assert!(matches!(i, Tag::Compound(_)));
write_compound(
writer,
i.as_compound()
.expect("List of Compound should only contain Compound"),
true,
)?;
}
}
_ => {
for i in value {
i.write_without_end(writer)?;
}
}
}
}
Ok(())
}
#[inline]
fn write_bytearray(writer: &mut dyn Write, value: &Vec<i8>) -> Result<(), Error> {
writer.write_i32::<BE>(value.len() as i32)?;
for &byte in value {
writer.write_i8(byte)?;
}
Ok(())
}
#[inline]
fn write_intarray(writer: &mut dyn Write, value: &Vec<i32>) -> Result<(), Error> {
writer.write_i32::<BE>(value.len() as i32)?;
for &int in value {
writer.write_i32::<BE>(int)?;
}
Ok(())
}
#[inline]
fn write_longarray(writer: &mut dyn Write, value: &Vec<i64>) -> Result<(), Error> {
writer.write_i32::<BE>(value.len() as i32)?;
for &long in value {
writer.write_i64::<BE>(long)?;
}
writer.write_u8(Tag::End.id())?;
Ok(())
}
@ -34,73 +191,12 @@ impl Tag {
Tag::Long(value) => writer.write_i64::<BE>(*value)?,
Tag::Float(value) => writer.write_f32::<BE>(*value)?,
Tag::Double(value) => writer.write_f64::<BE>(*value)?,
Tag::ByteArray(value) => {
writer.write_i32::<BE>(value.len() as i32)?;
for &byte in value {
writer.write_i8(byte)?;
}
}
Tag::String(value) => {
write_string(writer, value)?;
}
Tag::List(value) => {
// we just get the type from the first item, or default the type to END
if value.is_empty() {
writer.write_all(&[0; 5])?;
} else {
let first_tag = &value[0];
writer.write_u8(first_tag.id())?;
writer.write_i32::<BE>(value.len() as i32)?;
match first_tag {
Self::Int(_) => {
for i in value {
assert!(matches!(i, Tag::Int(_)));
writer.write_i32::<BE>(
*i.as_int().expect("List of Int should only contains Int"),
)?;
}
}
Self::String(_) => {
for i in value {
assert!(matches!(i, Tag::String(_)));
write_string(
writer,
i.as_string()
.expect("List of String should only contain String"),
)?;
}
}
Self::Compound(_) => {
for i in value {
assert!(matches!(i, Tag::Compound(_)));
write_compound(
writer,
i.as_compound()
.expect("List of Compound should only contain Compound"),
)?;
}
}
_ => {
for tag in value {
tag.write_without_end(writer)?;
}
}
}
}
}
Tag::Compound(value) => write_compound(writer, value)?,
Tag::IntArray(value) => {
writer.write_i32::<BE>(value.len() as i32)?;
for &int in value {
writer.write_i32::<BE>(int)?;
}
}
Tag::LongArray(value) => {
writer.write_i32::<BE>(value.len() as i32)?;
for &long in value {
writer.write_i64::<BE>(long)?;
}
}
Tag::ByteArray(value) => write_bytearray(writer, value)?,
Tag::String(value) => write_string(writer, value)?,
Tag::List(value) => write_list(writer, value)?,
Tag::Compound(value) => write_compound(writer, value, true)?,
Tag::IntArray(value) => write_intarray(writer, value)?,
Tag::LongArray(value) => write_longarray(writer, value)?,
}
Ok(())
@ -109,11 +205,7 @@ impl Tag {
pub fn write(&self, writer: &mut impl Write) -> Result<(), Error> {
match self {
Tag::Compound(value) => {
for (key, tag) in value {
writer.write_u8(tag.id())?;
write_string(writer, key)?;
tag.write_without_end(writer)?;
}
write_compound(writer, value, false)?;
Ok(())
}
_ => Err(Error::InvalidTag),

View file

@ -37,6 +37,24 @@ impl Tag {
}
}
#[inline]
pub fn as_byte(&self) -> Option<&i8> {
if let Tag::Byte(v) = self {
Some(v)
} else {
None
}
}
#[inline]
pub fn as_short(&self) -> Option<&i16> {
if let Tag::Short(v) = self {
Some(v)
} else {
None
}
}
#[inline]
pub fn as_int(&self) -> Option<&i32> {
if let Tag::Int(v) = self {
@ -46,6 +64,33 @@ impl Tag {
}
}
#[inline]
pub fn as_long(&self) -> Option<&i64> {
if let Tag::Long(v) = self {
Some(v)
} else {
None
}
}
#[inline]
pub fn as_float(&self) -> Option<&f32> {
if let Tag::Float(v) = self {
Some(v)
} else {
None
}
}
#[inline]
pub fn as_double(&self) -> Option<&f64> {
if let Tag::Double(v) = self {
Some(v)
} else {
None
}
}
#[inline]
pub fn as_string(&self) -> Option<&str> {
if let Tag::String(v) = self {
@ -63,4 +108,40 @@ impl Tag {
None
}
}
#[inline]
pub fn as_bytearray(&self) -> Option<&Vec<i8>> {
if let Tag::ByteArray(v) = self {
Some(v)
} else {
None
}
}
#[inline]
pub fn as_intarray(&self) -> Option<&Vec<i32>> {
if let Tag::IntArray(v) = self {
Some(v)
} else {
None
}
}
#[inline]
pub fn as_longarray(&self) -> Option<&Vec<i64>> {
if let Tag::LongArray(v) = self {
Some(v)
} else {
None
}
}
#[inline]
pub fn as_list(&self) -> Option<&Vec<Tag>> {
if let Tag::List(v) = self {
Some(v)
} else {
None
}
}
}