This repository has been archived by the owner on Dec 8, 2017. It is now read-only.
/
Program.cs
159 lines (129 loc) · 4.52 KB
/
Program.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
using BinarySerialization;
using NUnit.Framework;
using System;
using System.IO;
using System.Linq;
namespace BinarySerializerRepro
{
/// <summary>
/// Wraps a stream to look like a NetworkStream
/// </summary>
public class LooksLikeANetworkStream : Stream
{
private Stream UnderlyingStream { get; }
public LooksLikeANetworkStream(Stream source)
{
UnderlyingStream = source;
}
public override void Flush()
{
UnderlyingStream.Flush();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override int Read(byte[] buffer, int offset, int count)
{
return UnderlyingStream.Read(buffer, offset, count);
}
public override void Write(byte[] buffer, int offset, int count)
{
UnderlyingStream.Write(buffer, offset, count);
}
public override bool CanRead => true;
public override bool CanSeek => false;
public override bool CanWrite => true;
public override long Length
{
get { throw new NotSupportedException();}
}
public override long Position
{
get { return UnderlyingStream.Position; }
set { UnderlyingStream.Position = value; }
}
}
public class Chunk { }
public class ImageHeaderChunk : Chunk { }
public class PaletteChunk : Chunk { }
public class ImageDataChunk : Chunk { }
public class TestChunk : Chunk
{
[FieldOrder(0)]
public CustomSerializable[] Customs;
}
public class CustomSerializable : IBinarySerializable
{
[BinarySerialization.Ignore]
public byte Value;
public void Serialize(Stream stream, Endianness endianness, BinarySerializationContext serializationContext)
{
stream.WriteByte(Value);
}
public void Deserialize(Stream stream, Endianness endianness, BinarySerializationContext serializationContext)
{
var readByte = stream.ReadByte();
if (readByte == -1) throw new EndOfStreamException();
Value = Convert.ToByte(readByte);
}
}
public class ChunkContainer
{
[FieldOrder(0)]
public int Length { get; set; }
[FieldOrder(1)]
[FieldLength(4)]
public string ChunkType { get; set; }
[FieldOrder(2)]
[FieldLength("Length")]
[Subtype("ChunkType", "IHDR", typeof(ImageHeaderChunk))]
[Subtype("ChunkType", "PLTE", typeof(PaletteChunk))]
[Subtype("ChunkType", "IDAT", typeof(ImageDataChunk))]
[Subtype("ChunkType", "TEST", typeof(TestChunk))]
public Chunk Chunk { get; set; }
[FieldOrder(3)]
public int Crc { get; set; }
}
public class Program
{
static void Main(string[] args)
{
var source = new ChunkContainer
{
ChunkType = "TEST",
Chunk = new TestChunk
{
Customs = new[]
{
new CustomSerializable
{
Value = 1
},
new CustomSerializable
{
Value = 2
}
}
}
};
var serializer = new BinarySerializer();
var outputStream = new MemoryStream();
serializer.Serialize(outputStream, source);
outputStream.Seek(0, SeekOrigin.Begin);
var inputStream = new LooksLikeANetworkStream(outputStream); //non-seekable stream
//var inputStream = outputStream; //successful
var roundtrip = serializer.Deserialize<ChunkContainer>(inputStream);
Assert.That(roundtrip.Chunk, Is.InstanceOf<TestChunk>());
var sourceChunk = (TestChunk) source.Chunk;
var testChunk = (TestChunk) roundtrip.Chunk;
Assert.That(testChunk.Customs.Length, Is.EqualTo(sourceChunk.Customs.Length));
Assert.That(testChunk.Customs.ElementAt(0).Value, Is.EqualTo(sourceChunk.Customs.ElementAt(0).Value));
Assert.That(testChunk.Customs.ElementAt(1).Value, Is.EqualTo(sourceChunk.Customs.ElementAt(1).Value));
}
}
}