avm2: Implement read/writeObject()
This commit is contained in:
parent
ea3d6e2a5c
commit
6c3b6e5109
|
@ -5,7 +5,6 @@ package flash.net {
|
|||
import flash.utils.IDataInput;
|
||||
import flash.utils.IDataOutput;
|
||||
|
||||
import __ruffle__.stub_method;
|
||||
import __ruffle__.stub_getter;
|
||||
|
||||
[Ruffle(InstanceAllocator)]
|
||||
|
@ -60,12 +59,7 @@ package flash.net {
|
|||
public native function readFloat():Number;
|
||||
public native function readInt():int;
|
||||
public native function readMultiByte(length:uint, charSet:String):String;
|
||||
|
||||
public function readObject():* {
|
||||
stub_method("flash.net.Socket", "readObject");
|
||||
return null;
|
||||
}
|
||||
|
||||
public native function readObject():*;
|
||||
public native function readShort():int;
|
||||
public native function readUnsignedByte():uint;
|
||||
public native function readUnsignedInt():uint;
|
||||
|
@ -80,11 +74,7 @@ package flash.net {
|
|||
public native function writeFloat(value:Number):void;
|
||||
public native function writeInt(value:int):void;
|
||||
public native function writeMultiByte(value:String, charSet:String):void;
|
||||
|
||||
public function writeObject(value:*):void {
|
||||
stub_method("flash.net.Socket", "writeObject");
|
||||
}
|
||||
|
||||
public native function writeObject(value:*):void;
|
||||
public native function writeShort(value:int):void;
|
||||
public native function writeUnsignedInt(value:uint):void;
|
||||
public native function writeUTF(value:String):void;
|
||||
|
|
|
@ -7,6 +7,9 @@ use crate::avm2::{Activation, Error, Object, TObject, Value};
|
|||
use crate::context::UpdateContext;
|
||||
use encoding_rs::Encoding;
|
||||
use encoding_rs::UTF_8;
|
||||
use flash_lso::amf0::read::AMF0Decoder;
|
||||
use flash_lso::amf3::read::AMF3Decoder;
|
||||
use flash_lso::types::{AMFVersion, Element};
|
||||
|
||||
pub fn connect<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
|
@ -292,6 +295,45 @@ pub fn read_multi_byte<'gc>(
|
|||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
pub fn read_object<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
this: Object<'gc>,
|
||||
_args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
if let Some(socket) = this.as_socket() {
|
||||
let mut bytes = socket.read_buffer();
|
||||
|
||||
let (bytes_left, value) = match socket.object_encoding() {
|
||||
ObjectEncoding::Amf0 => {
|
||||
let mut decoder = AMF0Decoder::default();
|
||||
let (extra, amf) = decoder
|
||||
.parse_single_element(&bytes)
|
||||
.map_err(|_| "Error: Invalid object")?;
|
||||
(
|
||||
extra.len(),
|
||||
crate::avm2::amf::deserialize_value(activation, &amf)?,
|
||||
)
|
||||
}
|
||||
ObjectEncoding::Amf3 => {
|
||||
let mut decoder = AMF3Decoder::default();
|
||||
let (extra, amf) = decoder
|
||||
.parse_single_element(&bytes)
|
||||
.map_err(|_| "Error: Invalid object")?;
|
||||
(
|
||||
extra.len(),
|
||||
crate::avm2::amf::deserialize_value(activation, &amf)?,
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
let len = bytes.len();
|
||||
let _ = bytes.drain(..(len - bytes_left));
|
||||
return Ok(value);
|
||||
}
|
||||
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
pub fn read_short<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
this: Object<'gc>,
|
||||
|
@ -504,6 +546,38 @@ pub fn write_multi_byte<'gc>(
|
|||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
pub fn write_object<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
if let Some(socket) = this.as_socket() {
|
||||
let obj = args.get_value(0);
|
||||
let amf_version = match socket.object_encoding() {
|
||||
ObjectEncoding::Amf0 => AMFVersion::AMF0,
|
||||
ObjectEncoding::Amf3 => AMFVersion::AMF3,
|
||||
};
|
||||
if let Some(amf) = crate::avm2::amf::serialize_value(activation, obj, amf_version) {
|
||||
let element = Element::new("", amf);
|
||||
let mut lso = flash_lso::types::Lso::new(vec![element], "", amf_version);
|
||||
let bytes = flash_lso::write::write_to_bytes(&mut lso)
|
||||
.map_err(|_| "Failed to serialize object")?;
|
||||
// This is kind of hacky: We need to strip out the header and any padding so that we only write
|
||||
// the value. In the future, there should be a method to do this in the flash_lso crate.
|
||||
let element_padding = match amf_version {
|
||||
AMFVersion::AMF0 => 8,
|
||||
AMFVersion::AMF3 => 7,
|
||||
};
|
||||
socket.write_bytes(
|
||||
&bytes[flash_lso::write::header_length(&lso.header) + element_padding
|
||||
..bytes.len() - 1],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
pub fn write_short<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
this: Object<'gc>,
|
||||
|
|
Loading…
Reference in New Issue