Skip to content

Commit f020bb2

Browse files
committed
Able to serialize element subclasses in binary, still got some issues with vmaps though
1 parent ab2e6a1 commit f020bb2

2 files changed

Lines changed: 151 additions & 77 deletions

File tree

Codecs/Binary.cs

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Text;
55
using System.Numerics;
66
using System.IO;
7+
using System.Diagnostics;
78

89
namespace Datamodel.Codecs
910
{
@@ -63,8 +64,12 @@ static byte TypeToId(Type type, int version)
6364
byte i = 0;
6465
foreach (var list_type in type_list)
6566
{
66-
if (list_type == search_type) break;
67-
else i++;
67+
if (list_type == typeof(Element) && type.IsSubclassOf(typeof(Element)))
68+
break;
69+
70+
if (list_type == search_type)
71+
break;
72+
i++;
6873
}
6974
if (i == type_list.Length)
7075
throw new CodecException(String.Format("\"{0}\" is not supported in encoding binary {1}", type.Name, version));
@@ -143,7 +148,7 @@ public StringDictionary(Binary codec)
143148
if (!Dummy)
144149
{
145150
foreach (var i in Enumerable.Range(0, LengthSize == sizeof(short) ? Codec.Reader.ReadInt16() : Codec.Reader.ReadInt32()))
146-
Strings.Add(Codec.ReadString_Raw());
151+
AddString(Codec.ReadString_Raw());
147152
}
148153
}
149154

@@ -174,15 +179,15 @@ void ScrapeElement(Element elem)
174179
if (elem == null || elem.Stub || Scraped.Contains(elem)) return;
175180
Scraped.Add(elem);
176181

177-
Strings.Add(elem.Name);
178-
Strings.Add(elem.ClassName);
182+
AddString(elem.Name);
183+
AddString(elem.ClassName);
179184
foreach (var attr in elem.GetAllAttributesForSerialization())
180185
{
181-
Strings.Add(attr.Key);
186+
AddString(attr.Key);
182187
switch (attr.Value)
183188
{
184189
case string stringValue:
185-
Strings.Add(stringValue);
190+
AddString(stringValue);
186191
break;
187192
case Element elementValue:
188193
ScrapeElement(elementValue);
@@ -195,6 +200,23 @@ void ScrapeElement(Element elem)
195200
}
196201
}
197202

203+
/// <summary>
204+
/// Add non-nullable string.
205+
/// </summary>
206+
/// <param name="value"></param>
207+
void AddString(string value)
208+
{
209+
value ??= string.Empty;
210+
211+
Strings.Add(value);
212+
}
213+
214+
int GetIndex(string value)
215+
{
216+
value ??= string.Empty;
217+
return Strings.IndexOf(value);
218+
}
219+
198220
public string ReadString()
199221
{
200222
if (Dummy) return Codec.ReadString_Raw();
@@ -207,7 +229,7 @@ public void WriteString(string value)
207229
Writer.Write(value);
208230
else
209231
{
210-
var index = Strings.IndexOf(value);
232+
var index = GetIndex(value);
211233
if (IndiceSize == sizeof(short)) Writer.Write((short)index);
212234
else Writer.Write(index);
213235
}
@@ -501,37 +523,42 @@ public Encoder(BinaryWriter writer, Datamodel dm, int version)
501523

502524
public void Encode()
503525
{
504-
Writer.Write(String.Format(CodecUtilities.HeaderPattern, "binary", EncodingVersion, Datamodel.Format, Datamodel.FormatVersion) + "\n");
526+
Writer.Write(string.Format(CodecUtilities.HeaderPattern, "binary", EncodingVersion, Datamodel.Format, Datamodel.FormatVersion) + "\n");
505527

506528
if (EncodingVersion >= 9)
507529
Writer.Write(0); // Prefix elements
508530

509531
StringDict.WriteSelf();
510532

511-
Writer.Write(CountChildren(Datamodel.Root, new HashSet<Element>()));
533+
{
534+
var counter = new HashSet<Element>(Element.IDComparer.Default);
535+
var elementCount = CountChildren(Datamodel.Root, counter);
536+
537+
Writer.Write(elementCount);
538+
}
512539

513540
WriteIndex(Datamodel.Root);
514541
foreach (var e in ElementOrder)
515542
WriteBody(e);
516543
}
517544

518-
int CountChildren(Element elem, HashSet<Element> counted)
545+
int CountChildren(Element elem, HashSet<Element> counter)
519546
{
520547
if (elem.Stub) return 0;
521548
int num_elems = 1;
522-
counted.Add(elem);
549+
counter.Add(elem);
523550
foreach (var attr in elem.GetAllAttributesForSerialization())
524551
{
525552
if (attr.Value == null) continue;
526553

527-
if (attr.Value is Element child_elem && !counted.Contains(child_elem))
554+
if (attr.Value is Element child_elem && !counter.Contains(child_elem))
528555
{
529-
num_elems += CountChildren(child_elem, counted);
556+
num_elems += CountChildren(child_elem, counter);
530557
}
531558
else if (attr.Value is IEnumerable<Element> child_array)
532559
{
533-
foreach (var array_elem in child_array.Where(c => c != null && !counted.Contains(c)))
534-
num_elems += CountChildren(array_elem, counted);
560+
foreach (var array_elem in child_array.Where(c => c != null && !counter.Contains(c)))
561+
num_elems += CountChildren(array_elem, counter);
535562
}
536563
}
537564

@@ -573,8 +600,10 @@ void WriteIndex(Element elem)
573600

574601
void WriteBody(Element elem)
575602
{
576-
Writer.Write(elem.Count);
577-
foreach (var attr in elem.GetAllAttributesForSerialization())
603+
var attributesIterated = elem.GetAllAttributesForSerialization().ToArray();
604+
//Writer.Write(elem.Count);
605+
Writer.Write(attributesIterated.Length);
606+
foreach (var attr in attributesIterated)
578607
{
579608
StringDict.WriteString(attr.Key);
580609
var attr_type = attr.Value == null ? typeof(Element) : attr.Value.GetType();

Tests/Tests.cs

Lines changed: 104 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using Datamodel;
99
using System.Numerics;
1010
using DM = Datamodel.Datamodel;
11+
using System.Text;
1112

1213
namespace Datamodel_Tests
1314
{
@@ -326,86 +327,130 @@ public void Nested_CanImportToRoot()
326327
Assert.That(elem2.Owner, Is.EqualTo(dm));
327328
}
328329

330+
[Test]
331+
public void ElementArrayInitializes()
332+
{
333+
var elem = new ElementArray();
334+
335+
Assert.That(elem.Owner, Is.Null);
336+
Assert.That(elem.Count, Is.Zero);
337+
}
338+
}
339+
340+
public class ElementSubclassing
341+
{
329342
class CustomElement : Element
330343
{
331344
public int MyProperty { get; set; } = 1337;
332345
}
333346

334-
public class ElementSubclassTests
347+
[Test]
348+
public void ElementSubclassInitializes()
335349
{
336-
[Test]
337-
public void ElementSubclassInitializes()
338-
{
339-
var elem = new CustomElement();
350+
var elem = new CustomElement();
340351

341-
Assert.That(elem.Owner, Is.Null);
342-
Assert.That(elem.Count, Is.Zero);
343-
Assert.That(elem.MyProperty, Is.EqualTo(1337));
344-
}
345-
346-
[Test]
347-
public void PropertyAccessByKey()
348-
{
349-
var elem = new CustomElement();
350-
var myprop = elem["MyProperty"];
352+
Assert.That(elem.Owner, Is.Null);
353+
Assert.That(elem.Count, Is.Zero);
354+
Assert.That(elem.MyProperty, Is.EqualTo(1337));
355+
}
351356

352-
Assert.That(myprop, Is.EqualTo(1337));
353-
}
357+
[Test]
358+
public void PropertyAccessByKey()
359+
{
360+
var elem = new CustomElement();
361+
var myprop = elem["MyProperty"];
354362

355-
[Test]
356-
public void PropertySetByKey_Throws()
357-
{
358-
var elem = new CustomElement();
363+
Assert.That(myprop, Is.EqualTo(1337));
364+
}
359365

360-
var ex = Assert.Throws(typeof(InvalidOperationException), () => elem["MyProperty"] = 5);
366+
[Test]
367+
public void PropertySetByKey_Throws()
368+
{
369+
var elem = new CustomElement();
361370

362-
Assert.That(ex.Message, Does.Contain("Cannot set the value of a property-derived attribute by key"));
363-
}
371+
var ex = Assert.Throws(typeof(InvalidOperationException), () => elem["MyProperty"] = 5);
364372

365-
[Test]
366-
public void CanBeAssignedToDatamodelRoot()
367-
{
368-
var elem = new CustomElement();
373+
Assert.That(ex.Message, Does.Contain("Cannot set the value of a property-derived attribute by key"));
374+
}
369375

370-
var dm = new DM("test", 1);
371-
dm.Root = elem;
376+
[Test]
377+
public void CanBeAssignedToDatamodelRoot()
378+
{
379+
var elem = new CustomElement();
372380

373-
Assert.That(elem.Owner, Is.EqualTo(dm));
374-
}
381+
var dm = new DM("test", 1);
382+
dm.Root = elem;
375383

376-
[Test]
377-
public void Nested_CanBeAssignedToDatamodelRoot()
378-
{
379-
var elem = new CustomElement();
380-
var elem2 = new CustomElement();
381-
elem["elem2"] = elem2;
382-
elem2["woah"] = 5;
383-
384-
Assert.That(elem.Owner, Is.Null);
385-
Assert.That(elem.Count, Is.EqualTo(1));
386-
Assert.That(elem2.Owner, Is.Null);
387-
Assert.That(elem2.Count, Is.EqualTo(1));
388-
389-
Assert.That(elem.First().Key, Is.EqualTo("elem2"));
390-
Assert.That(elem.First().Value, Is.EqualTo(elem2));
391-
Assert.That(elem2.First().Key, Is.EqualTo("woah"));
392-
Assert.That(elem2.First().Value, Is.EqualTo(5));
393-
394-
var dm = new DM("test", 1);
395-
dm.Root = elem;
396-
397-
Assert.That(elem.Owner, Is.EqualTo(dm));
398-
Assert.That(elem2.Owner, Is.EqualTo(dm));
399-
}
384+
Assert.That(elem.Owner, Is.EqualTo(dm));
400385
}
401386

402387
[Test]
403-
public void ElementArrayInitializes()
388+
public void Nested_CanBeAssignedToDatamodelRoot()
404389
{
405-
var elem = new ElementArray();
390+
var elem = new CustomElement();
391+
var elem2 = new CustomElement();
392+
elem["elem2"] = elem2;
393+
elem2["woah"] = 5;
406394

407395
Assert.That(elem.Owner, Is.Null);
408-
Assert.That(elem.Count, Is.Zero);
396+
Assert.That(elem.Count, Is.EqualTo(1));
397+
Assert.That(elem2.Owner, Is.Null);
398+
Assert.That(elem2.Count, Is.EqualTo(1));
399+
400+
Assert.That(elem.First().Key, Is.EqualTo("elem2"));
401+
Assert.That(elem.First().Value, Is.EqualTo(elem2));
402+
Assert.That(elem2.First().Key, Is.EqualTo("woah"));
403+
Assert.That(elem2.First().Value, Is.EqualTo(5));
404+
405+
var dm = new DM("test", 1);
406+
dm.Root = elem;
407+
408+
Assert.That(elem.Owner, Is.EqualTo(dm));
409+
Assert.That(elem2.Owner, Is.EqualTo(dm));
410+
}
411+
412+
[Test]
413+
public void SerializesText()
414+
{
415+
var elem = new CustomElement();
416+
using var dm = new DM("vmap", 29);
417+
dm.Root = elem;
418+
419+
elem["as_child"] = new CustomElement() { MyProperty = 5 };
420+
421+
using var stream = new MemoryStream();
422+
dm.Save(stream, "keyvalues2", 4);
423+
424+
stream.Position = 0;
425+
using (var reader = new StreamReader(stream))
426+
{
427+
var text = reader.ReadToEnd();
428+
429+
Assert.Multiple(() =>
430+
{
431+
Assert.That(text, Does.Contain("CustomElement"));
432+
Assert.That(text, Does.Contain("MyProperty"));
433+
Assert.That(text, Does.Contain("1337"));
434+
Assert.That(text, Does.Contain("\"as_child\" \"CustomElement\""));
435+
});
436+
}
437+
438+
SaveAndConvert(dm, "keyvalues2", 4);
439+
440+
// binary
441+
using var stream2 = new MemoryStream();
442+
dm.Save(stream2, "binary", 9);
443+
444+
stream2.Position = 0;
445+
using var reader2 = new BinaryReader(stream2);
446+
var bytes = reader2.ReadBytes((int)stream2.Length);
447+
448+
// idk
449+
//Assert.That(bytes, Does.Contain(
450+
// [.. Encoding.ASCII.GetBytes("CustomElement")]
451+
//));
452+
453+
SaveAndConvert(dm, "binary", 9);
409454
}
410455
}
411456

0 commit comments

Comments
 (0)