Make writing List fields on Streamables possible from ActionScript again, and fix List reading and
writing in the code generated by GenActionScriptStreamableTask. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@6199 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -34,7 +34,7 @@ import com.threerings.util.Long;
|
|||||||
public class ObjectInputStream
|
public class ObjectInputStream
|
||||||
{
|
{
|
||||||
/** Enables verbose object I/O debugging. */
|
/** Enables verbose object I/O debugging. */
|
||||||
public static const DEBUG :Boolean = false;
|
public static const DEBUG :Boolean = true;
|
||||||
|
|
||||||
public function ObjectInputStream (source :IDataInput = null, clientProps :Object = null)
|
public function ObjectInputStream (source :IDataInput = null, clientProps :Object = null)
|
||||||
{
|
{
|
||||||
@@ -172,7 +172,8 @@ public class ObjectInputStream
|
|||||||
* Called to read an Object of a known final type into a Streamable object.
|
* Called to read an Object of a known final type into a Streamable object.
|
||||||
*
|
*
|
||||||
* @param type either a String representing the java type,
|
* @param type either a String representing the java type,
|
||||||
* or a Class object representing the actionscript type.
|
* a Class representing the actionscript type,
|
||||||
|
* or the Streamer to be used to read the field.
|
||||||
*/
|
*/
|
||||||
public function readField (type :Object) :*
|
public function readField (type :Object) :*
|
||||||
//throws IOError
|
//throws IOError
|
||||||
@@ -181,13 +182,18 @@ public class ObjectInputStream
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var jname :String = type as String;
|
var streamer :Streamer;
|
||||||
if (type is Class) {
|
if (type is Streamer) {
|
||||||
jname = Translations.getToServer(ClassUtil.getClassName(type));
|
streamer = Streamer(type);
|
||||||
}
|
} else {
|
||||||
var streamer :Streamer = Streamer.getStreamerByJavaName(jname);
|
var jname :String = type as String;
|
||||||
if (streamer == null) {
|
if (type is Class) {
|
||||||
throw new Error("Cannot field stream " + type);
|
jname = Translations.getToServer(ClassUtil.getClassName(type));
|
||||||
|
}
|
||||||
|
streamer= Streamer.getStreamerByJavaName(jname);
|
||||||
|
if (streamer == null) {
|
||||||
|
throw new Error("Cannot field stream " + type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var obj :Object = streamer.createObject(this);
|
var obj :Object = streamer.createObject(this);
|
||||||
|
|||||||
@@ -86,10 +86,13 @@ public class ObjectOutputStream
|
|||||||
writeBareObjectImpl(obj, cmap.streamer);
|
writeBareObjectImpl(obj, cmap.streamer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function writeBareObject (obj :Object) :void
|
public function writeBareObject (obj :Object, streamer :Streamer = null) :void
|
||||||
//throws IOError
|
//throws IOError
|
||||||
{
|
{
|
||||||
writeBareObjectImpl(obj, Streamer.getStreamer(obj));
|
if (streamer == null) {
|
||||||
|
streamer = Streamer.getStreamer(obj);
|
||||||
|
}
|
||||||
|
writeBareObjectImpl(obj, streamer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function writeBareObjectImpl (obj :Object, streamer :Streamer) :void
|
public function writeBareObjectImpl (obj :Object, streamer :Streamer) :void
|
||||||
@@ -125,13 +128,13 @@ public class ObjectOutputStream
|
|||||||
* }
|
* }
|
||||||
* </listing>
|
* </listing>
|
||||||
*/
|
*/
|
||||||
public function writeField (val :Object) :void
|
public function writeField (val :Object, streamer :Streamer = null) :void
|
||||||
//throws IOError
|
//throws IOError
|
||||||
{
|
{
|
||||||
var b :Boolean = (val != null);
|
var b :Boolean = (val != null);
|
||||||
writeBoolean(b);
|
writeBoolean(b);
|
||||||
if (b) {
|
if (b) {
|
||||||
writeBareObject(val);
|
writeBareObject(val, streamer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,7 +220,7 @@ public class ObjectOutputStream
|
|||||||
|
|
||||||
/** The target DataOutput that we route things to. */
|
/** The target DataOutput that we route things to. */
|
||||||
protected var _targ :IDataOutput;
|
protected var _targ :IDataOutput;
|
||||||
|
|
||||||
/** A counter used to assign codes to streamed classes. */
|
/** A counter used to assign codes to streamed classes. */
|
||||||
protected var _nextCode :int = 1;
|
protected var _nextCode :int = 1;
|
||||||
|
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ public class AuthRequest extends UpstreamMessage
|
|||||||
// if we fail here because the client is old, leave ourselves with a partially
|
// if we fail here because the client is old, leave ourselves with a partially
|
||||||
// initialized set of credentials, which the server will generally cope with by telling
|
// initialized set of credentials, which the server will generally cope with by telling
|
||||||
// the client it is out of date
|
// the client it is out of date
|
||||||
|
ioe.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public class ClientResolver extends Invoker.Unit
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initiailizes this instance.
|
* Initializes this instance.
|
||||||
*
|
*
|
||||||
* @param username the username of the user to be resolved.
|
* @param username the username of the user to be resolved.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -95,6 +95,11 @@ public class GenActionScriptStreamableTask extends GenActionScriptTask
|
|||||||
{
|
{
|
||||||
this.name = f.getName();
|
this.name = f.getName();
|
||||||
this.simpleType = addImportAndGetShortType(f.getType(), true, imports);
|
this.simpleType = addImportAndGetShortType(f.getType(), true, imports);
|
||||||
|
|
||||||
|
// Reading and writing Lists uses ArrayStreamer.INSTANCE directly
|
||||||
|
if (List.class.isAssignableFrom(f.getType())) {
|
||||||
|
imports.add("com.threerings.io.streamers.ArrayStreamer");
|
||||||
|
}
|
||||||
this.reader = toReadObject(f.getType());
|
this.reader = toReadObject(f.getType());
|
||||||
this.writer = toWriteObject(f.getType(), name);
|
this.writer = toWriteObject(f.getType(), name);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import java.lang.reflect.Field;
|
|||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
@@ -247,7 +248,7 @@ public class GenActionScriptTask extends GenTask
|
|||||||
if (needsActionScriptImport(type, isField)) {
|
if (needsActionScriptImport(type, isField)) {
|
||||||
imports.add(full);
|
imports.add(full);
|
||||||
}
|
}
|
||||||
return getSimpleType(full);
|
return Iterables.getLast(DOT_SPLITTER.split(full));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static boolean needsActionScriptImport (Class<?> type, boolean isField)
|
protected static boolean needsActionScriptImport (Class<?> type, boolean isField)
|
||||||
@@ -260,7 +261,7 @@ public class GenActionScriptTask extends GenTask
|
|||||||
|
|
||||||
protected static String toActionScriptType (Class<?> type, boolean isField)
|
protected static String toActionScriptType (Class<?> type, boolean isField)
|
||||||
{
|
{
|
||||||
if (type.isArray()) {
|
if (type.isArray() || List.class.isAssignableFrom(type)) {
|
||||||
if (Byte.TYPE.equals(type.getComponentType())) {
|
if (Byte.TYPE.equals(type.getComponentType())) {
|
||||||
return "flash.utils.ByteArray";
|
return "flash.utils.ByteArray";
|
||||||
}
|
}
|
||||||
@@ -290,6 +291,7 @@ public class GenActionScriptTask extends GenTask
|
|||||||
return "Boolean";
|
return "Boolean";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// inner classes are not supported by ActionScript so we _
|
||||||
return type.getName().replaceAll("\\$", "_");
|
return type.getName().replaceAll("\\$", "_");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,6 +331,9 @@ public class GenActionScriptTask extends GenTask
|
|||||||
} else if (type.equals(Double.TYPE)) {
|
} else if (type.equals(Double.TYPE)) {
|
||||||
return "readDouble()";
|
return "readDouble()";
|
||||||
|
|
||||||
|
} else if (List.class.isAssignableFrom(type)) {
|
||||||
|
return "readField(ArrayStreamer.INSTANCE)";
|
||||||
|
|
||||||
} else if (type.isArray()) {
|
} else if (type.isArray()) {
|
||||||
if (!type.getComponentType().isPrimitive()) {
|
if (!type.getComponentType().isPrimitive()) {
|
||||||
return "readObject(TypedArray)";
|
return "readObject(TypedArray)";
|
||||||
@@ -347,30 +352,23 @@ public class GenActionScriptTask extends GenTask
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return "readObject(" + ActionScriptSource.toSimpleName(type.getName()) + ")";
|
return "readObject(" + Iterables.getLast(DOT_SPLITTER.split(toActionScriptType(type, false))) + ")";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getSimpleType(String fullType)
|
|
||||||
{
|
|
||||||
return Iterables.getLast(DOT_SPLITTER.split(fullType));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String toWriteObject (Class<?> type, String name)
|
public static String toWriteObject (Class<?> type, String name)
|
||||||
{
|
{
|
||||||
if (type.equals(Integer.class)) {
|
if (type.equals(Integer.class)) {
|
||||||
return "writeObject(new Integer(" + name + "))";
|
return "writeObject(new Integer(" + name + "))";
|
||||||
|
|
||||||
} else if (type.equals(Long.class)) {
|
|
||||||
return "writeField(" + name + ")";
|
|
||||||
|
|
||||||
} else if (type.equals(Boolean.TYPE)) {
|
} else if (type.equals(Boolean.TYPE)) {
|
||||||
return "writeBoolean(" + name + ")";
|
return "writeBoolean(" + name + ")";
|
||||||
|
|
||||||
} else if (type.equals(Byte.TYPE)) {
|
} else if (type.equals(Byte.TYPE)) {
|
||||||
return "writeByte(" + name + ")";
|
return "writeByte(" + name + ")";
|
||||||
|
|
||||||
} else if (type.equals(Short.TYPE) || type.equals(Character.TYPE)) {
|
} else if (type.equals(Short.TYPE) ||
|
||||||
|
type.equals(Character.TYPE)) {
|
||||||
return "writeShort(" + name + ")";
|
return "writeShort(" + name + ")";
|
||||||
|
|
||||||
} else if (type.equals(Integer.TYPE)) {
|
} else if (type.equals(Integer.TYPE)) {
|
||||||
@@ -385,10 +383,14 @@ public class GenActionScriptTask extends GenTask
|
|||||||
} else if (type.equals(Double.TYPE)) {
|
} else if (type.equals(Double.TYPE)) {
|
||||||
return "writeDouble(" + name + ")";
|
return "writeDouble(" + name + ")";
|
||||||
|
|
||||||
} else if (type.equals(String.class) ||
|
} else if (type.equals(Long.class) ||
|
||||||
|
type.equals(String.class) ||
|
||||||
(type.isArray() && type.getComponentType().isPrimitive())) {
|
(type.isArray() && type.getComponentType().isPrimitive())) {
|
||||||
return "writeField(" + name + ")";
|
return "writeField(" + name + ")";
|
||||||
|
|
||||||
|
} else if (List.class.isAssignableFrom(type)) {
|
||||||
|
return "writeField(" + name + ", ArrayStreamer.INSTANCE)";
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return "writeObject(" + name + ")";
|
return "writeObject(" + name + ")";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import com.threerings.io.SimpleStreamableObject;
|
|||||||
import com.threerings.util.Long;
|
import com.threerings.util.Long;
|
||||||
import com.threerings.io.TypedArray;
|
import com.threerings.io.TypedArray;
|
||||||
import flash.utils.ByteArray;
|
import flash.utils.ByteArray;
|
||||||
|
import com.threerings.io.streamers.ArrayStreamer;
|
||||||
// GENERATED PREAMBLE END
|
// GENERATED PREAMBLE END
|
||||||
|
|
||||||
import com.threerings.util.Util;
|
import com.threerings.util.Util;
|
||||||
@@ -64,6 +65,7 @@ public class ASStreamableSubset extends SimpleStreamableObject
|
|||||||
bytes.writeByte(2);
|
bytes.writeByte(2);
|
||||||
bytes.writeByte(3);
|
bytes.writeByte(3);
|
||||||
ints = TypedArray.create(int, [1, 2, 3]);
|
ints = TypedArray.create(int, [1, 2, 3]);
|
||||||
|
strings = TypedArray.create(String, ["one", "two", "three"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function equals (o :ASStreamableSubset) :Boolean
|
public function equals (o :ASStreamableSubset) :Boolean
|
||||||
@@ -73,7 +75,8 @@ public class ASStreamableSubset extends SimpleStreamableObject
|
|||||||
byte8 === o.byte8 && string1 === o.string1 && nullString1 === o.nullString1 &&
|
byte8 === o.byte8 && string1 === o.string1 && nullString1 === o.nullString1 &&
|
||||||
Util.equals(bools, o.bools) && Util.equals(bytes, o.bytes) &&
|
Util.equals(bools, o.bools) && Util.equals(bytes, o.bytes) &&
|
||||||
Util.equals(ints, o.ints) && Util.equals(nullBools, o.nullBools) &&
|
Util.equals(ints, o.ints) && Util.equals(nullBools, o.nullBools) &&
|
||||||
Util.equals(nullBytes, o.nullBytes) && Util.equals(nullInts, o.nullInts);
|
Util.equals(nullBytes, o.nullBytes) && Util.equals(nullInts, o.nullInts) &&
|
||||||
|
Util.equals(strings, o.strings) && Util.equals(nullStrings, o.nullStrings);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,6 +97,8 @@ public class ASStreamableSubset extends SimpleStreamableObject
|
|||||||
public var nullBools :TypedArray;
|
public var nullBools :TypedArray;
|
||||||
public var nullBytes :ByteArray;
|
public var nullBytes :ByteArray;
|
||||||
public var nullInts :TypedArray;
|
public var nullInts :TypedArray;
|
||||||
|
public var strings :TypedArray;
|
||||||
|
public var nullStrings :TypedArray;
|
||||||
|
|
||||||
override public function readObject (ins :ObjectInputStream) :void
|
override public function readObject (ins :ObjectInputStream) :void
|
||||||
{
|
{
|
||||||
@@ -114,8 +119,10 @@ public class ASStreamableSubset extends SimpleStreamableObject
|
|||||||
nullBools = ins.readField(TypedArray.getJavaType(Boolean));
|
nullBools = ins.readField(TypedArray.getJavaType(Boolean));
|
||||||
nullBytes = ins.readField(ByteArray);
|
nullBytes = ins.readField(ByteArray);
|
||||||
nullInts = ins.readField(TypedArray.getJavaType(int));
|
nullInts = ins.readField(TypedArray.getJavaType(int));
|
||||||
|
strings = ins.readField(ArrayStreamer.INSTANCE);
|
||||||
|
nullStrings = ins.readField(ArrayStreamer.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
override public function writeObject (out :ObjectOutputStream) :void
|
override public function writeObject (out :ObjectOutputStream) :void
|
||||||
{
|
{
|
||||||
super.writeObject(out);
|
super.writeObject(out);
|
||||||
@@ -135,6 +142,8 @@ public class ASStreamableSubset extends SimpleStreamableObject
|
|||||||
out.writeField(nullBools);
|
out.writeField(nullBools);
|
||||||
out.writeField(nullBytes);
|
out.writeField(nullBytes);
|
||||||
out.writeField(nullInts);
|
out.writeField(nullInts);
|
||||||
|
out.writeField(strings, ArrayStreamer.INSTANCE);
|
||||||
|
out.writeField(nullStrings, ArrayStreamer.INSTANCE);
|
||||||
}
|
}
|
||||||
// GENERATED STREAMING END
|
// GENERATED STREAMING END
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,11 @@ import asunit.framework.TestCase;
|
|||||||
|
|
||||||
public class StreamableTest extends TestCase
|
public class StreamableTest extends TestCase
|
||||||
{
|
{
|
||||||
|
public function StreamableTest (name:String = null)
|
||||||
|
{
|
||||||
|
super(name);
|
||||||
|
}
|
||||||
|
|
||||||
public function testStreamingToSelf ():void
|
public function testStreamingToSelf ():void
|
||||||
{
|
{
|
||||||
var sub:ASStreamableSubset = ASStreamableSubset.createWithJavaDefaults();
|
var sub:ASStreamableSubset = ASStreamableSubset.createWithJavaDefaults();
|
||||||
@@ -49,7 +54,8 @@ public class StreamableTest extends TestCase
|
|||||||
var javaData:ByteArray = StringUtil.unhexlate(
|
var javaData:ByteArray = StringUtil.unhexlate(
|
||||||
"ffff0024636f6d2e746872656572696e67732e696f2e415353747265616d61626c65537562736574" +
|
"ffff0024636f6d2e746872656572696e67732e696f2e415353747265616d61626c65537562736574" +
|
||||||
"01000200000003000000000000000440a0000040180000000000000007080100036f6e6500010000" +
|
"01000200000003000000000000000440a0000040180000000000000007080100036f6e6500010000" +
|
||||||
"000301000101000000030102030100000003000000010000000200000003000000");
|
"0003010001010000000301020301000000030000000100000002000000030000000100000003fffe" +
|
||||||
|
"00106a6176612e6c616e672e537472696e6700036f6e650002000374776f00020005746872656500");
|
||||||
var input:ObjectInputStream = new ObjectInputStream(javaData);
|
var input:ObjectInputStream = new ObjectInputStream(javaData);
|
||||||
var read :ASStreamableSubset = input.readObject(ASStreamableSubset);
|
var read :ASStreamableSubset = input.readObject(ASStreamableSubset);
|
||||||
assertTrue(sub.equals(read));
|
assertTrue(sub.equals(read));
|
||||||
|
|||||||
@@ -22,8 +22,10 @@ package com.threerings.io;
|
|||||||
//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
public class ASStreamableSubset extends SimpleStreamableObject
|
public class ASStreamableSubset extends SimpleStreamableObject
|
||||||
{
|
{
|
||||||
@@ -47,6 +49,9 @@ public class ASStreamableSubset extends SimpleStreamableObject
|
|||||||
public byte[] nullBytes;
|
public byte[] nullBytes;
|
||||||
public int[] nullInts;
|
public int[] nullInts;
|
||||||
|
|
||||||
|
public List<String> strings = Lists.newArrayList("one", "two", "three");
|
||||||
|
public List<String> nullStrings;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals (Object other)
|
public boolean equals (Object other)
|
||||||
{
|
{
|
||||||
@@ -67,6 +72,10 @@ public class ASStreamableSubset extends SimpleStreamableObject
|
|||||||
Arrays.equals(bools, ow.bools) && Arrays.equals(bytes, ow.bytes)
|
Arrays.equals(bools, ow.bools) && Arrays.equals(bytes, ow.bytes)
|
||||||
&& Arrays.equals(ints, ow.ints) &&
|
&& Arrays.equals(ints, ow.ints) &&
|
||||||
|
|
||||||
Arrays.equals(nullBools, ow.nullBools) && Arrays.equals(nullBytes, ow.nullBytes);
|
Arrays.equals(nullBools, ow.nullBools) && Arrays.equals(nullBytes, ow.nullBytes)
|
||||||
|
&& Arrays.equals(nullInts, ow.nullInts)
|
||||||
|
&&
|
||||||
|
|
||||||
|
Objects.equal(strings, ow.strings) && Objects.equal(nullStrings, ow.nullStrings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -345,11 +345,8 @@ public class StreamableTest
|
|||||||
oout.writeObject(w);
|
oout.writeObject(w);
|
||||||
byte[] data = bout.toByteArray();
|
byte[] data = bout.toByteArray();
|
||||||
|
|
||||||
// uncomment this and rerun the tests to generate an updated WIRE_DATA blob:
|
// uncomment this and rerun the tests to generate an updated WIRE_DATA blob
|
||||||
// String dstr = StringUtil.wordWrap(StringUtil.hexlate(data), 80);
|
// printWireData(w);
|
||||||
// dstr = StringUtil.join(dstr.split("\n"), "\" +\n \"");
|
|
||||||
// System.out.println(" protected static final byte[] WIRE_DATA = " +
|
|
||||||
// "StringUtil.unhexlate(\n \"" + dstr + "\");");
|
|
||||||
|
|
||||||
// oddly, JUnit doesn't like comparing byte arrays directly (this fails:
|
// oddly, JUnit doesn't like comparing byte arrays directly (this fails:
|
||||||
// assertEquals(WIRE_DATA, WIRE_DATA.clone())), but comparing strings is fine
|
// assertEquals(WIRE_DATA, WIRE_DATA.clone())), but comparing strings is fine
|
||||||
@@ -360,6 +357,18 @@ public class StreamableTest
|
|||||||
assertEquals(w, oin.readObject());
|
assertEquals(w, oin.readObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void printWireData (Object o)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||||
|
ObjectOutputStream oout = new ObjectOutputStream(bout);
|
||||||
|
oout.writeObject(o);
|
||||||
|
String dstr = StringUtil.wordWrap(StringUtil.hexlate(bout.toByteArray()), 80);
|
||||||
|
dstr = StringUtil.join(dstr.split("\n"), "\" +\n \"");
|
||||||
|
System.out.println(" protected static final byte[] WIRE_DATA = "
|
||||||
|
+ "StringUtil.unhexlate(\n \"" + dstr + "\");");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPostStreamingMutation ()
|
public void testPostStreamingMutation ()
|
||||||
throws IOException, ClassNotFoundException
|
throws IOException, ClassNotFoundException
|
||||||
|
|||||||
Reference in New Issue
Block a user