csharp-sdk-upm/Storage/Source/Internal/Encoding/AVEncoder.cs

139 lines
4.4 KiB
C#

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using LeanCloud.Utilities;
using LeanCloud.Storage.Internal;
namespace LeanCloud.Storage.Internal
{
/// <summary>
/// A <c>AVEncoder</c> can be used to transform objects such as <see cref="AVObject"/> into JSON
/// data structures.
/// </summary>
/// <seealso cref="AVDecoder"/>
public abstract class AVEncoder
{
#if UNITY
private static readonly bool isCompiledByIL2CPP = AppDomain.CurrentDomain.FriendlyName.Equals("IL2CPP Root Domain");
#else
private static readonly bool isCompiledByIL2CPP = false;
#endif
public static bool IsValidType(object value)
{
return value == null ||
ReflectionHelpers.IsPrimitive(value.GetType()) ||
value is string ||
value is AVObject ||
value is AVACL ||
value is AVFile ||
value is AVGeoPoint ||
value is AVRelationBase ||
value is DateTime ||
value is byte[] ||
Conversion.As<IDictionary<string, object>>(value) != null ||
Conversion.As<IList<object>>(value) != null;
}
public object Encode(object value)
{
// If this object has a special encoding, encode it and return the
// encoded object. Otherwise, just return the original object.
if (value is DateTime)
{
return new Dictionary<string, object>
{
{
"iso", ((DateTime)value).ToUniversalTime().ToString(AVClient.DateFormatStrings.First(), CultureInfo.InvariantCulture)
},
{
"__type", "Date"
}
};
}
if (value is AVFile)
{
var file = value as AVFile;
return new Dictionary<string, object>
{
{"__type", "Pointer"},
{ "className", "_File"},
{ "objectId", file.ObjectId}
};
}
var bytes = value as byte[];
if (bytes != null)
{
return new Dictionary<string, object>
{
{ "__type", "Bytes"},
{ "base64", Convert.ToBase64String(bytes)}
};
}
var obj = value as AVObject;
if (obj != null)
{
return EncodeAVObject(obj);
}
var jsonConvertible = value as IJsonConvertible;
if (jsonConvertible != null)
{
return jsonConvertible.ToJSON();
}
var dict = Conversion.As<IDictionary<string, object>>(value);
if (dict != null)
{
var json = new Dictionary<string, object>();
foreach (var pair in dict)
{
json[pair.Key] = Encode(pair.Value);
}
return json;
}
var list = Conversion.As<IList<object>>(value);
if (list != null)
{
return EncodeList(list);
}
// TODO (hallucinogen): convert IAVFieldOperation to IJsonConvertible
var operation = value as IAVFieldOperation;
if (operation != null)
{
return operation.Encode();
}
return value;
}
protected abstract IDictionary<string, object> EncodeAVObject(AVObject value);
private object EncodeList(IList<object> list)
{
var newArray = new List<object>();
// We need to explicitly cast `list` to `List<object>` rather than
// `IList<object>` because IL2CPP is stricter than the usual Unity AOT compiler pipeline.
if (isCompiledByIL2CPP && list.GetType().IsArray)
{
list = new List<object>(list);
}
foreach (var item in list)
{
if (!IsValidType(item))
{
throw new ArgumentException("Invalid type for value in an array");
}
newArray.Add(Encode(item));
}
return newArray;
}
}
}