167 lines
9.9 KiB
C#
167 lines
9.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace LeanCloud.Storage.Internal
|
|
{
|
|
public class AVIncrementOperation : IAVFieldOperation
|
|
{
|
|
private static readonly IDictionary<Tuple<Type, Type>, Func<object, object, object>> adders;
|
|
|
|
static AVIncrementOperation()
|
|
{
|
|
// Defines adders for all of the implicit conversions: http://msdn.microsoft.com/en-US/library/y5b434w4(v=vs.80).aspx
|
|
adders = new Dictionary<Tuple<Type, Type>, Func<object, object, object>> {
|
|
{new Tuple<Type, Type>(typeof(sbyte), typeof(sbyte)), (left, right) => (sbyte)left + (sbyte)right},
|
|
{new Tuple<Type, Type>(typeof(sbyte), typeof(short)), (left, right) => (sbyte)left + (short)right},
|
|
{new Tuple<Type, Type>(typeof(sbyte), typeof(int)), (left, right) => (sbyte)left + (int)right},
|
|
{new Tuple<Type, Type>(typeof(sbyte), typeof(long)), (left, right) => (sbyte)left + (long)right},
|
|
{new Tuple<Type, Type>(typeof(sbyte), typeof(float)), (left, right) => (sbyte)left + (float)right},
|
|
{new Tuple<Type, Type>(typeof(sbyte), typeof(double)), (left, right) => (sbyte)left + (double)right},
|
|
{new Tuple<Type, Type>(typeof(sbyte), typeof(decimal)), (left, right) => (sbyte)left + (decimal)right},
|
|
{new Tuple<Type, Type>(typeof(byte), typeof(byte)), (left, right) => (byte)left + (byte)right},
|
|
{new Tuple<Type, Type>(typeof(byte), typeof(short)), (left, right) => (byte)left + (short)right},
|
|
{new Tuple<Type, Type>(typeof(byte), typeof(ushort)), (left, right) => (byte)left + (ushort)right},
|
|
{new Tuple<Type, Type>(typeof(byte), typeof(int)), (left, right) => (byte)left + (int)right},
|
|
{new Tuple<Type, Type>(typeof(byte), typeof(uint)), (left, right) => (byte)left + (uint)right},
|
|
{new Tuple<Type, Type>(typeof(byte), typeof(long)), (left, right) => (byte)left + (long)right},
|
|
{new Tuple<Type, Type>(typeof(byte), typeof(ulong)), (left, right) => (byte)left + (ulong)right},
|
|
{new Tuple<Type, Type>(typeof(byte), typeof(float)), (left, right) => (byte)left + (float)right},
|
|
{new Tuple<Type, Type>(typeof(byte), typeof(double)), (left, right) => (byte)left + (double)right},
|
|
{new Tuple<Type, Type>(typeof(byte), typeof(decimal)), (left, right) => (byte)left + (decimal)right},
|
|
{new Tuple<Type, Type>(typeof(short), typeof(short)), (left, right) => (short)left + (short)right},
|
|
{new Tuple<Type, Type>(typeof(short), typeof(int)), (left, right) => (short)left + (int)right},
|
|
{new Tuple<Type, Type>(typeof(short), typeof(long)), (left, right) => (short)left + (long)right},
|
|
{new Tuple<Type, Type>(typeof(short), typeof(float)), (left, right) => (short)left + (float)right},
|
|
{new Tuple<Type, Type>(typeof(short), typeof(double)), (left, right) => (short)left + (double)right},
|
|
{new Tuple<Type, Type>(typeof(short), typeof(decimal)), (left, right) => (short)left + (decimal)right},
|
|
{new Tuple<Type, Type>(typeof(ushort), typeof(ushort)), (left, right) => (ushort)left + (ushort)right},
|
|
{new Tuple<Type, Type>(typeof(ushort), typeof(int)), (left, right) => (ushort)left + (int)right},
|
|
{new Tuple<Type, Type>(typeof(ushort), typeof(uint)), (left, right) => (ushort)left + (uint)right},
|
|
{new Tuple<Type, Type>(typeof(ushort), typeof(long)), (left, right) => (ushort)left + (long)right},
|
|
{new Tuple<Type, Type>(typeof(ushort), typeof(ulong)), (left, right) => (ushort)left + (ulong)right},
|
|
{new Tuple<Type, Type>(typeof(ushort), typeof(float)), (left, right) => (ushort)left + (float)right},
|
|
{new Tuple<Type, Type>(typeof(ushort), typeof(double)), (left, right) => (ushort)left + (double)right},
|
|
{new Tuple<Type, Type>(typeof(ushort), typeof(decimal)), (left, right) => (ushort)left + (decimal)right},
|
|
{new Tuple<Type, Type>(typeof(int), typeof(int)), (left, right) => (int)left + (int)right},
|
|
{new Tuple<Type, Type>(typeof(int), typeof(long)), (left, right) => (int)left + (long)right},
|
|
{new Tuple<Type, Type>(typeof(int), typeof(float)), (left, right) => (int)left + (float)right},
|
|
{new Tuple<Type, Type>(typeof(int), typeof(double)), (left, right) => (int)left + (double)right},
|
|
{new Tuple<Type, Type>(typeof(int), typeof(decimal)), (left, right) => (int)left + (decimal)right},
|
|
{new Tuple<Type, Type>(typeof(uint), typeof(uint)), (left, right) => (uint)left + (uint)right},
|
|
{new Tuple<Type, Type>(typeof(uint), typeof(long)), (left, right) => (uint)left + (long)right},
|
|
{new Tuple<Type, Type>(typeof(uint), typeof(ulong)), (left, right) => (uint)left + (ulong)right},
|
|
{new Tuple<Type, Type>(typeof(uint), typeof(float)), (left, right) => (uint)left + (float)right},
|
|
{new Tuple<Type, Type>(typeof(uint), typeof(double)), (left, right) => (uint)left + (double)right},
|
|
{new Tuple<Type, Type>(typeof(uint), typeof(decimal)), (left, right) => (uint)left + (decimal)right},
|
|
{new Tuple<Type, Type>(typeof(long), typeof(long)), (left, right) => (long)left + (long)right},
|
|
{new Tuple<Type, Type>(typeof(long), typeof(float)), (left, right) => (long)left + (float)right},
|
|
{new Tuple<Type, Type>(typeof(long), typeof(double)), (left, right) => (long)left + (double)right},
|
|
{new Tuple<Type, Type>(typeof(long), typeof(decimal)), (left, right) => (long)left + (decimal)right},
|
|
{new Tuple<Type, Type>(typeof(char), typeof(char)), (left, right) => (char)left + (char)right},
|
|
{new Tuple<Type, Type>(typeof(char), typeof(ushort)), (left, right) => (char)left + (ushort)right},
|
|
{new Tuple<Type, Type>(typeof(char), typeof(int)), (left, right) => (char)left + (int)right},
|
|
{new Tuple<Type, Type>(typeof(char), typeof(uint)), (left, right) => (char)left + (uint)right},
|
|
{new Tuple<Type, Type>(typeof(char), typeof(long)), (left, right) => (char)left + (long)right},
|
|
{new Tuple<Type, Type>(typeof(char), typeof(ulong)), (left, right) => (char)left + (ulong)right},
|
|
{new Tuple<Type, Type>(typeof(char), typeof(float)), (left, right) => (char)left + (float)right},
|
|
{new Tuple<Type, Type>(typeof(char), typeof(double)), (left, right) => (char)left + (double)right},
|
|
{new Tuple<Type, Type>(typeof(char), typeof(decimal)), (left, right) => (char)left + (decimal)right},
|
|
{new Tuple<Type, Type>(typeof(float), typeof(float)), (left, right) => (float)left + (float)right},
|
|
{new Tuple<Type, Type>(typeof(float), typeof(double)), (left, right) => (float)left + (double)right},
|
|
{new Tuple<Type, Type>(typeof(ulong), typeof(ulong)), (left, right) => (ulong)left + (ulong)right},
|
|
{new Tuple<Type, Type>(typeof(ulong), typeof(float)), (left, right) => (ulong)left + (float)right},
|
|
{new Tuple<Type, Type>(typeof(ulong), typeof(double)), (left, right) => (ulong)left + (double)right},
|
|
{new Tuple<Type, Type>(typeof(ulong), typeof(decimal)), (left, right) => (ulong)left + (decimal)right},
|
|
{new Tuple<Type, Type>(typeof(double), typeof(double)), (left, right) => (double)left + (double)right},
|
|
{new Tuple<Type, Type>(typeof(decimal), typeof(decimal)), (left, right) => (decimal)left + (decimal)right}
|
|
};
|
|
// Generate the adders in the other direction
|
|
foreach (var pair in adders.Keys.ToList())
|
|
{
|
|
if (pair.Item1.Equals(pair.Item2))
|
|
{
|
|
continue;
|
|
}
|
|
var reversePair = new Tuple<Type, Type>(pair.Item2, pair.Item1);
|
|
var func = adders[pair];
|
|
adders[reversePair] = (left, right) => func(right, left);
|
|
}
|
|
}
|
|
|
|
private object amount;
|
|
|
|
public AVIncrementOperation(object amount)
|
|
{
|
|
this.amount = amount;
|
|
}
|
|
|
|
public object Encode()
|
|
{
|
|
return new Dictionary<string, object>
|
|
{
|
|
{"__op", "Increment"},
|
|
{"amount", amount}
|
|
};
|
|
}
|
|
|
|
private static object Add(object obj1, object obj2)
|
|
{
|
|
Func<object, object, object> adder;
|
|
if (adders.TryGetValue(new Tuple<Type, Type>(obj1.GetType(), obj2.GetType()), out adder))
|
|
{
|
|
return adder(obj1, obj2);
|
|
}
|
|
throw new InvalidCastException("Cannot add " + obj1.GetType() + " to " + obj2.GetType());
|
|
}
|
|
|
|
public IAVFieldOperation MergeWithPrevious(IAVFieldOperation previous)
|
|
{
|
|
if (previous == null)
|
|
{
|
|
return this;
|
|
}
|
|
if (previous is AVDeleteOperation)
|
|
{
|
|
return new AVSetOperation(amount);
|
|
}
|
|
if (previous is AVSetOperation)
|
|
{
|
|
var otherAmount = ((AVSetOperation)previous).Value;
|
|
if (otherAmount is string)
|
|
{
|
|
throw new InvalidOperationException("Cannot increment a non-number type.");
|
|
}
|
|
var myAmount = amount;
|
|
return new AVSetOperation(Add(otherAmount, myAmount));
|
|
}
|
|
if (previous is AVIncrementOperation)
|
|
{
|
|
object otherAmount = ((AVIncrementOperation)previous).Amount;
|
|
object myAmount = amount;
|
|
return new AVIncrementOperation(Add(otherAmount, myAmount));
|
|
}
|
|
throw new InvalidOperationException("Operation is invalid after previous operation.");
|
|
}
|
|
|
|
public object Apply(object oldValue, string key)
|
|
{
|
|
if (oldValue is string)
|
|
{
|
|
throw new InvalidOperationException("Cannot increment a non-number type.");
|
|
}
|
|
object otherAmount = oldValue ?? 0;
|
|
object myAmount = amount;
|
|
return Add(otherAmount, myAmount);
|
|
}
|
|
|
|
public object Amount
|
|
{
|
|
get
|
|
{
|
|
return amount;
|
|
}
|
|
}
|
|
}
|
|
}
|