public void Roundtrip() { var data = new List <int> { 6, 32, 573, 246, 24, 2 }; var serialized = _s.Serialize(data); var clone = _s.Deserialize <List <int> >(serialized); Assert.Equal(data.Count, clone.Count); for (int i = 0; i < data.Count; i++) { Assert.Equal(data[i], clone[i]); } var serializedAsObject = _s.Serialize <object>(data); var cloneObject = _s.Deserialize <object>(serializedAsObject); Assert.Equal(data.Count, ((List <int>)cloneObject).Count); for (int i = 0; i < data.Count; i++) { Assert.Equal(data[i], ((List <int>)cloneObject)[i]); } }
public void ShouldClearEncounteredSchemata() { var plugin = new Plugin(); var plugin2 = new Plugin(); var serializerConfig = new SerializerConfig(); serializerConfig.VersionTolerance.Mode = VersionToleranceMode.Standard; var s = new CerasSerializer(serializerConfig); for (int i = 0; i < 2; i++) { Assert.True(s.InstanceData.EncounteredSchemaTypes.Count == 0); var data = s.Serialize(plugin); Assert.True(s.InstanceData.EncounteredSchemaTypes.Count == 0); var data2 = s.Serialize(plugin2); Assert.True(s.InstanceData.EncounteredSchemaTypes.Count == 0); for (int j = 0; j < 3; j++) { var p1 = s.Deserialize <Plugin>(data); Assert.True(s.InstanceData.EncounteredSchemaTypes.Count == 0); var p2 = s.Deserialize <Plugin>(data2); Assert.True(s.InstanceData.EncounteredSchemaTypes.Count == 0); Assert.True(p1?.PluginLocation?.PluginName != null); Assert.True(p1.PluginLocation.PluginName == plugin.PluginLocation.PluginName); Assert.True(p2?.PluginLocation?.PluginName != null); Assert.True(p2.PluginLocation.PluginName == plugin2.PluginLocation.PluginName); } } }
static void WrongRefTypeTest() { var ceras = new CerasSerializer(); var container = new WrongRefTypeTestClass(); LinkedList <int> list = new LinkedList <int>(); list.AddLast(6); list.AddLast(2); list.AddLast(7); container.Collection = list; var data = ceras.Serialize(container); var linkedListClone = ceras.Deserialize <WrongRefTypeTestClass>(data); var listClone = linkedListClone.Collection as LinkedList <int>; Debug.Assert(listClone != null); Debug.Assert(listClone.Count == 3); Debug.Assert(listClone.First.Value == 6); // Now the actual test: // We change the type that is actually inside // And next ask to deserialize into the changed instance! // What we expect to happen is that ceras sees that the type is wrong and creates a new object container.Collection = new List <int>(); ceras.Deserialize(ref container, data); Debug.Assert(container.Collection is LinkedList <int>); }
public List <SaveMetadata> loadSaveMetas() { var saveFolderPos = SaveFolderPos; var saveFolders = Directory.EnumerateDirectories(saveFolderPos); this.saveMetas.Clear(); foreach (var folder in saveFolders) { try { var metaFile = File.ReadAllBytes(Path.Combine(folder, MetadataFilename)); var metadata = ceras.Deserialize <SaveMetadata>(metaFile); saveMetas.Add(metadata); } catch (Exception e) { Debug.LogWarning($"Metadata file \"meta.bin\" cannot be read in {folder}. Is this save folder corrupted?"); Debug.LogWarning(e); } } Debug.Log("Successfully loaded metadata:\n" + String.Join("\n", this.saveMetas.ConvertAll <String>(m => m.ToString()))); return(saveMetas); }
public void CustomFormatterForEnum() { var config = new SerializerConfig(); config.ConfigType <DayOfWeek>().CustomFormatter = new DayOfWeekFormatter(); var ceras = new CerasSerializer(config); Assert.True(ceras.Deserialize <DayOfWeek>(ceras.Serialize(DayOfWeek.Sunday)) == DayOfWeek.Sunday); Assert.True(ceras.Deserialize <DayOfWeek>(ceras.Serialize(DayOfWeek.Monday)) == DayOfWeek.Monday); Assert.True(ceras.Deserialize <DayOfWeek>(ceras.Serialize(DayOfWeek.Saturday)) == DayOfWeek.Saturday); Assert.True(ceras.Deserialize <DayOfWeek>(ceras.Serialize((DayOfWeek)591835)) == (DayOfWeek)591835); }
public void AutomaticSchemaChanges() { SerializerConfig CreateConfig() { var config = new SerializerConfig(); config.VersionTolerance.Mode = VersionToleranceMode.Standard; var typeMap = new MappingTypeBinder(); config.Advanced.TypeBinder = typeMap; typeMap.Map(typeof(Version1.Person), "Person"); typeMap.Map(typeof(Version2.Person), "Person"); typeMap.Map("Person", typeof(Version2.Person)); return(config); } byte[] data1 = null; byte[] data2 = null; { // 1: Save old data CerasSerializer ceras = new CerasSerializer(CreateConfig()); Version1.Person p1 = new Version1.Person { Name = "A", Age = 1 }; data1 = ceras.Serialize(p1); } { // 2: Use new type (added member), load old data, save again CerasSerializer ceras = new CerasSerializer(CreateConfig()); Version2.Person p2 = null; ceras.Deserialize(ref p2, data1); // Check if everything was loaded correctly Assert.True(p2.Name == "A"); Assert.True(p2.Age == 1); Assert.True(p2.Surname == null); // Make use of the new member, and save it p2.Surname = "S"; data2 = ceras.Serialize(p2); // Load new data, then old again var p2Clone = ceras.Deserialize <Version2.Person>(data2); var p1Clone = ceras.Deserialize <Version2.Person>(data1); Assert.True(p2Clone.Surname == "S"); Assert.True(p1Clone.Surname == null); } }
static void CustomComparerFormatter() { // Our HashSet<byte> is losing its Comparer // We use a custom formatter to fix it SerializerConfig config = new SerializerConfig(); config.OnResolveFormatter.Add((c, t) => { if (t == typeof(HashSet <byte[]>)) { return(new HashSetFormatterThatKeepsItsComparer()); } return(null); // continue searching }); config.ConfigType <HashSet <byte[]> >() .SetFormatter(new HashSetFormatterThatKeepsItsComparer()); var ceras = new CerasSerializer(config); var set = new HashSet <byte[]>(new CustomComparer()); set.Add(new byte[] { 1, 2, 3 }); set.Add(new byte[] { 4, 5, 6 }); var clone = ceras.Deserialize <HashSet <byte[]> >(ceras.Serialize(set)); Debug.Assert(clone.Comparer.GetType() == typeof(CustomComparer)); }
public object Deserialize(byte[] data) { try { lock (mSerializer) { return(mSerializer.Deserialize <object>(data)); } } catch (Exception exception) { Log.Error(exception); return(null); } }
public void BeforeAndAfterSerializeCalls() { SimpleListTest test = new SimpleListTest(); test.SomeNumber = 123; test.SomeText = "asdasd"; // Deserialize stuff should only be called on the new object (obviously) // And Serialize methods only on the old object { var clone = Clone(test); Assert.True(test.Actions.SequenceEqual(new int[] { 0, 1, 2 })); Assert.True(clone.Actions.SequenceEqual(new int[] { 0, 3, 4 })); } // But if we overwrite the object instead, we expect all methods to appear in the list var c = new CerasSerializer(); var data = c.Serialize(test); // we serialize AGAIN (in addition to the clone above), so we expect 0,1,2,1,2 Assert.True(test.Actions.SequenceEqual(new int[] { 0, 1, 2, 1, 2 })); c.Deserialize(ref test, data); // overwrite data into existing object Assert.True(test.Actions.SequenceEqual(new int[] { 0, 1, 2, 1, 2, 3, 4 })); }
/// <summary> /// Reads an object that was written using <see cref="WriteToStream(CerasSerializer, object, Stream)"/> by reading the size-prefix and then deserializing the data. /// <para>This method(-pair) is intended to be an easy to understand example for networking scenarios.</para> /// </summary> public static async Task <object> ReadFromStream(this CerasSerializer ceras, Stream stream) { // Read length bytes var length = (int) await ReadVarIntFromStream(stream); var recvBuffer = new byte[length]; // Keep reading until we have the full packet int totalRead = 0; while (totalRead < length) { int leftToRead = length - totalRead; int read = await stream.ReadAsync(recvBuffer, totalRead, leftToRead); if (read <= 0) { throw new Exception("Stream closed"); } totalRead += read; } // We have the full packet; now deserialize it var obj = ceras.Deserialize <object>(recvBuffer); return(obj); }
static void TryWithCount(int boolCount, int floatCount) { var serializer = new CerasSerializer(); var deserializer = new CerasSerializer(); var dict = new Dictionary <string, object>(); bool[] boolArray = new bool[boolCount]; float[] floatArray = new float[floatCount]; for (int i = 0; i < boolCount; i++) { boolArray[i] = i % 2 == 0 ? false : true; } for (int i = 0; i < floatCount; i++) { floatArray[i] = (float)i * 10000.0f; } dict.Add("Booleans", boolArray); dict.Add("Floats", floatArray); var bytes = serializer.Serialize <Dictionary <string, object> >(dict); Dictionary <string, object> clone = new Dictionary <string, object>(); deserializer.Deserialize <Dictionary <string, object> >(ref clone, bytes); foreach (var element in clone) { Console.WriteLine($"{element.Key}: {element.Value}"); } }
static void VersionToleranceTest() { var config = new SerializerConfig(); config.VersionTolerance = VersionTolerance.AutomaticEmbedded; config.TypeBinder = new DebugVersionTypeBinder(); var ceras = new CerasSerializer(config); var v1 = new VersionTest1 { A = 33, B = 34, C = 36 }; var v2 = new VersionTest2 { A = -3, C2 = -6, D = -7 }; var v1Data = ceras.Serialize(v1); v1Data.VisualizePrint("data with version tolerance"); ceras.Deserialize <VersionTest2>(ref v2, v1Data); var v1ObjData = ceras.Serialize <object>(v1); Debug.Assert(v1Data.SequenceEqual(v1ObjData), "data should be the same (because VersionTolerance forces generic parameter to <object>)"); Debug.Assert(v1.A == v2.A, "normal prop did not persist"); Debug.Assert(v1.C == v2.C2, "expected prop 'C2' to be populated by prop previously named 'C'"); }
public void Test() { var p = new Adult(); p.Name = "1"; p.Friends.Add(new Adult { Name = "2" }); var config = new SerializerConfig(); config.DefaultTargets = TargetMember.AllPublic; var ceras = new CerasSerializer(config); var data = ceras.Serialize <object>(p); var clone = new Adult(); clone.SetFriendsToNull(); object refObj = clone; ceras.Deserialize <object>(ref refObj, data); Assert.True(refObj != null); clone = refObj as Adult; Assert.True(clone.Friends != null); Assert.True(clone.Friends.Count == 1); Assert.True(clone.Friends[0].Name == "2"); }
static void NetworkTest() { var config = new SerializerConfig(); config.Advanced.PersistTypeCache = true; config.KnownTypes.Add(typeof(SetName)); config.KnownTypes.Add(typeof(NewPlayer)); config.KnownTypes.Add(typeof(LongEnum)); config.KnownTypes.Add(typeof(ByteEnum)); config.KnownTypes.Add(typeof(ComplexClass)); config.KnownTypes.Add(typeof(Complex2)); var msg = new SetName { Name = "abc", Type = SetName.SetNameType.Join }; CerasSerializer sender = new CerasSerializer(config); CerasSerializer receiver = new CerasSerializer(config); Console.WriteLine("Hash: " + sender.ProtocolChecksum.Checksum); var data = sender.Serialize <object>(msg); PrintData(data); data = sender.Serialize <object>(msg); PrintData(data); var obj = receiver.Deserialize <object>(data); var clone = (SetName)obj; Debug.Assert(clone.Name == msg.Name); Debug.Assert(clone.Type == msg.Type); }
static void TryWithCount(int boolCount, int floatCount) { var serializer = new CerasSerializer(); var deserializer = new CerasSerializer(); var dict = new Dictionary <string, object>(); bool[] boolArray = new bool[boolCount]; float[] floatArray = new float[floatCount]; for (int i = 0; i < boolCount; i++) { boolArray[i] = i % 2 == 0 ? false : true; } for (int i = 0; i < floatCount; i++) { floatArray[i] = (float)i * 10000.0f; } dict.Add("Booleans", boolArray); dict.Add("Floats", floatArray); var bytes = serializer.Serialize <Dictionary <string, object> >(dict); Dictionary <string, object> clone = new Dictionary <string, object>(); deserializer.Deserialize <Dictionary <string, object> >(ref clone, bytes); var b1 = dict["Booleans"] as bool[]; var b2 = clone["Booleans"] as bool[]; Assert.True(b1.SequenceEqual(b2)); }
static void InheritTest() { var config = new SerializerConfig(); config.KnownTypes.Add(typeof(SyncUnitHealth)); var ceras = new CerasSerializer(config); // This should be no problem: // - including inherited fields // - registering as derived (when derived is used), but still including inherited fields // There's literally no reason why this shouldn't work (except for some major bug ofc) var obj = new SyncUnitHealth { NetId = 1235, Health = 600 }; var bytes = ceras.Serialize <object>(obj); var clone = ceras.Deserialize <object>(bytes) as SyncUnitHealth; Debug.Assert(obj != clone); Debug.Assert(obj.NetId == clone.NetId); Debug.Assert(obj.Health == clone.Health); // we're using KnownTypes, so we expect the message to be really short Debug.Assert(bytes.Length == 6); }
static void MemberInfoAndTypeInfoTest() { var ceras = new CerasSerializer(); var multipleTypesHolder = new TypeTestClass(); multipleTypesHolder.Type1 = typeof(Person); multipleTypesHolder.Type2 = typeof(Person); multipleTypesHolder.Type3 = typeof(Person); multipleTypesHolder.Object1 = new Person(); multipleTypesHolder.Object2 = new Person(); multipleTypesHolder.Object3 = multipleTypesHolder.Object1; multipleTypesHolder.Member = typeof(TypeTestClass).GetMembers().First(); multipleTypesHolder.Method = typeof(TypeTestClass).GetMethods().First(); var data = ceras.Serialize(multipleTypesHolder); data.VisualizePrint("member info"); var multipleTypesHolderClone = ceras.Deserialize <TypeTestClass>(data); // todo: check object1 .. 3 as well. Debug.Assert(multipleTypesHolder.Member.MetadataToken == multipleTypesHolderClone.Member.MetadataToken); Debug.Assert(multipleTypesHolder.Method.MetadataToken == multipleTypesHolderClone.Method.MetadataToken); Debug.Assert(multipleTypesHolder.Type1 == multipleTypesHolderClone.Type1); Debug.Assert(multipleTypesHolder.Type2 == multipleTypesHolderClone.Type2); Debug.Assert(multipleTypesHolder.Type3 == multipleTypesHolderClone.Type3); }
static void PropertyTest() { var p = new PropertyClass() { Name = "qweqrwetwr", Num = 348765213, Other = new OtherPropertyClass() }; p.MutateProperties(); p.Other.Other = p; p.Other.PropertyClasses.Add(p); p.Other.PropertyClasses.Add(p); var config = new SerializerConfig(); config.DefaultTargets = TargetMember.All; var ceras = new CerasSerializer(config); var data = ceras.Serialize(p); data.VisualizePrint("Property Test"); var clone = ceras.Deserialize <PropertyClass>(data); Debug.Assert(p.Name == clone.Name); Debug.Assert(p.Num == clone.Num); Debug.Assert(p.Other.PropertyClasses.Count == 2); Debug.Assert(p.Other.PropertyClasses[0] == p.Other.PropertyClasses[1]); Debug.Assert(p.VerifyAllPropsAreChanged()); }
static void TupleTest() { // todo: // // - ValueTuple: can already be serialized as is! We just need to somehow enforce serialization of public fields // maybe a predefined list of fixed overrides? An additional step directly after ShouldSerializeMember? // // - Tuple: does not work and (for now) can't be fixed. // we'll need support for a different kind of ReferenceSerializer (one that does not create an instance) // and a different DynamicSerializer (one that collects the values into local variables, then instantiates the object) // SerializerConfig config = new SerializerConfig(); config.DefaultTargets = TargetMember.AllPublic; var ceras = new CerasSerializer(config); var vt = ValueTuple.Create(5, "b", DateTime.Now); var data = ceras.Serialize(vt); var vtClone = ceras.Deserialize <ValueTuple <int, string, DateTime> >(data); Debug.Assert(vt.Item1 == vtClone.Item1); Debug.Assert(vt.Item2 == vtClone.Item2); Debug.Assert(vt.Item3 == vtClone.Item3); //var t = Tuple.Create(5, "b", DateTime.Now); //data = ceras.Serialize(vt); //var tClone = ceras.Deserialize<Tuple<int, string, DateTime>>(data); }
static void EnumTest() { var s = new CerasSerializer(); var longEnum = LongEnum.b; var longEnumData = s.Serialize(longEnum); var cloneLong = s.Deserialize <LongEnum>(longEnumData); Debug.Assert(cloneLong == longEnum); var byteEnum = ByteEnum.b; var cloneByte = s.Deserialize <ByteEnum>(s.Serialize(byteEnum)); Debug.Assert(byteEnum == cloneByte); }
//[BenchmarkCategory("Single"), Benchmark] //public void Protobuf_Single() => RunProtobuf(_person); //[BenchmarkCategory("Single"), Benchmark] //public void Wire_Single() => RunWire(_person); //[BenchmarkCategory("Single"), Benchmark] //public void NetSerializer_Single() => RunNetSerializer(_person); //[BenchmarkCategory("List"), Benchmark(Baseline = true)] //public void Ceras_List() => RunCeras(_list); //[BenchmarkCategory("List"), Benchmark] //public void MessagePack_List() => RunMessagePackCSharp(_list); //[BenchmarkCategory("List"), Benchmark] //public void Protobuf_List() => RunProtobuf(_list); //[BenchmarkCategory("List"), Benchmark] //public void Wire_List() => RunWire(_list); //[BenchmarkCategory("List"), Benchmark] //public void NetSerializer_List() => RunNetSerializer(_list); static T RunCeras <T>(T obj) // Size = 76 { T clone = default; int size = _ceras.Serialize(obj, ref _buffer); _ceras.Deserialize(ref clone, _buffer); return(clone); }
private static void SimpleDictionaryTest() { var dict = new Dictionary <string, object> { ["name"] = "Test", }; var s = new CerasSerializer(); var data = s.Serialize(dict); var clone = s.Deserialize <Dictionary <string, object> >(data); }
static void TuplesTest() { var ceras = new CerasSerializer(); var obj1 = Tuple.Create(5, "a", DateTime.Now, 3.141); var data = ceras.Serialize <object>(obj1); var clone = ceras.Deserialize <object>(data); Debug.Assert(obj1.Equals(clone)); var obj2 = (234, "bsdasdasdf", DateTime.Now, 34.23424); data = ceras.Serialize <object>(obj2); clone = ceras.Deserialize <object>(data); Debug.Assert(obj2.Equals(clone)); }
static void ListTest() { var data = new List <int> { 6, 32, 573, 246, 24, 2, 9 }; var s = new CerasSerializer(); var p = new Person() { Name = "abc", Health = 30 }; var pData = s.Serialize <object>(p); pData.VisualizePrint("person data"); var pClone = (Person)s.Deserialize <object>(pData); Assert.Equal(p.Health, pClone.Health); Assert.Equal(p.Name, pClone.Name); var serialized = s.Serialize(data); var clone = s.Deserialize <List <int> >(serialized); Assert.Equal(data.Count, clone.Count); for (int i = 0; i < data.Count; i++) { Assert.Equal(data[i], clone[i]); } var serializedAsObject = s.Serialize <object>(data); var cloneObject = s.Deserialize <object>(serializedAsObject); Assert.Equal(data.Count, ((List <int>)cloneObject).Count); for (int i = 0; i < data.Count; i++) { Assert.Equal(data[i], ((List <int>)cloneObject)[i]); } }
public void SerializeStaticPart() { var ceras = new CerasSerializer(); var obj = new StaticMembersTest(); var dataStaticDefault = ceras.Advanced.SerializeStatic(typeof(StaticMembersTest)); var dataInstanceDefault = ceras.Serialize(obj); Assert.True(StaticMembersTest.ValueField == -12); Assert.True(obj.InstanceValue == -5); obj.InstanceValue = 1; StaticMembersTest.ValueField = 2; var dataStaticChanged = ceras.Advanced.SerializeStatic(typeof(StaticMembersTest)); var dataInstanceChanged = ceras.Serialize(obj); Assert.True(StaticMembersTest.ValueField == 2); Assert.True(obj.InstanceValue == 1); // // Deserialize // ceras.Advanced.DeserializeStatic(typeof(StaticMembersTest), dataStaticDefault); ceras.Deserialize(ref obj, dataInstanceDefault); Assert.True(StaticMembersTest.ValueField == -12); Assert.True(obj.InstanceValue == -5); ceras.Advanced.DeserializeStatic(typeof(StaticMembersTest), dataStaticChanged); ceras.Deserialize(ref obj, dataInstanceChanged); Assert.True(StaticMembersTest.ValueField == 2); Assert.True(obj.InstanceValue == 1); }
public static T FromCERAS <T>(this Stream data, SerializerConfig config) { var ceras = new CerasSerializer(config); byte[] bytes = data.ReadAll(); using (var m1 = new MemoryStream(bytes)) using (var m2 = new MemoryStream()) { BZip2.Decompress(m1, m2, false); m2.Seek(0, SeekOrigin.Begin); return(ceras.Deserialize <T>(m2.ToArray())); } }
protected override T Deserialize(Stream stream) { var pooledArray = ArrayPool <byte> .Shared.Rent((int)stream.Length); stream.Read(pooledArray, 0, (int)stream.Length); T ret = default; int offset = 0; _cerasSerializer.Deserialize <T>(ref ret, pooledArray, ref offset, (int)stream.Length); ArrayPool <byte> .Shared.Return(pooledArray); return(ret); }
/// <summary> /// Deserializes the given <see cref="TransportMessage"/> back into a <see cref="Message"/>. Expects a /// <see cref="Headers.ContentType"/> header with a value of <see cref="CerasContentType"/>, otherwise /// it will not attempt to deserialize the message. /// </summary> public async Task <Message> Deserialize(TransportMessage transportMessage) { var contentType = transportMessage.Headers.GetValue(Headers.ContentType); if (contentType != CerasContentType) { throw new FormatException($"Unknown content type: '{contentType}' - must be '{CerasContentType}' for the JSON serialier to work"); } var body = _serializer.Deserialize <object>(transportMessage.Body); return(new Message(transportMessage.Headers.Clone(), body)); }
private void ReadData(byte[] buffer) { var config = new SerializerConfig(); config.VersionTolerance.Mode = VersionToleranceMode.Standard; config.ConfigType <VersionTest>().CustomResolver = (c, t) => new Ceras.Versioning.DynamicEmulator <VersionTest>(c, c.GetTypeMetaData(t).PrimarySchema); CerasSerializer ceras = new CerasSerializer(config); var clone = ceras.Deserialize <VersionTest>(buffer); }
static void MaintainTypeTest() { CerasSerializer ceras = new CerasSerializer(); var dict = new Dictionary <string, object> { ["int"] = 5, ["byte"] = (byte)12, ["float"] = 3.141f, ["ushort"] = (ushort)345, ["sbyte"] = (sbyte)91, }; var data1 = ceras.Serialize(dict); var clone = ceras.Deserialize <Dictionary <string, object> >(data1); foreach (var kvp in dict) { var cloneValue = clone[kvp.Key]; Debug.Assert(kvp.Value.Equals(cloneValue)); if (kvp.Value.GetType() != cloneValue.GetType()) { Debug.Assert(false, $"Type does not match: A={kvp.Value.GetType()} B={cloneValue.GetType()}"); } else { Console.WriteLine($"Success! Type matching: {kvp.Value.GetType()}"); } } var data2 = new Dictionary <string, object>(); data2["test"] = 5; var s = new CerasSerializer(); var clonedDict = s.Deserialize <Dictionary <string, object> >(s.Serialize(data2)); var originalType = data2["test"].GetType(); var clonedType = clonedDict["test"].GetType(); if (originalType != clonedType) { Debug.Assert(false, $"Types don't match anymore!! {originalType} {clonedType}"); } else { Console.WriteLine("Success! Type match: " + originalType); } }