using System; using System.Collections.Generic; using System.Runtime.Serialization; using System.Text; using ZeroLevel.Services.Pools; using ZeroLevel.Services.Serialization; namespace ZeroLevel.Network { [Serializable] [DataContract] public sealed class Frame : IEquatable, IBinarySerializable, ICloneable { private static ObjectPool _pool = new ObjectPool(() => new Frame(), 256); public static Frame FromPool() { var frame = _pool.Allocate(); frame.Inbox = null; frame.Payload = null; return frame; } public static Frame FromPool(string inbox) { var frame = _pool.Allocate(); frame.Inbox = inbox; frame.Payload = null; return frame; } public static Frame FromPool(string inbox, byte[] payload) { var frame = _pool.Allocate(); frame.Inbox = inbox; frame.Payload = payload; return frame; } public void Release() { _pool.Free(this); } [DataMember] public string Inbox { get; set; } [DataMember] public byte[] Payload { get; set; } public bool IsRequest { get; set; } public Frame() { } public Frame(Frame other) { var data = MessageSerializer.Serialize(other); using (var reader = new MemoryStreamReader(data)) { Deserialize(reader); } } public void Deserialize(IBinaryReader reader) { this.Inbox = reader.ReadString(); this.Payload = reader.ReadBytes(); } public void Serialize(IBinaryWriter writer) { writer.WriteString(this.Inbox); writer.WriteBytes(this.Payload); } public T Read() { if (this.Payload == null || this.Payload.Length == 0) return default(T); return MessageSerializer.DeserializeCompatible(this.Payload); } public IEnumerable ReadCollection() where T : IBinarySerializable { return MessageSerializer.DeserializeCollection(this.Payload); } public string ReadText() { if (this.Payload == null || this.Payload.Length == 0) return null; return Encoding.UTF32.GetString(this.Payload); } public void Write(T data) where T : IBinarySerializable { this.Payload = MessageSerializer.Serialize(data); } public void Write(IEnumerable items) where T : IBinarySerializable { this.Payload = MessageSerializer.Serialize(items); } public void Write(string data) { this.Payload = Encoding.UTF32.GetBytes(data); } public override bool Equals(object obj) { return this.Equals(obj as Frame); } public bool Equals(Frame other) { if (other == null) return false; if (ReferenceEquals(this, other)) return true; if (this.GetType() != other.GetType()) return false; if (string.Compare(this.Inbox, other.Inbox, true) != 0) return false; if (ArrayExtensions.UnsafeEquals(this.Payload, other.Payload) == false) return false; return true; } public override int GetHashCode() { return base.GetHashCode(); } public object Clone() { return new Frame(this); } } }