[Protocol] Add latin1 string decoder for gamespy1

This commit is contained in:
Douile 2023-08-21 17:56:03 +01:00 committed by Douile
parent 5bd609af72
commit e2414b197e
No known key found for this signature in database
GPG key ID: D94ABB9BCCB5A6EA
3 changed files with 35 additions and 2 deletions

View file

@ -29,6 +29,7 @@ byteorder = "1.4"
bzip2-rs = "0.1"
crc32fast = "1.3"
serde_json = "1.0"
encoding = "0.2"
serde = { version = "1.0", optional = true }

View file

@ -4,6 +4,8 @@ use crate::GDResult;
use byteorder::{BigEndian, ByteOrder, LittleEndian};
use std::{convert::TryInto, marker::PhantomData};
use encoding::{DecoderTrap, Encoding};
/// A struct representing a buffer with a specific byte order.
///
/// It's comprised of a byte slice that it reads from, a cursor to keep track of
@ -320,6 +322,36 @@ pub trait StringDecoder {
fn decode_string(data: &[u8], cursor: &mut usize, delimiter: Self::Delimiter) -> GDResult<String>;
}
pub struct Latin1Decoder;
impl StringDecoder for Latin1Decoder {
type Delimiter = [u8; 1];
const DELIMITER: Self::Delimiter = [0x00];
fn decode_string(data: &[u8], cursor: &mut usize, delimiter: Self::Delimiter) -> GDResult<String> {
// Find the position of the delimiter in the data. If the delimiter is not
// found, the length of the data is returned.
let position = data
// Create an iterator over the data.
.iter()
// Find the position of the delimiter
.position(|&b| b == delimiter.as_ref()[0])
// If the delimiter is not found, use the whole data slice.
.unwrap_or(data.len());
let result = encoding::all::ISO_8859_1
.decode(&data[.. position], DecoderTrap::Strict)
.map_err(|e| PacketBad.context(e))?;
// Update the cursor position
// The +1 is to skip the delimiter
*cursor += position + 1;
Ok(result)
}
}
/// A decoder for UTF-8 encoded strings.
///
/// This decoder uses a single null byte (`0x00`) as the default delimiter.

View file

@ -1,6 +1,6 @@
use byteorder::LittleEndian;
use crate::buffer::Utf8Decoder;
use crate::buffer::Latin1Decoder;
use crate::protocols::gamespy::common::has_password;
use crate::GDErrorKind::TypeParse;
@ -46,7 +46,7 @@ fn get_server_values_impl(socket: &mut UdpSocket) -> GDResult<HashMap<String, St
let data = socket.receive(None)?;
let mut bufferer = Buffer::<LittleEndian>::new(&data);
let mut as_string = bufferer.read_string::<Utf8Decoder>(None)?;
let mut as_string = bufferer.read_string::<Latin1Decoder>(None)?;
as_string.remove(0);
let splited: Vec<String> = as_string.split('\\').map(str::to_string).collect();