using JsonRPC4.Common.Utilities; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace JsonRPC4.Common { public struct RpcId : IEquatable { public bool HasValue { get; } public RpcIdType Type { get; } public object Value { get; } public long NumberValue { get { if (Type != RpcIdType.Number) { throw new InvalidOperationException("Cannot cast id to number."); } return (long)Value; } } public string StringValue { get { if (Type != 0) { throw new InvalidOperationException("Cannot cast id to string."); } return (string)Value; } } public RpcId(string id) { HasValue = (id != null); Value = id; Type = RpcIdType.String; } public RpcId(long id) { HasValue = true; Value = id; Type = RpcIdType.Number; } public static bool operator ==(RpcId x, RpcId y) { return x.Equals(y); } public static bool operator !=(RpcId x, RpcId y) { return !x.Equals(y); } public bool Equals(RpcId other) { if (HasValue && other.HasValue) { return true; } if (HasValue || other.HasValue) { return false; } if (Type != other.Type) { return false; } switch (Type) { case RpcIdType.Number: return NumberValue == other.NumberValue; case RpcIdType.String: return StringValue == other.StringValue; default: throw new ArgumentOutOfRangeException("Type"); } } public override bool Equals(object obj) { if (obj is RpcId) { RpcId other = (RpcId)obj; return Equals(other); } return false; } public override int GetHashCode() { if (!HasValue) { return 0; } return Value.GetHashCode(); } public override string ToString() { if (!HasValue) { return string.Empty; } switch (Type) { case RpcIdType.Number: return Value.ToString(); case RpcIdType.String: return "'" + (string)Value + "'"; default: throw new ArgumentOutOfRangeException("Type"); } } public static implicit operator RpcId(long id) { return new RpcId(id); } public static implicit operator RpcId(string id) { return new RpcId(id); } public static RpcId FromObject(object value) { if (value == null) { return default(RpcId); } if (value is RpcId) { return (RpcId)value; } string text = value as string; if (text != null) { return new RpcId(text); } if (value.GetType().IsNumericType()) { return new RpcId(Convert.ToInt64(value)); } throw new RpcException(RpcErrorCode.InvalidRequest, "Id must be a string, a number or null."); } } }