Changeset View
Changeset View
Standalone View
Standalone View
source/simulation2/serialization/BinarySerializer.cpp
/* Copyright (C) 2020 Wildfire Games. | /* Copyright (C) 2020 Wildfire Games. | ||||
Stan: 2021 | |||||
* This file is part of 0 A.D. | * This file is part of 0 A.D. | ||||
* | * | ||||
* 0 A.D. is free software: you can redistribute it and/or modify | * 0 A.D. is free software: you can redistribute it and/or modify | ||||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | ||||
* the Free Software Foundation, either version 2 of the License, or | * the Free Software Foundation, either version 2 of the License, or | ||||
* (at your option) any later version. | * (at your option) any later version. | ||||
* | * | ||||
* 0 A.D. is distributed in the hope that it will be useful, | * 0 A.D. is distributed in the hope that it will be useful, | ||||
Show All 39 Lines | static u8 GetArrayType(js::Scalar::Type arrayType) | ||||
case js::Scalar::Uint8Clamped: | case js::Scalar::Uint8Clamped: | ||||
return SCRIPT_TYPED_ARRAY_UINT8_CLAMPED; | return SCRIPT_TYPED_ARRAY_UINT8_CLAMPED; | ||||
default: | default: | ||||
LOGERROR("Cannot serialize unrecognized typed array view: %d", arrayType); | LOGERROR("Cannot serialize unrecognized typed array view: %d", arrayType); | ||||
throw PSERROR_Serialize_InvalidScriptValue(); | throw PSERROR_Serialize_InvalidScriptValue(); | ||||
} | } | ||||
} | } | ||||
CBinarySerializerScriptImpl::CBinarySerializerScriptImpl(const ScriptInterface& scriptInterface, ISerializer& serializer) : | CBinarySerializerScriptImpl::CBinarySerializerScriptImpl(const ScriptInterface& scriptInterface, IBinarySerializer& serializer) : | ||||
m_ScriptInterface(scriptInterface), m_Serializer(serializer), m_ScriptBackrefsNext(0) | m_ScriptInterface(scriptInterface), m_Serializer(serializer), m_ScriptBackrefsNext(0) | ||||
{ | { | ||||
ScriptRequest rq(m_ScriptInterface); | ScriptRequest rq(m_ScriptInterface); | ||||
m_ScriptBackrefSymbol.init(rq.cx, JS::NewSymbol(rq.cx, nullptr)); | m_ScriptBackrefSymbol.init(rq.cx, JS::NewSymbol(rq.cx, nullptr)); | ||||
} | } | ||||
void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val) | void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val) | ||||
▲ Show 20 Lines • Show All 153 Lines • ▼ Show 20 Lines | else | ||||
if (protokey == JSProto_Object) | if (protokey == JSProto_Object) | ||||
{ | { | ||||
// Standard Object prototype | // Standard Object prototype | ||||
m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_OBJECT); | m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_OBJECT); | ||||
} | } | ||||
else if (protokey == JSProto_Number) | else if (protokey == JSProto_Number) | ||||
{ | { | ||||
// Standard Number object | |||||
m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_OBJECT_NUMBER); | |||||
// Get primitive value | |||||
double d; | double d; | ||||
if (!JS::ToNumber(rq.cx, val, &d)) | if (!JS::ToNumber(rq.cx, val, &d)) | ||||
throw PSERROR_Serialize_ScriptError("JS::ToNumber failed"); | throw PSERROR_Serialize_ScriptError("JS::ToNumber failed"); | ||||
m_Serializer.NumberDouble_Unbounded("value", d); | |||||
if (std::isnan(d)) | |||||
{ | |||||
m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_NAN); | |||||
m_Serializer.Bool("object", true); | |||||
break; | |||||
} | |||||
// Standard Number object | |||||
m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_OBJECT_NUMBER); | |||||
// Get primitive value | |||||
m_Serializer.PutNumber("value", d); | |||||
break; | break; | ||||
} | } | ||||
else if (protokey == JSProto_String) | else if (protokey == JSProto_String) | ||||
{ | { | ||||
// Standard String object | // Standard String object | ||||
m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_OBJECT_STRING); | m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_OBJECT_STRING); | ||||
// Get primitive value | // Get primitive value | ||||
JS::RootedString str(rq.cx, JS::ToString(rq.cx, val)); | JS::RootedString str(rq.cx, JS::ToString(rq.cx, val)); | ||||
▲ Show 20 Lines • Show All 98 Lines • ▼ Show 20 Lines | #endif | ||||
} | } | ||||
case JSTYPE_NUMBER: | case JSTYPE_NUMBER: | ||||
{ | { | ||||
// To reduce the size of the serialized data, we handle integers and doubles separately. | // To reduce the size of the serialized data, we handle integers and doubles separately. | ||||
// We can't check for val.isInt32 and val.isDouble directly, because integer numbers are not guaranteed | // We can't check for val.isInt32 and val.isDouble directly, because integer numbers are not guaranteed | ||||
// to be represented as integers. A number like 33 could be stored as integer on the computer of one player | // to be represented as integers. A number like 33 could be stored as integer on the computer of one player | ||||
// and as double on the other player's computer. That would cause out of sync errors in multiplayer games because | // and as double on the other player's computer. That would cause out of sync errors in multiplayer games because | ||||
// their binary representation and thus the hash would be different. | // their binary representation and thus the hash would be different. | ||||
if (val == JS::NaNValue()) | |||||
{ | |||||
m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_NAN); | |||||
m_Serializer.Bool("object", false); | |||||
break; | |||||
} | |||||
double d; | double d; | ||||
d = val.toNumber(); | d = val.toNumber(); | ||||
i32 integer; | i32 integer; | ||||
if (JS_DoubleIsInt32(d, &integer)) | if (JS_DoubleIsInt32(d, &integer)) | ||||
{ | { | ||||
m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_INT); | m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_INT); | ||||
m_Serializer.NumberI32_Unbounded("value", integer); | m_Serializer.NumberI32_Unbounded("value", integer); | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_DOUBLE); | m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_DOUBLE); | ||||
m_Serializer.NumberDouble_Unbounded("value", d); | m_Serializer.PutNumber("value", d); | ||||
} | } | ||||
break; | break; | ||||
} | } | ||||
case JSTYPE_BOOLEAN: | case JSTYPE_BOOLEAN: | ||||
{ | { | ||||
m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_BOOLEAN); | m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_BOOLEAN); | ||||
bool b = val.toBoolean(); | bool b = val.toBoolean(); | ||||
m_Serializer.NumberU8_Unbounded("value", b ? 1 : 0); | m_Serializer.NumberU8_Unbounded("value", b ? 1 : 0); | ||||
▲ Show 20 Lines • Show All 77 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator
2021