use crate::rdp::error::RdpError;
use byteorder::ReadBytesExt;
use memchr::memchr;
use nom7::{Err, IResult, Needed};
use std::io::Cursor;
use widestring::U16CString;
pub fn le_slice_to_string(input: &[u8]) -> Result<String, Box<dyn std::error::Error>> {
let mut vec = Vec::new();
let mut cursor = Cursor::new(input);
while let Ok(x) = cursor.read_u16::<byteorder::LittleEndian>() {
if x == 0 {
break;
}
vec.push(x);
}
match U16CString::new(vec) {
Ok(x) => match x.to_string() {
Ok(x) => Ok(x),
Err(e) => Err(e.into()),
},
Err(e) => Err(e.into()),
}
}
pub fn utf7_slice_to_string(input: &[u8]) -> Result<String, Box<dyn std::error::Error>> {
let s = match memchr(b'\0', input) {
Some(end) => &input[..end],
None => input,
};
match std::str::from_utf8(s) {
Ok(s) => Ok(String::from(s)),
Err(e) => Err(e.into()),
}
}
pub fn parse_per_length_determinant(input: &[u8]) -> IResult<&[u8], u32, RdpError> {
if input.is_empty() {
Err(Err::Incomplete(Needed::new(1)))
} else {
let bit7 = input[0] >> 7;
match bit7 {
0b0 => {
let length = input[0] as u32 & 0x7f;
Ok((&input[1..], length))
}
_ => {
let bit6 = (input[0] >> 6) & 0x1;
match bit6 {
0b0 => {
if input.len() < 2 {
Err(Err::Incomplete(Needed::new(2)))
} else {
let length = ((input[0] as u32 & 0x3f) << 8) | input[1] as u32;
Ok((&input[2..], length))
}
}
_ => {
Err(Err::Error(RdpError::UnimplementedLengthDeterminant))
}
}
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::rdp::error::RdpError;
use nom7::Needed;
#[test]
fn test_le_string_abc() {
let abc = &[0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00];
assert_eq!(String::from("ABC"), le_slice_to_string(abc).unwrap());
}
#[test]
fn test_le_string_empty() {
let empty = &[];
assert_eq!(String::from(""), le_slice_to_string(empty).unwrap());
}
#[test]
fn test_le_string_invalid() {
let not_utf16le = &[0x00, 0xd8, 0x01, 0x00];
assert!(le_slice_to_string(not_utf16le).is_err());
}
#[test]
fn test_utf7_string_abc() {
let abc = &[0x41, 0x42, 0x43, 0x00, 0x00];
assert_eq!(String::from("ABC"), utf7_slice_to_string(abc).unwrap());
}
#[test]
fn test_utf7_string_empty() {
let empty = &[];
assert_eq!(String::from(""), utf7_slice_to_string(empty).unwrap());
}
#[test]
fn test_utf7_string_invalid() {
let not_utf7 = &[0x80];
assert!(utf7_slice_to_string(not_utf7).is_err());
}
#[test]
fn test_length_single_length() {
let bytes = &[0x28];
assert_eq!(Ok((&[][..], 0x28)), parse_per_length_determinant(bytes));
}
#[test]
fn test_length_double_length() {
let bytes = &[0x81, 0x28];
assert_eq!(Ok((&[][..], 0x128)), parse_per_length_determinant(bytes));
}
#[test]
fn test_length_single_length_incomplete() {
let bytes = &[];
assert_eq!(
Err(Err::Incomplete(Needed::new(1))),
parse_per_length_determinant(bytes)
)
}
#[test]
fn test_length_16k_unimplemented() {
let bytes = &[0xc0];
assert_eq!(
Err(Err::Error(RdpError::UnimplementedLengthDeterminant)),
parse_per_length_determinant(bytes)
)
}
#[test]
fn test_length_double_length_incomplete() {
let bytes = &[0x81];
assert_eq!(
Err(Err::Incomplete(Needed::new(2))),
parse_per_length_determinant(bytes)
)
}
}