avm2: Implement read/writeUTFBytes

This commit is contained in:
sleepycatcoding 2023-07-17 16:22:14 +03:00 committed by Nathan Adams
parent ad51041457
commit 6ca6bb1d78
3 changed files with 51 additions and 7 deletions

View File

@ -87,10 +87,7 @@ package flash.net {
return "";
}
public function readUTFBytes(length:uint):String {
stub_method("flash.net.Socket", "readUTFBytes");
return "";
}
public native function readUTFBytes(length:uint):String;
public native function writeBoolean(value:Boolean):void;
public native function writeByte(value:int):void;
@ -114,8 +111,6 @@ package flash.net {
stub_method("flash.net.Socket", "writeUTF");
}
public function writeUTFBytes(value:String):void {
stub_method("flash.net.Socket", "writeUTFBytes");
}
public native function writeUTFBytes(value:String):void;
}
}

View File

@ -2,6 +2,7 @@ use crate::avm2::bytearray::Endian;
use crate::avm2::error::{io_error, make_error_2008, security_error};
pub use crate::avm2::object::socket_allocator;
use crate::avm2::parameters::ParametersExt;
use crate::avm2::string::AvmString;
use crate::avm2::{Activation, Error, Object, TObject, Value};
use crate::context::UpdateContext;
@ -293,6 +294,26 @@ pub fn read_unsigned_short<'gc>(
Ok(Value::Undefined)
}
pub fn read_utf_bytes<'gc>(
activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(socket) = this.as_socket() {
let length = args.get_u32(activation, 0)?;
return Ok(AvmString::new_utf8_bytes(
activation.gc(),
&socket
.read_utf_bytes(length as usize)
.map_err(|e| e.to_avm(activation))?,
)
.into());
}
Ok(Value::Undefined)
}
pub fn write_boolean<'gc>(
_activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
@ -416,6 +437,20 @@ pub fn write_unsigned_int<'gc>(
Ok(Value::Undefined)
}
pub fn write_utf_bytes<'gc>(
activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(socket) = this.as_socket() {
let string = args.get_string(activation, 0)?;
socket.write_bytes(string.to_utf8_lossy().as_bytes());
}
Ok(Value::Undefined)
}
fn invalid_socket_error<'gc>(activation: &mut Activation<'_, 'gc>) -> Error<'gc> {
match io_error(
activation,

View File

@ -110,6 +110,20 @@ impl<'gc> SocketObject<'gc> {
pub fn write_boolean(&self, val: bool) {
self.write_bytes(&[val as u8; 1])
}
/// Same as `read_bytes`, but:
/// - cuts the result at the first null byte to recreate a bug in FP
/// - strips off an optional UTF8 BOM at the beginning
pub fn read_utf_bytes(&self, amnt: usize) -> Result<Vec<u8>, EofError> {
let mut bytes = &*self.read_bytes(amnt)?;
if let Some(without_bom) = bytes.strip_prefix(&[0xEF, 0xBB, 0xBF]) {
bytes = without_bom;
}
if let Some(null) = bytes.iter().position(|b| *b == b'\0') {
bytes = &bytes[..null];
}
Ok(bytes.to_vec())
}
}
macro_rules! impl_write{