Add VRChat and GitHub packages to Unity project

This commit is contained in:
gunnbr committed 2021-01-18 09:14:18 -08:00
1 parent 0334a52b21
commit 85538aaccc
3297 files changed
+847877

No files matched your search

@@ -0,0 +1,68 @@
//-----------------------------------------------------------------------
// <copyright file="BooleanSerializer.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
/// <summary>
/// Serializer for the <see cref="bool"/> type.
/// </summary>
/// <seealso cref="Serializer{System.Boolean}" />
public sealed class BooleanSerializer : Serializer<bool>
{
/// <summary>
/// Reads a value of type <see cref="bool" />.
/// </summary>
/// <param name="reader">The reader to use.</param>
/// <returns>
/// The value which has been read.
/// </returns>
public override bool ReadValue(IDataReader reader)
{
string name;
var entry = reader.PeekEntry(out name);
if (entry == EntryType.Boolean)
{
bool value;
if (reader.ReadBoolean(out value) == false)
{
reader.Context.Config.DebugContext.LogWarning("Failed to read entry '" + name + "' of type " + entry.ToString());
}
return value;
}
else
{
reader.Context.Config.DebugContext.LogWarning("Expected entry of type " + EntryType.Boolean.ToString() + ", but got entry '" + name + "' of type " + entry.ToString());
reader.SkipEntry();
return default(bool);
}
}
/// <summary>
/// Writes a value of type <see cref="bool" />.
/// </summary>
/// <param name="name">The name of the value to write.</param>
/// <param name="value">The value to write.</param>
/// <param name="writer">The writer to use.</param>
public override void WriteValue(string name, bool value, IDataWriter writer)
{
FireOnSerializedType();
writer.WriteBoolean(name, value);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0e8d8c5a97fdc322a8b8471aaf02f469
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,68 @@
//-----------------------------------------------------------------------
// <copyright file="ByteSerializer.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
/// <summary>
/// Serializer for the <see cref="byte"/> type.
/// </summary>
/// <seealso cref="Serializer{System.Byte}" />
public sealed class ByteSerializer : Serializer<byte>
{
/// <summary>
/// Reads a value of type <see cref="byte" />.
/// </summary>
/// <param name="reader">The reader to use.</param>
/// <returns>
/// The value which has been read.
/// </returns>
public override byte ReadValue(IDataReader reader)
{
string name;
var entry = reader.PeekEntry(out name);
if (entry == EntryType.Integer)
{
byte value;
if (reader.ReadByte(out value) == false)
{
reader.Context.Config.DebugContext.LogWarning("Failed to read entry '" + name + "' of type " + entry.ToString());
}
return value;
}
else
{
reader.Context.Config.DebugContext.LogWarning("Expected entry of type " + EntryType.Integer.ToString() + ", but got entry '" + name + "' of type " + entry.ToString());
reader.SkipEntry();
return default(byte);
}
}
/// <summary>
/// Writes a value of type <see cref="byte" />.
/// </summary>
/// <param name="name">The name of the value to write.</param>
/// <param name="value">The value to write.</param>
/// <param name="writer">The writer to use.</param>
public override void WriteValue(string name, byte value, IDataWriter writer)
{
FireOnSerializedType();
writer.WriteByte(name, value);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8aa9f52771b0e4e6f8f0c438a4f0430b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,68 @@
//-----------------------------------------------------------------------
// <copyright file="CharSerializer.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
/// <summary>
/// Serializer for the <see cref="char"/> type.
/// </summary>
/// <seealso cref="Serializer{System.Char}" />
public sealed class CharSerializer : Serializer<char>
{
/// <summary>
/// Reads a value of type <see cref="char" />.
/// </summary>
/// <param name="reader">The reader to use.</param>
/// <returns>
/// The value which has been read.
/// </returns>
public override char ReadValue(IDataReader reader)
{
string name;
var entry = reader.PeekEntry(out name);
if (entry == EntryType.String)
{
char value;
if (reader.ReadChar(out value) == false)
{
reader.Context.Config.DebugContext.LogWarning("Failed to read entry '" + name + "' of type " + entry.ToString());
}
return value;
}
else
{
reader.Context.Config.DebugContext.LogWarning("Expected entry of type " + EntryType.String.ToString() + ", but got entry '" + name + "' of type " + entry.ToString());
reader.SkipEntry();
return default(char);
}
}
/// <summary>
/// Writes a value of type <see cref="char" />.
/// </summary>
/// <param name="name">The name of the value to write.</param>
/// <param name="value">The value to write.</param>
/// <param name="writer">The writer to use.</param>
public override void WriteValue(string name, char value, IDataWriter writer)
{
FireOnSerializedType();
writer.WriteChar(name, value);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d44d1ae83013328d7b855275fa1cfad7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,663 @@
//-----------------------------------------------------------------------
// <copyright file="ComplexTypeSerializer.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
using System;
using System.Collections.Generic;
using Utilities;
/// <summary>
/// Serializer for all complex types; IE, types which are not primitives as determined by the <see cref="FormatterUtilities.IsPrimitiveType(Type)" /> method.
/// </summary>
/// <typeparam name="T">The type which the <see cref="ComplexTypeSerializer{T}" /> can serialize and deserialize.</typeparam>
/// <seealso cref="Serializer{T}" />
public sealed class ComplexTypeSerializer<T> : Serializer<T>
{
private static readonly bool ComplexTypeMayBeBoxedValueType = typeof(T).IsInterface || typeof(T) == typeof(object) || typeof(T) == typeof(ValueType) || typeof(T) == typeof(Enum);
private static readonly bool ComplexTypeIsAbstract = typeof(T).IsAbstract || typeof(T).IsInterface;
private static readonly bool ComplexTypeIsNullable = typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(Nullable<>);
private static readonly bool ComplexTypeIsValueType = typeof(T).IsValueType;
private static readonly Type TypeOf_T = typeof(T);
private static readonly bool AllowDeserializeInvalidDataForT = typeof(T).IsDefined(typeof(AllowDeserializeInvalidDataAttribute), true);
private static readonly Dictionary<ISerializationPolicy, IFormatter<T>> FormattersByPolicy = new Dictionary<ISerializationPolicy, IFormatter<T>>(ReferenceEqualityComparer<ISerializationPolicy>.Default);
private static readonly object FormattersByPolicy_LOCK = new object();
private static readonly ISerializationPolicy UnityPolicy = SerializationPolicies.Unity;
private static readonly ISerializationPolicy StrictPolicy = SerializationPolicies.Strict;
private static readonly ISerializationPolicy EverythingPolicy = SerializationPolicies.Everything;
private static IFormatter<T> UnityPolicyFormatter;
private static IFormatter<T> StrictPolicyFormatter;
private static IFormatter<T> EverythingPolicyFormatter;
/// <summary>
/// Reads a value of type <see cref="T" />.
/// </summary>
/// <param name="reader">The reader to use.</param>
/// <returns>
/// The value which has been read.
/// </returns>
public override T ReadValue(IDataReader reader)
{
var context = reader.Context;
if (context.Config.SerializationPolicy.AllowNonSerializableTypes == false && TypeOf_T.IsSerializable == false)
{
context.Config.DebugContext.LogError("The type " + TypeOf_T.Name + " is not marked as serializable.");
return default(T);
}
bool exitNode = true;
string name;
var entry = reader.PeekEntry(out name);
if (ComplexTypeIsValueType)
{
if (entry == EntryType.Null)
{
context.Config.DebugContext.LogWarning("Expecting complex struct of type " + TypeOf_T.GetNiceFullName() + " but got null value.");
reader.ReadNull();
return default(T);
}
else if (entry != EntryType.StartOfNode)
{
context.Config.DebugContext.LogWarning("Unexpected entry '" + name + "' of type " + entry.ToString() + ", when " + EntryType.StartOfNode + " was expected. A value has likely been lost.");
reader.SkipEntry();
return default(T);
}
try
{
Type expectedType = TypeOf_T;
Type serializedType;
if (reader.EnterNode(out serializedType))
{
if (serializedType != expectedType)
{
if (serializedType != null)
{
context.Config.DebugContext.LogWarning("Expected complex struct value " + expectedType.Name + " but the serialized value is of type " + serializedType.Name + ".");
if (serializedType.IsCastableTo(expectedType))
{
object value = FormatterLocator.GetFormatter(serializedType, context.Config.SerializationPolicy).Deserialize(reader);
bool serializedTypeIsNullable = serializedType.IsGenericType && serializedType.GetGenericTypeDefinition() == typeof(Nullable<>);
bool allowCastMethod = !ComplexTypeIsNullable && !serializedTypeIsNullable;
var castMethod = allowCastMethod ? serializedType.GetCastMethodDelegate(expectedType) : null;
if (castMethod != null)
{
return (T)castMethod(value);
}
else
{
return (T)value;
}
}
else if (AllowDeserializeInvalidDataForT || reader.Context.Config.AllowDeserializeInvalidData)
{
context.Config.DebugContext.LogWarning("Can't cast serialized type " + serializedType.Name + " into expected type " + expectedType.Name + ". Attempting to deserialize with possibly invalid data. Value may be lost or corrupted for node '" + name + "'.");
return GetBaseFormatter(context.Config.SerializationPolicy).Deserialize(reader);
}
else
{
context.Config.DebugContext.LogWarning("Can't cast serialized type " + serializedType.Name + " into expected type " + expectedType.Name + ". Value lost for node '" + name + "'.");
return default(T);
}
}
else if (AllowDeserializeInvalidDataForT || reader.Context.Config.AllowDeserializeInvalidData)
{
context.Config.DebugContext.LogWarning("Expected complex struct value " + expectedType.Name + " but the serialized type could not be resolved. Attempting to deserialize with possibly invalid data. Value may be lost or corrupted for node '" + name + "'.");
return GetBaseFormatter(context.Config.SerializationPolicy).Deserialize(reader);
}
else
{
context.Config.DebugContext.LogWarning("Expected complex struct value " + expectedType.Name + " but the serialized type could not be resolved. Value lost for node '" + name + "'.");
return default(T);
}
}
else
{
return GetBaseFormatter(context.Config.SerializationPolicy).Deserialize(reader);
}
}
else
{
context.Config.DebugContext.LogError("Failed to enter node '" + name + "'.");
return default(T);
}
}
catch (SerializationAbortException ex)
{
exitNode = false;
throw ex;
}
catch (Exception ex)
{
context.Config.DebugContext.LogException(ex);
return default(T);
}
finally
{
if (exitNode)
{
reader.ExitNode();
}
}
}
else
{
switch (entry)
{
case EntryType.Null:
{
reader.ReadNull();
return default(T);
}
case EntryType.ExternalReferenceByIndex:
{
int index;
reader.ReadExternalReference(out index);
object value = context.GetExternalObject(index);
try
{
return (T)value;
}
catch (InvalidCastException)
{
context.Config.DebugContext.LogWarning("Can't cast external reference type " + value.GetType().Name + " into expected type " + TypeOf_T.Name + ". Value lost for node '" + name + "'.");
return default(T);
}
}
case EntryType.ExternalReferenceByGuid:
{
Guid guid;
reader.ReadExternalReference(out guid);
object value = context.GetExternalObject(guid);
try
{
return (T)value;
}
catch (InvalidCastException)
{
context.Config.DebugContext.LogWarning("Can't cast external reference type " + value.GetType().Name + " into expected type " + TypeOf_T.Name + ". Value lost for node '" + name + "'.");
return default(T);
}
}
case EntryType.ExternalReferenceByString:
{
string id;
reader.ReadExternalReference(out id);
object value = context.GetExternalObject(id);
try
{
return (T)value;
}
catch (InvalidCastException)
{
context.Config.DebugContext.LogWarning("Can't cast external reference type " + value.GetType().Name + " into expected type " + TypeOf_T.Name + ". Value lost for node '" + name + "'.");
return default(T);
}
}
case EntryType.InternalReference:
{
int id;
reader.ReadInternalReference(out id);
object value = context.GetInternalReference(id);
try
{
return (T)value;
}
catch (InvalidCastException)
{
context.Config.DebugContext.LogWarning("Can't cast internal reference type " + value.GetType().Name + " into expected type " + TypeOf_T.Name + ". Value lost for node '" + name + "'.");
return default(T);
}
}
case EntryType.StartOfNode:
{
try
{
Type expectedType = TypeOf_T;
Type serializedType;
int id;
if (reader.EnterNode(out serializedType))
{
id = reader.CurrentNodeId;
T result;
if (serializedType != null && expectedType != serializedType) // We have type metadata different from the expected type
{
bool success = false;
var isPrimitive = FormatterUtilities.IsPrimitiveType(serializedType);
bool assignableCast;
if (ComplexTypeMayBeBoxedValueType && isPrimitive)
{
// It's a boxed primitive type, so simply read that straight and register success
var serializer = Serializer.Get(serializedType);
result = (T)serializer.ReadValueWeak(reader);
success = true;
}
else if ((assignableCast = expectedType.IsAssignableFrom(serializedType)) || serializedType.HasCastDefined(expectedType, false))
{
try
{
object value;
if (isPrimitive)
{
var serializer = Serializer.Get(serializedType);
value = serializer.ReadValueWeak(reader);
}
else
{
var alternateFormatter = FormatterLocator.GetFormatter(serializedType, context.Config.SerializationPolicy);
value = alternateFormatter.Deserialize(reader);
}
if (assignableCast)
{
result = (T)value;
}
else
{
var castMethod = serializedType.GetCastMethodDelegate(expectedType);
if (castMethod != null)
{
result = (T)castMethod(value);
}
else
{
// Let's just give it a go anyways
result = (T)value;
}
}
success = true;
}
catch (SerializationAbortException ex)
{
exitNode = false;
throw ex;
}
catch (InvalidCastException)
{
success = false;
result = default(T);
}
}
else if (!ComplexTypeIsAbstract && (AllowDeserializeInvalidDataForT || reader.Context.Config.AllowDeserializeInvalidData))
{
// We will try to deserialize an instance of T with the invalid data.
context.Config.DebugContext.LogWarning("Can't cast serialized type " + serializedType.Name + " into expected type " + expectedType.Name + ". Attempting to deserialize with invalid data. Value may be lost or corrupted for node '" + name + "'.");
result = GetBaseFormatter(context.Config.SerializationPolicy).Deserialize(reader);
success = true;
}
else
{
// We couldn't cast or use the type, but we still have to deserialize it and register
// the reference so the reference isn't lost if it is referred to further down
// the data stream.
var alternateFormatter = FormatterLocator.GetFormatter(serializedType, context.Config.SerializationPolicy);
object value = alternateFormatter.Deserialize(reader);
if (id >= 0)
{
context.RegisterInternalReference(id, value);
}
result = default(T);
}
if (!success)
{
// We can't use this
context.Config.DebugContext.LogWarning("Can't cast serialized type " + serializedType.Name + " into expected type " + expectedType.Name + ". Value lost for node '" + name + "'.");
result = default(T);
}
}
else if (ComplexTypeIsAbstract)
{
result = default(T);
}
else
{
result = GetBaseFormatter(context.Config.SerializationPolicy).Deserialize(reader);
}
if (id >= 0)
{
context.RegisterInternalReference(id, result);
}
return result;
}
else
{
context.Config.DebugContext.LogError("Failed to enter node '" + name + "'.");
return default(T);
}
}
catch (SerializationAbortException ex)
{
exitNode = false;
throw ex;
}
catch (Exception ex)
{
context.Config.DebugContext.LogException(ex);
return default(T);
}
finally
{
if (exitNode)
{
reader.ExitNode();
}
}
}
//
// The below cases are for when we expect an object, but have
// serialized a straight primitive type. In such cases, we can
// often box the primitive type as an object.
//
// Sadly, the exact primitive type might be lost in case of
// integer and floating points numbers, as we don't know what
// type to expect.
//
// To be safe, we read and box the most precise type available.
//
case EntryType.Boolean:
{
if (!ComplexTypeMayBeBoxedValueType)
{
goto default;
}
bool value;
reader.ReadBoolean(out value);
return (T)(object)value;
}
case EntryType.FloatingPoint:
{
if (!ComplexTypeMayBeBoxedValueType)
{
goto default;
}
double value;
reader.ReadDouble(out value);
return (T)(object)value;
}
case EntryType.Integer:
{
if (!ComplexTypeMayBeBoxedValueType)
{
goto default;
}
long value;
reader.ReadInt64(out value);
return (T)(object)value;
}
case EntryType.String:
{
if (!ComplexTypeMayBeBoxedValueType)
{
goto default;
}
string value;
reader.ReadString(out value);
return (T)(object)value;
}
case EntryType.Guid:
{
if (!ComplexTypeMayBeBoxedValueType)
{
goto default;
}
Guid value;
reader.ReadGuid(out value);
return (T)(object)value;
}
default:
// Lost value somehow
context.Config.DebugContext.LogWarning("Unexpected entry of type " + entry.ToString() + ", when a reference or node start was expected. A value has been lost.");
reader.SkipEntry();
return default(T);
}
}
}
private static IFormatter<T> GetBaseFormatter(ISerializationPolicy serializationPolicy)
{
// This is an optimization - it's a lot cheaper to compare three references and do a null check,
// than it is to look something up in a dictionary. By far most of the time, we will be using
// one of these three policies.
if (object.ReferenceEquals(serializationPolicy, UnityPolicy))
{
if (UnityPolicyFormatter == null)
{
UnityPolicyFormatter = FormatterLocator.GetFormatter<T>(UnityPolicy);
}
return UnityPolicyFormatter;
}
else if (object.ReferenceEquals(serializationPolicy, EverythingPolicy))
{
if (EverythingPolicyFormatter == null)
{
EverythingPolicyFormatter = FormatterLocator.GetFormatter<T>(EverythingPolicy);
}
return EverythingPolicyFormatter;
}
else if (object.ReferenceEquals(serializationPolicy, StrictPolicy))
{
if (StrictPolicyFormatter == null)
{
StrictPolicyFormatter = FormatterLocator.GetFormatter<T>(StrictPolicy);
}
return StrictPolicyFormatter;
}
IFormatter<T> formatter;
lock (FormattersByPolicy_LOCK)
{
if (!FormattersByPolicy.TryGetValue(serializationPolicy, out formatter))
{
formatter = FormatterLocator.GetFormatter<T>(serializationPolicy);
FormattersByPolicy.Add(serializationPolicy, formatter);
}
}
return formatter;
}
/// <summary>
/// Writes a value of type <see cref="T" />.
/// </summary>
/// <param name="name">The name of the value to write.</param>
/// <param name="value">The value to write.</param>
/// <param name="writer">The writer to use.</param>
public override void WriteValue(string name, T value, IDataWriter writer)
{
var context = writer.Context;
var policy = context.Config.SerializationPolicy;
if (policy.AllowNonSerializableTypes == false && TypeOf_T.IsSerializable == false)
{
context.Config.DebugContext.LogError("The type " + TypeOf_T.Name + " is not marked as serializable.");
return;
}
FireOnSerializedType();
if (ComplexTypeIsValueType)
{
bool endNode = true;
try
{
writer.BeginStructNode(name, TypeOf_T);
GetBaseFormatter(policy).Serialize(value, writer);
}
catch (SerializationAbortException ex)
{
endNode = false;
throw ex;
}
finally
{
if (endNode)
{
writer.EndNode(name);
}
}
}
else
{
int id;
int index;
string strId;
Guid guid;
bool endNode = true;
if (object.ReferenceEquals(value, null))
{
writer.WriteNull(name);
}
else if (context.TryRegisterExternalReference(value, out index))
{
writer.WriteExternalReference(name, index);
}
else if (context.TryRegisterExternalReference(value, out guid))
{
writer.WriteExternalReference(name, guid);
}
else if (context.TryRegisterExternalReference(value, out strId))
{
writer.WriteExternalReference(name, strId);
}
else if (context.TryRegisterInternalReference(value, out id))
{
Type type = value.GetType(); // Get type of actual stored object
if (ComplexTypeMayBeBoxedValueType && FormatterUtilities.IsPrimitiveType(type))
// It's a boxed primitive type
{
try
{
writer.BeginReferenceNode(name, type, id);
var serializer = Serializer.Get(type);
serializer.WriteValueWeak(value, writer);
}
catch (SerializationAbortException ex)
{
endNode = false;
throw ex;
}
finally
{
if (endNode)
{
writer.EndNode(name);
}
}
}
else
{
IFormatter formatter;
if (object.ReferenceEquals(type, TypeOf_T))
{
formatter = GetBaseFormatter(policy);
}
else
{
formatter = FormatterLocator.GetFormatter(type, policy);
}
try
{
writer.BeginReferenceNode(name, type, id);
formatter.Serialize(value, writer);
}
catch (SerializationAbortException ex)
{
endNode = false;
throw ex;
}
finally
{
if (endNode)
{
writer.EndNode(name);
}
}
}
}
else
{
writer.WriteInternalReference(name, id);
}
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5a2a43b51cef79fd0e85028650394b55
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,68 @@
//-----------------------------------------------------------------------
// <copyright file="DecimalSerializer.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
/// <summary>
/// Serializer for the <see cref="decimal"/> type.
/// </summary>
/// <seealso cref="Serializer{System.Decimal}" />
public sealed class DecimalSerializer : Serializer<decimal>
{
/// <summary>
/// Reads a value of type <see cref="decimal" />.
/// </summary>
/// <param name="reader">The reader to use.</param>
/// <returns>
/// The value which has been read.
/// </returns>
public override decimal ReadValue(IDataReader reader)
{
string name;
var entry = reader.PeekEntry(out name);
if (entry == EntryType.FloatingPoint || entry == EntryType.Integer)
{
decimal value;
if (reader.ReadDecimal(out value) == false)
{
reader.Context.Config.DebugContext.LogWarning("Failed to read entry of type " + entry.ToString());
}
return value;
}
else
{
reader.Context.Config.DebugContext.LogWarning("Expected entry of type " + EntryType.FloatingPoint.ToString() + " or " + EntryType.Integer.ToString() + ", but got entry of type " + entry.ToString());
reader.SkipEntry();
return default(decimal);
}
}
/// <summary>
/// Writes a value of type <see cref="decimal" />.
/// </summary>
/// <param name="name">The name of the value to write.</param>
/// <param name="value">The value to write.</param>
/// <param name="writer">The writer to use.</param>
public override void WriteValue(string name, decimal value, IDataWriter writer)
{
FireOnSerializedType();
writer.WriteDecimal(name, value);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 50c67937d611e4749188b838e4cff5dc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,68 @@
//-----------------------------------------------------------------------
// <copyright file="DoubleSerializer.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
/// <summary>
/// Serializer for the <see cref="double"/> type.
/// </summary>
/// <seealso cref="Serializer{System.Double}" />
public sealed class DoubleSerializer : Serializer<double>
{
/// <summary>
/// Reads a value of type <see cref="double" />.
/// </summary>
/// <param name="reader">The reader to use.</param>
/// <returns>
/// The value which has been read.
/// </returns>
public override double ReadValue(IDataReader reader)
{
string name;
var entry = reader.PeekEntry(out name);
if (entry == EntryType.FloatingPoint || entry == EntryType.Integer)
{
double value;
if (reader.ReadDouble(out value) == false)
{
reader.Context.Config.DebugContext.LogWarning("Failed to read entry '" + name + "' of type " + entry.ToString());
}
return value;
}
else
{
reader.Context.Config.DebugContext.LogWarning("Expected entry of type " + EntryType.FloatingPoint.ToString() + " or " + EntryType.Integer.ToString() + ", but got entry '" + name + "' of type " + entry.ToString());
reader.SkipEntry();
return default(double);
}
}
/// <summary>
/// Writes a value of type <see cref="double" />.
/// </summary>
/// <param name="name">The name of the value to write.</param>
/// <param name="value">The value to write.</param>
/// <param name="writer">The writer to use.</param>
public override void WriteValue(string name, double value, IDataWriter writer)
{
FireOnSerializedType();
writer.WriteDouble(name, value);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9fc4716f683bc313c24bfa537cdd97f6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,115 @@
//-----------------------------------------------------------------------
// <copyright file="EnumSerializer.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
using System;
/// <summary>
/// Serializer for all enums.
/// </summary>
/// <typeparam name="T">The type of the enum to serialize and deserialize.</typeparam>
/// <seealso cref="Serializer{T}" />
#if CSHARP_7_3_OR_NEWER
public unsafe sealed class EnumSerializer<T> : Serializer<T> where T : unmanaged, Enum
{
private static readonly int SizeOf_T = sizeof(T);
#else
public sealed class EnumSerializer<T> : Serializer<T>
{
static EnumSerializer()
{
if (typeof(T).IsEnum == false)
{
throw new Exception("Type " + typeof(T).Name + " is not an enum.");
}
}
#endif
/// <summary>
/// Reads an enum value of type <see cref="T" />.
/// </summary>
/// <param name="reader">The reader to use.</param>
/// <returns>
/// The value which has been read.
/// </returns>
public override T ReadValue(IDataReader reader)
{
string name;
var entry = reader.PeekEntry(out name);
if (entry == EntryType.Integer)
{
ulong value;
if (reader.ReadUInt64(out value) == false)
{
reader.Context.Config.DebugContext.LogWarning("Failed to read entry '" + name + "' of type " + entry.ToString());
}
#if CSHARP_7_3_OR_NEWER
return *(T*)&value;
#else
return (T)Enum.ToObject(typeof(T), value);
#endif
}
else
{
reader.Context.Config.DebugContext.LogWarning("Expected entry of type " + EntryType.Integer.ToString() + ", but got entry '" + name + "' of type " + entry.ToString());
reader.SkipEntry();
return default(T);
}
}
/// <summary>
/// Writes an enum value of type <see cref="T" />.
/// </summary>
/// <param name="name">The name of the value to write.</param>
/// <param name="value">The value to write.</param>
/// <param name="writer">The writer to use.</param>
public override void WriteValue(string name, T value, IDataWriter writer)
{
ulong ul;
FireOnSerializedType();
#if CSHARP_7_3_OR_NEWER
byte* toPtr = (byte*)&ul;
byte* fromPtr = (byte*)&value;
for (int i = 0; i < SizeOf_T; i++)
{
*toPtr++ = *fromPtr++;
}
#else
try
{
ul = Convert.ToUInt64(value as Enum);
}
catch (OverflowException)
{
unchecked
{
ul = (ulong)Convert.ToInt64(value as Enum);
}
}
#endif
writer.WriteUInt64(name, ul);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7a5d23b139cd8e692702aa431b071d07
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,72 @@
//-----------------------------------------------------------------------
// <copyright file="GuidSerializer.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
using System.Globalization;
namespace VRC.Udon.Serialization.OdinSerializer
{
using System;
/// <summary>
/// Serializer for the <see cref="Guid"/> type.
/// </summary>
/// <seealso cref="Serializer{System.Guid}" />
public sealed class GuidSerializer : Serializer<Guid>
{
/// <summary>
/// Reads a value of type <see cref="Guid" />.
/// </summary>
/// <param name="reader">The reader to use.</param>
/// <returns>
/// The value which has been read.
/// </returns>
public override Guid ReadValue(IDataReader reader)
{
string name;
var entry = reader.PeekEntry(out name);
if (entry == EntryType.Guid)
{
Guid value;
if (reader.ReadGuid(out value) == false)
{
reader.Context.Config.DebugContext.LogWarning("Failed to read entry '" + name + "' of type " + entry.ToString());
}
return value;
}
else
{
reader.Context.Config.DebugContext.LogWarning("Expected entry of type " + EntryType.Guid.ToString() + ", but got entry '" + name + "' of type " + entry.ToString());
reader.SkipEntry();
return default(Guid);
}
}
/// <summary>
/// Writes a value of type <see cref="Guid" />.
/// </summary>
/// <param name="name">The name of the value to write.</param>
/// <param name="value">The value to write.</param>
/// <param name="writer">The writer to use.</param>
public override void WriteValue(string name, Guid value, IDataWriter writer)
{
FireOnSerializedType();
writer.WriteGuid(name, value);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 19dcfa9f6a40979fc2b6c3ae0f24b67c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,68 @@
//-----------------------------------------------------------------------
// <copyright file="Int16Serializer.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
/// <summary>
/// Serializer for the <see cref="short"/> type.
/// </summary>
/// <seealso cref="Serializer{System.Int16}" />
public sealed class Int16Serializer : Serializer<short>
{
/// <summary>
/// Reads a value of type <see cref="short" />.
/// </summary>
/// <param name="reader">The reader to use.</param>
/// <returns>
/// The value which has been read.
/// </returns>
public override short ReadValue(IDataReader reader)
{
string name;
var entry = reader.PeekEntry(out name);
if (entry == EntryType.Integer)
{
short value;
if (reader.ReadInt16(out value) == false)
{
reader.Context.Config.DebugContext.LogWarning("Failed to read entry '" + name + "' of type " + entry.ToString());
}
return value;
}
else
{
reader.Context.Config.DebugContext.LogWarning("Expected entry of type " + EntryType.Integer.ToString() + ", but got entry '" + name + "' of type " + entry.ToString());
reader.SkipEntry();
return default(short);
}
}
/// <summary>
/// Writes a value of type <see cref="short" />.
/// </summary>
/// <param name="name">The name of the value to write.</param>
/// <param name="value">The value to write.</param>
/// <param name="writer">The writer to use.</param>
public override void WriteValue(string name, short value, IDataWriter writer)
{
FireOnSerializedType();
writer.WriteInt16(name, value);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d280b44f7c75a9a18484a84745998130
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,68 @@
//-----------------------------------------------------------------------
// <copyright file="Int32Serializer.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
/// <summary>
/// Serializer for the <see cref="int"/> type.
/// </summary>
/// <seealso cref="Serializer{System.Int32}" />
public sealed class Int32Serializer : Serializer<int>
{
/// <summary>
/// Reads a value of type <see cref="int" />.
/// </summary>
/// <param name="reader">The reader to use.</param>
/// <returns>
/// The value which has been read.
/// </returns>
public override int ReadValue(IDataReader reader)
{
string name;
var entry = reader.PeekEntry(out name);
if (entry == EntryType.Integer)
{
int value;
if (reader.ReadInt32(out value) == false)
{
reader.Context.Config.DebugContext.LogWarning("Failed to read entry '" + name + "' of type " + entry.ToString());
}
return value;
}
else
{
reader.Context.Config.DebugContext.LogWarning("Expected entry of type " + EntryType.Integer.ToString() + ", but got entry '" + name + "' of type " + entry.ToString());
reader.SkipEntry();
return default(int);
}
}
/// <summary>
/// Writes a value of type <see cref="int" />.
/// </summary>
/// <param name="name">The name of the value to write.</param>
/// <param name="value">The value to write.</param>
/// <param name="writer">The writer to use.</param>
public override void WriteValue(string name, int value, IDataWriter writer)
{
FireOnSerializedType();
writer.WriteInt32(name, value);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: eafebb70813195e03b1ba467931eb686
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,68 @@
//-----------------------------------------------------------------------
// <copyright file="Int64Serializer.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
/// <summary>
/// Serializer for the <see cref="long"/> type.
/// </summary>
/// <seealso cref="Serializer{System.Int64}" />
public sealed class Int64Serializer : Serializer<long>
{
/// <summary>
/// Reads a value of type <see cref="long" />.
/// </summary>
/// <param name="reader">The reader to use.</param>
/// <returns>
/// The value which has been read.
/// </returns>
public override long ReadValue(IDataReader reader)
{
string name;
var entry = reader.PeekEntry(out name);
if (entry == EntryType.Integer)
{
long value;
if (reader.ReadInt64(out value) == false)
{
reader.Context.Config.DebugContext.LogWarning("Failed to read entry '" + name + "' of type " + entry.ToString());
}
return value;
}
else
{
reader.Context.Config.DebugContext.LogWarning("Expected entry of type " + EntryType.Integer.ToString() + ", but got entry '" + name + "' of type " + entry.ToString());
reader.SkipEntry();
return default(long);
}
}
/// <summary>
/// Writes a value of type <see cref="long" />.
/// </summary>
/// <param name="name">The name of the value to write.</param>
/// <param name="value">The value to write.</param>
/// <param name="writer">The writer to use.</param>
public override void WriteValue(string name, long value, IDataWriter writer)
{
FireOnSerializedType();
writer.WriteInt64(name, value);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: afe45c48508431a62aba886d943d8501
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,70 @@
//-----------------------------------------------------------------------
// <copyright file="IntPtrSerializer.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
using System;
/// <summary>
/// Serializer for the <see cref="IntPtr"/> type.
/// </summary>
/// <seealso cref="Serializer{System.IntPtr}" />
public sealed class IntPtrSerializer : Serializer<IntPtr>
{
/// <summary>
/// Reads a value of type <see cref="IntPtr" />.
/// </summary>
/// <param name="reader">The reader to use.</param>
/// <returns>
/// The value which has been read.
/// </returns>
public override IntPtr ReadValue(IDataReader reader)
{
string name;
var entry = reader.PeekEntry(out name);
if (entry == EntryType.Integer)
{
long value;
if (reader.ReadInt64(out value) == false)
{
reader.Context.Config.DebugContext.LogWarning("Failed to read entry '" + name + "' of type " + entry.ToString());
}
return new IntPtr(value);
}
else
{
reader.Context.Config.DebugContext.LogWarning("Expected entry of type " + EntryType.Integer.ToString() + ", but got entry '" + name + "' of type " + entry.ToString());
reader.SkipEntry();
return default(IntPtr);
}
}
/// <summary>
/// Writes a value of type <see cref="IntPtr" />.
/// </summary>
/// <param name="name">The name of the value to write.</param>
/// <param name="value">The value to write.</param>
/// <param name="writer">The writer to use.</param>
public override void WriteValue(string name, IntPtr value, IDataWriter writer)
{
FireOnSerializedType();
writer.WriteInt64(name, (long)value);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6ccaffe3090611c2ada67d49cf834771
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,68 @@
//-----------------------------------------------------------------------
// <copyright file="SByteSerializer.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
/// <summary>
/// Serializer for the <see cref="sbyte"/> type.
/// </summary>
/// <seealso cref="Serializer{System.SByte}" />
public sealed class SByteSerializer : Serializer<sbyte>
{
/// <summary>
/// Reads a value of type <see cref="sbyte" />.
/// </summary>
/// <param name="reader">The reader to use.</param>
/// <returns>
/// The value which has been read.
/// </returns>
public override sbyte ReadValue(IDataReader reader)
{
string name;
var entry = reader.PeekEntry(out name);
if (entry == EntryType.Integer)
{
sbyte value;
if (reader.ReadSByte(out value) == false)
{
reader.Context.Config.DebugContext.LogWarning("Failed to read entry '" + name + "' of type " + entry.ToString());
}
return value;
}
else
{
reader.Context.Config.DebugContext.LogWarning("Expected entry of type " + EntryType.Integer.ToString() + ", but got entry '" + name + "' of type " + entry.ToString());
reader.SkipEntry();
return default(sbyte);
}
}
/// <summary>
/// Writes a value of type <see cref="sbyte" />.
/// </summary>
/// <param name="name">The name of the value to write.</param>
/// <param name="value">The value to write.</param>
/// <param name="writer">The writer to use.</param>
public override void WriteValue(string name, sbyte value, IDataWriter writer)
{
FireOnSerializedType();
writer.WriteSByte(name, value);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 88f3ec418fdfdd7eabd6134f1de91991
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,311 @@
//-----------------------------------------------------------------------
// <copyright file="Serializer.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
using VRC.Udon.Serialization.OdinSerializer.Utilities;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
/// <summary>
/// Serializes and deserializes a given type, and wraps serialization and deserialization with all the proper calls to free formatters from tedious boilerplate.
/// <para />
/// Whenever serializing or deserializing anything, it is *strongly recommended* to use <see cref="Serializer.Get{T}"/> to get a proper wrapping serializer for that type.
/// <para />
/// NOTE: This class should NOT be inherited from; it is hard-coded into the system.
/// <para />
/// To extend the serialization system, instead create custom formatters, which are used by the <see cref="ComplexTypeSerializer{T}"/> class.
/// </summary>
public abstract class Serializer
{
private static readonly Dictionary<Type, Type> PrimitiveReaderWriterTypes = new Dictionary<Type, Type>()
{
{ typeof(char), typeof(CharSerializer) },
{ typeof(string), typeof(StringSerializer) },
{ typeof(sbyte), typeof(SByteSerializer) },
{ typeof(short), typeof(Int16Serializer) },
{ typeof(int), typeof(Int32Serializer) },
{ typeof(long), typeof(Int64Serializer) },
{ typeof(byte), typeof(ByteSerializer) },
{ typeof(ushort), typeof(UInt16Serializer) },
{ typeof(uint), typeof(UInt32Serializer) },
{ typeof(ulong), typeof(UInt64Serializer) },
{ typeof(decimal), typeof(DecimalSerializer) },
{ typeof(bool), typeof(BooleanSerializer) },
{ typeof(float), typeof(SingleSerializer) },
{ typeof(double), typeof(DoubleSerializer) },
{ typeof(IntPtr), typeof(IntPtrSerializer) },
{ typeof(UIntPtr), typeof(UIntPtrSerializer) },
{ typeof(Guid), typeof(GuidSerializer) }
};
private static readonly object LOCK = new object();
private static readonly Dictionary<Type, Serializer> ReaderWriterCache = new Dictionary<Type, Serializer>(FastTypeComparer.Instance);
#if UNITY_EDITOR
/// <summary>
/// Editor-only event that fires whenever a serializer serializes a type.
/// </summary>
public static event Action<Type> OnSerializedType;
#endif
/// <summary>
/// Fires the <see cref="OnSerializedType"/> event.
/// </summary>
[Conditional("UNITY_EDITOR")]
protected static void FireOnSerializedType(Type type)
{
#if UNITY_EDITOR
if (OnSerializedType != null)
{
OnSerializedType(type);
}
#endif
}
/// <summary>
/// Gets a <see cref="Serializer"/> for the given value. If the value is null, it will be treated as a value of type <see cref="object"/>.
/// </summary>
/// <param name="value">The value to get a <see cref="Serializer"/> for.</param>
/// <returns>A <see cref="Serializer"/> for the given value.</returns>
public static Serializer GetForValue(object value)
{
if (object.ReferenceEquals(value, null))
{
return Get(typeof(object));
}
else
{
return Get(value.GetType());
}
}
/// <summary>
/// Gets a <see cref="Serializer"/> for type T.
/// </summary>
/// <typeparam name="T">The type to get a <see cref="Serializer"/> for.</typeparam>
/// <returns>A <see cref="Serializer"/> for type T.</returns>
public static Serializer<T> Get<T>()
{
return (Serializer<T>)Serializer.Get(typeof(T));
}
/// <summary>
/// Gets a <see cref="Serializer"/> for the given type.
/// </summary>
/// <param name="type">The type to get a <see cref="Serializer"/> for.</param>
/// <returns>A <see cref="Serializer"/> for the given type.</returns>
/// <exception cref="System.ArgumentNullException">The type argument is null.</exception>
public static Serializer Get(Type type)
{
if (type == null)
{
throw new ArgumentNullException();
}
Serializer result;
lock (LOCK)
{
if (ReaderWriterCache.TryGetValue(type, out result) == false)
{
result = Create(type);
ReaderWriterCache.Add(type, result);
}
}
return result;
}
/// <summary>
/// Reads a value weakly, casting it into object. Use this method if you don't know what type you're going to be working with at compile time.
/// </summary>
/// <param name="reader">The reader to use.</param>
/// <returns>The value which has been read.</returns>
public abstract object ReadValueWeak(IDataReader reader);
/// <summary>
/// Writes a weakly typed value. Use this method if you don't know what type you're going to be working with at compile time.
/// </summary>
/// <param name="value">The value to write.</param>
/// <param name="writer">The writer to use.</param>
public void WriteValueWeak(object value, IDataWriter writer)
{
this.WriteValueWeak(null, value, writer);
}
/// <summary>
/// Writes a weakly typed value with a given name. Use this method if you don't know what type you're going to be working with at compile time.
/// </summary>
/// <param name="name">The name of the value to write.</param>
/// <param name="value">The value to write.</param>
/// <param name="writer">The writer to use.</param>
public abstract void WriteValueWeak(string name, object value, IDataWriter writer);
private static Serializer Create(Type type)
{
try
{
Type resultType = null;
if (type.IsEnum)
{
resultType = typeof(EnumSerializer<>).MakeGenericType(type);
}
else if (FormatterUtilities.IsPrimitiveType(type))
{
try
{
resultType = PrimitiveReaderWriterTypes[type];
}
catch (KeyNotFoundException)
{
UnityEngine.Debug.LogError("Failed to find primitive serializer for " + type.Name);
}
}
else
{
resultType = typeof(ComplexTypeSerializer<>).MakeGenericType(type);
}
return (Serializer)Activator.CreateInstance(resultType);
}
// System.ExecutionEngineException is marked obsolete in .NET 4.6
// That's all very good for .NET, but Unity still uses it!
#pragma warning disable 618
catch (TargetInvocationException ex)
{
if (ex.GetBaseException() is ExecutionEngineException)
{
LogAOTError(type, ex.GetBaseException() as ExecutionEngineException);
return null;
}
else
{
throw ex;
}
}
catch (TypeInitializationException ex)
{
if (ex.GetBaseException() is ExecutionEngineException)
{
LogAOTError(type, ex.GetBaseException() as ExecutionEngineException);
return null;
}
else
{
throw ex;
}
}
catch (ExecutionEngineException ex)
{
LogAOTError(type, ex);
return null;
}
}
private static void LogAOTError(Type type, ExecutionEngineException ex)
{
UnityEngine.Debug.LogError("No AOT serializer was pre-generated for the type '" + type.GetNiceFullName() + "'. " +
"Please use Odin's AOT generation feature to generate an AOT dll before building, and ensure that '" +
type.GetNiceFullName() + "' is in the list of supported types after a scan. If it is not, please " +
"report an issue and add it to the list manually.");
throw new SerializationAbortException("AOT serializer was missing for type '" + type.GetNiceFullName() + "'.");
}
}
#pragma warning restore 618
/// <summary>
/// Serializes and deserializes the type <see cref="T"/>, and wraps serialization and deserialization with all the proper calls to free formatters from tedious boilerplate.
/// <para />
/// Whenever serializing or deserializing anything, it is *strongly recommended* to use <see cref="Serializer.Get{T}"/> to get a proper wrapping serializer for that type.
/// <para />
/// NOTE: This class should NOT be inherited from; it is hard-coded into the system.
/// <para />
/// To extend the serialization system, instead create custom formatters, which are used by the <see cref="ComplexTypeSerializer{T}"/> class.
/// </summary>
/// <typeparam name="T">The type which the <see cref="Serializer{T}"/> can serialize and deserialize.</typeparam>
public abstract class Serializer<T> : Serializer
{
/// <summary>
/// Reads a value of type <see cref="T"/> weakly, casting it into object. Use this method if you don't know what type you're going to be working with at compile time.
/// </summary>
/// <param name="reader">The reader to use.</param>
/// <returns>
/// The value which has been read.
/// </returns>
public override object ReadValueWeak(IDataReader reader)
{
return this.ReadValue(reader);
}
/// <summary>
/// Writes a weakly typed value of type <see cref="T"/> with a given name. Use this method if you don't know what type you're going to be working with at compile time.
/// </summary>
/// <param name="name">The name of the value to write.</param>
/// <param name="value">The value to write.</param>
/// <param name="writer">The writer to use.</param>
public override void WriteValueWeak(string name, object value, IDataWriter writer)
{
this.WriteValue(name, (T)value, writer);
}
/// <summary>
/// Reads a value of type <see cref="T"/>.
/// </summary>
/// <param name="reader">The reader to use.</param>
/// <returns>
/// The value which has been read.
/// </returns>
public abstract T ReadValue(IDataReader reader);
/// <summary>
/// Writes a value of type <see cref="T"/>.
/// </summary>
/// <param name="value">The value to write.</param>
/// <param name="writer">The writer to use.</param>
public void WriteValue(T value, IDataWriter writer)
{
this.WriteValue(null, value, writer);
}
/// <summary>
/// Writes a value of type <see cref="T"/> with a given name.
/// </summary>
/// <param name="name">The name of the value to write.</param>
/// <param name="value">The value to write.</param>
/// <param name="writer">The writer to use.</param>
public abstract void WriteValue(string name, T value, IDataWriter writer);
/// <summary>
/// Fires the <see cref="OnSerializedType"/> event with the T generic argument of the serializer.
/// </summary>
[Conditional("UNITY_EDITOR")]
protected static void FireOnSerializedType()
{
FireOnSerializedType(typeof(T));
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 29261eaea99f2d34c42cdc0b04f95daa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,68 @@
//-----------------------------------------------------------------------
// <copyright file="SingleSerializer.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
/// <summary>
/// Serializer for the <see cref="float"/> type.
/// </summary>
/// <seealso cref="Serializer{System.Single}" />
public sealed class SingleSerializer : Serializer<float>
{
/// <summary>
/// Reads a value of type <see cref="float" />.
/// </summary>
/// <param name="reader">The reader to use.</param>
/// <returns>
/// The value which has been read.
/// </returns>
public override float ReadValue(IDataReader reader)
{
string name;
var entry = reader.PeekEntry(out name);
if (entry == EntryType.FloatingPoint || entry == EntryType.Integer)
{
float value;
if (reader.ReadSingle(out value) == false)
{
reader.Context.Config.DebugContext.LogWarning("Failed to read entry '" + name + "' of type " + entry.ToString());
}
return value;
}
else
{
reader.Context.Config.DebugContext.LogWarning("Expected entry of type " + EntryType.FloatingPoint.ToString() + " or " + EntryType.Integer.ToString() + ", but got entry '" + name + "' of type " + entry.ToString());
reader.SkipEntry();
return default(float);
}
}
/// <summary>
/// Writes a value of type <see cref="float" />.
/// </summary>
/// <param name="name">The name of the value to write.</param>
/// <param name="value">The value to write.</param>
/// <param name="writer">The writer to use.</param>
public override void WriteValue(string name, float value, IDataWriter writer)
{
FireOnSerializedType();
writer.WriteSingle(name, value);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7aa356971fd0b66eb59875b278fa7f03
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,84 @@
//-----------------------------------------------------------------------
// <copyright file="StringSerializer.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
/// <summary>
/// Serializer for the <see cref="string"/> type.
/// </summary>
/// <seealso cref="Serializer{System.String}" />
public sealed class StringSerializer : Serializer<string>
{
/// <summary>
/// Reads a value of type <see cref="string" />.
/// </summary>
/// <param name="reader">The reader to use.</param>
/// <returns>
/// The value which has been read.
/// </returns>
public override string ReadValue(IDataReader reader)
{
string name;
var entry = reader.PeekEntry(out name);
if (entry == EntryType.String)
{
string value;
if (reader.ReadString(out value) == false)
{
reader.Context.Config.DebugContext.LogWarning("Failed to read entry '" + name + "' of type " + entry.ToString());
}
return value;
}
else if (entry == EntryType.Null)
{
if (reader.ReadNull() == false)
{
reader.Context.Config.DebugContext.LogWarning("Failed to read entry '" + name + "' of type " + entry.ToString());
}
return null;
}
else
{
reader.Context.Config.DebugContext.LogWarning("Expected entry of type " + EntryType.String.ToString() + " or " + EntryType.Null.ToString() + ", but got entry '" + name + "' of type " + entry.ToString());
reader.SkipEntry();
return default(string);
}
}
/// <summary>
/// Writes a value of type <see cref="string" />.
/// </summary>
/// <param name="name">The name of the value to write.</param>
/// <param name="value">The value to write.</param>
/// <param name="writer">The writer to use.</param>
public override void WriteValue(string name, string value, IDataWriter writer)
{
FireOnSerializedType();
if (value == null)
{
writer.WriteNull(name);
}
else
{
writer.WriteString(name, value);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 85996580a8691185d06ec342c5c43747
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,68 @@
//-----------------------------------------------------------------------
// <copyright file="UInt16Serializer.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
/// <summary>
/// Serializer for the <see cref="ushort"/> type.
/// </summary>
/// <seealso cref="Serializer{System.UInt16}" />
public sealed class UInt16Serializer : Serializer<ushort>
{
/// <summary>
/// Reads a value of type <see cref="ushort" />.
/// </summary>
/// <param name="reader">The reader to use.</param>
/// <returns>
/// The value which has been read.
/// </returns>
public override ushort ReadValue(IDataReader reader)
{
string name;
var entry = reader.PeekEntry(out name);
if (entry == EntryType.Integer)
{
ushort value;
if (reader.ReadUInt16(out value) == false)
{
reader.Context.Config.DebugContext.LogWarning("Failed to read entry '" + name + "' of type " + entry.ToString());
}
return value;
}
else
{
reader.Context.Config.DebugContext.LogWarning("Expected entry of type " + EntryType.Integer.ToString() + ", but got entry '" + name + "' of type " + entry.ToString());
reader.SkipEntry();
return default(ushort);
}
}
/// <summary>
/// Writes a value of type <see cref="ulong" />.
/// </summary>
/// <param name="name">The name of the value to write.</param>
/// <param name="value">The value to write.</param>
/// <param name="writer">The writer to use.</param>
public override void WriteValue(string name, ushort value, IDataWriter writer)
{
FireOnSerializedType();
writer.WriteUInt16(name, value);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3936194ea64890e11a7db8474eb0bbcf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,68 @@
//-----------------------------------------------------------------------
// <copyright file="UInt32Serializer.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
/// <summary>
/// Serializer for the <see cref="uint"/> type.
/// </summary>
/// <seealso cref="Serializer{System.UInt32}" />
public sealed class UInt32Serializer : Serializer<uint>
{
/// <summary>
/// Reads a value of type <see cref="uint" />.
/// </summary>
/// <param name="reader">The reader to use.</param>
/// <returns>
/// The value which has been read.
/// </returns>
public override uint ReadValue(IDataReader reader)
{
string name;
var entry = reader.PeekEntry(out name);
if (entry == EntryType.Integer)
{
uint value;
if (reader.ReadUInt32(out value) == false)
{
reader.Context.Config.DebugContext.LogWarning("Failed to read entry '" + name + "' of type " + entry.ToString());
}
return value;
}
else
{
reader.Context.Config.DebugContext.LogWarning("Expected entry of type " + EntryType.Integer.ToString() + ", but got entry '" + name + "' of type " + entry.ToString());
reader.SkipEntry();
return default(uint);
}
}
/// <summary>
/// Writes a value of type <see cref="uint" />.
/// </summary>
/// <param name="name">The name of the value to write.</param>
/// <param name="value">The value to write.</param>
/// <param name="writer">The writer to use.</param>
public override void WriteValue(string name, uint value, IDataWriter writer)
{
FireOnSerializedType();
writer.WriteUInt32(name, value);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f30e426f88b471e498dd1853b7bbaee6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,68 @@
//-----------------------------------------------------------------------
// <copyright file="UInt64Serializer.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
/// <summary>
/// Serializer for the <see cref="ulong"/> type.
/// </summary>
/// <seealso cref="Serializer{System.UInt64}" />
public sealed class UInt64Serializer : Serializer<ulong>
{
/// <summary>
/// Reads a value of type <see cref="ulong" />.
/// </summary>
/// <param name="reader">The reader to use.</param>
/// <returns>
/// The value which has been read.
/// </returns>
public override ulong ReadValue(IDataReader reader)
{
string name;
var entry = reader.PeekEntry(out name);
if (entry == EntryType.Integer)
{
ulong value;
if (reader.ReadUInt64(out value) == false)
{
reader.Context.Config.DebugContext.LogWarning("Failed to read entry '" + name + "' of type " + entry.ToString());
}
return value;
}
else
{
reader.Context.Config.DebugContext.LogWarning("Expected entry of type " + EntryType.Integer.ToString() + ", but got entry '" + name + "' of type " + entry.ToString());
reader.SkipEntry();
return default(ulong);
}
}
/// <summary>
/// Writes a value of type <see cref="ulong" />.
/// </summary>
/// <param name="name">The name of the value to write.</param>
/// <param name="value">The value to write.</param>
/// <param name="writer">The writer to use.</param>
public override void WriteValue(string name, ulong value, IDataWriter writer)
{
FireOnSerializedType();
writer.WriteUInt64(name, value);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f55c085325e12800428d01e3535cb297
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,70 @@
//-----------------------------------------------------------------------
// <copyright file="IntPtrSerializer.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
using System;
/// <summary>
/// Serializer for the <see cref="UIntPtr"/> type.
/// </summary>
/// <seealso cref="Serializer{System.UIntPtr}" />
public sealed class UIntPtrSerializer : Serializer<UIntPtr>
{
/// <summary>
/// Reads a value of type <see cref="UIntPtr" />.
/// </summary>
/// <param name="reader">The reader to use.</param>
/// <returns>
/// The value which has been read.
/// </returns>
public override UIntPtr ReadValue(IDataReader reader)
{
string name;
var entry = reader.PeekEntry(out name);
if (entry == EntryType.Integer)
{
ulong value;
if (reader.ReadUInt64(out value) == false)
{
reader.Context.Config.DebugContext.LogWarning("Failed to read entry '" + name + "' of type " + entry.ToString());
}
return new UIntPtr(value);
}
else
{
reader.Context.Config.DebugContext.LogWarning("Expected entry of type " + EntryType.Integer.ToString() + ", but got entry '" + name + "' of type " + entry.ToString());
reader.SkipEntry();
return default(UIntPtr);
}
}
/// <summary>
/// Writes a value of type <see cref="UIntPtr" />.
/// </summary>
/// <param name="name">The name of the value to write.</param>
/// <param name="value">The value to write.</param>
/// <param name="writer">The writer to use.</param>
public override void WriteValue(string name, UIntPtr value, IDataWriter writer)
{
FireOnSerializedType();
writer.WriteUInt64(name, (ulong)value);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0ee9dd19c234e4b16c835b9188459e36
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: