diff options
| author | mat <github@matdoes.dev> | 2021-12-08 00:41:42 -0600 |
|---|---|---|
| committer | mat <github@matdoes.dev> | 2021-12-08 00:41:42 -0600 |
| commit | c16d55ccddd741057bf532bd946b2854dc208c65 (patch) | |
| tree | e6ae8af47e1931ef98ea55913831197b8e65a7ee /minecraft-protocol/src/mc_buf.rs | |
| parent | 4a44c58444c901d939a8594669c819ab2bfbac13 (diff) | |
| download | azalea-drasl-c16d55ccddd741057bf532bd946b2854dc208c65.tar.xz | |
start adding minecraft-chat
Diffstat (limited to 'minecraft-protocol/src/mc_buf.rs')
| -rw-r--r-- | minecraft-protocol/src/mc_buf.rs | 48 |
1 files changed, 43 insertions, 5 deletions
diff --git a/minecraft-protocol/src/mc_buf.rs b/minecraft-protocol/src/mc_buf.rs index 1e6e5b08..a58905b7 100644 --- a/minecraft-protocol/src/mc_buf.rs +++ b/minecraft-protocol/src/mc_buf.rs @@ -33,14 +33,14 @@ pub fn write_bytes(buf: &mut Vec<u8>, bytes: &[u8]) { /// Read a single varint from the reader and return the value, along with the number of bytes read pub async fn read_varint<T: AsyncRead + std::marker::Unpin>( buf: &mut BufReader<T>, -) -> Result<(u32, u8), String> { +) -> Result<(i32, u8), String> { let mut buffer = [0]; let mut ans = 0; for i in 0..4 { buf.read_exact(&mut buffer) .await .or_else(|_| Err("Invalid VarInt".to_string()))?; - ans |= ((buffer[0] & 0b0111_1111) as u32) << 7 * i; + ans |= ((buffer[0] & 0b0111_1111) as i32) << 7 * i; if buffer[0] & 0b1000_0000 == 0 { return Ok((ans, i + 1)); } @@ -48,14 +48,14 @@ pub async fn read_varint<T: AsyncRead + std::marker::Unpin>( Ok((ans, 5)) } -pub fn write_varint(buf: &mut Vec<u8>, mut value: u32) { +pub fn write_varint(buf: &mut Vec<u8>, mut value: i32) { let mut buffer = [0]; if value == 0 { buf.write(&buffer).unwrap(); } while value != 0 { buffer[0] = (value & 0b0111_1111) as u8; - value = (value >> 7) & (u32::max_value() >> 6); + value = (value >> 7) & (i32::max_value() >> 6); if value != 0 { buffer[0] |= 0b1000_0000; } @@ -104,10 +104,48 @@ pub fn write_utf_with_len(buf: &mut Vec<u8>, string: &String, len: usize) { len ); } - write_varint(buf, string.len() as u32); + write_varint(buf, string.len() as i32); write_bytes(buf, string.as_bytes()); } +pub async fn read_utf<T: AsyncRead + std::marker::Unpin>( + buf: &mut BufReader<T>, + max_length: u32, +) -> Result<String, String> { + let (length, length_varint_length) = read_varint(buf).await?; + // i don't know why it's multiplied by 4 but it's like that in mojang's code so + if length < 0 { + return Err( + "The received encoded string buffer length is less than zero! Weird string!" + .to_string(), + ); + } + if length as u32 > max_length * 4 { + return Err(format!( + "The received encoded string buffer length is longer than maximum allowed ({} > {})", + length, + max_length * 4 + )); + } + + // this is probably quite inefficient, idk how to do it better + let mut string = String::new(); + let mut buffer = vec![0; length as usize]; + buf.read_exact(&mut buffer) + .await + .or_else(|_| Err("Invalid UTF-8".to_string()))?; + + string.push_str(std::str::from_utf8(&buffer).unwrap()); + if string.len() > length as usize { + return Err(format!( + "The received string length is longer than maximum allowed ({} > {})", + length, max_length + )); + } + + Ok(string) +} + pub fn write_utf(buf: &mut Vec<u8>, string: &String) { write_utf_with_len(buf, string, MAX_STRING_LENGTH as usize); } |
