Skip to content

Commit 62b7a1a

Browse files
Merge pull request #89 from paulpach/floattest
Add tests for floating points serialization
2 parents 5ca26bc + 67e4fd7 commit 62b7a1a

File tree

2 files changed

+138
-40
lines changed

2 files changed

+138
-40
lines changed

MLAPI.Tests/NetworkingManagerComponents/Binary/BitStreamTest.cs

Lines changed: 104 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,31 @@ public void TestBool()
2727
Assert.That(bitStream.Length, Is.EqualTo(100));
2828
}
2929

30+
[Test]
31+
public void TestSetLength()
32+
{
33+
BitStream bitStream = new BitStream(4);
34+
bitStream.SetLength(100);
35+
36+
Assert.That(bitStream.Capacity, Is.GreaterThanOrEqualTo(100));
37+
}
38+
39+
[Test]
40+
public void TestSetLength2()
41+
{
42+
BitStream bitStream = new BitStream(4);
43+
44+
bitStream.WriteByte(1);
45+
bitStream.WriteByte(1);
46+
bitStream.WriteByte(1);
47+
bitStream.WriteByte(1);
48+
49+
bitStream.SetLength(0);
50+
51+
// position should never go beyond length
52+
Assert.That(bitStream.Position, Is.EqualTo(0));
53+
}
54+
3055
[Test]
3156
public void TestGrow()
3257
{
@@ -161,9 +186,6 @@ public void TestInOutBytes()
161186
BitStream outStream = new BitStream(buffer);
162187
outStream.WriteByte(someNumber);
163188

164-
165-
// the bit should now be stored in the buffer, lets see if it comes out
166-
167189
BitStream inStream = new BitStream(buffer);
168190
Assert.That(inStream.ReadByte(), Is.EqualTo(someNumber));
169191

@@ -182,9 +204,6 @@ public void TestInOutInt16()
182204
BitStream outStream = new BitStream(buffer);
183205
outStream.WriteInt16(someNumber);
184206

185-
186-
// the bit should now be stored in the buffer, lets see if it comes out
187-
188207
BitStream inStream = new BitStream(buffer);
189208
short result = inStream.ReadInt16();
190209

@@ -202,11 +221,25 @@ public void TestInOutInt32()
202221
BitStream outStream = new BitStream(buffer);
203222
outStream.WriteInt32(someNumber);
204223

224+
BitStream inStream = new BitStream(buffer);
225+
int result = inStream.ReadInt32();
226+
227+
Assert.That(result, Is.EqualTo(someNumber));
228+
}
229+
230+
[Test]
231+
public void TestInOutInt64()
232+
{
233+
byte[] buffer = new byte[100];
234+
235+
long someNumber = 4614256656552045848;
205236

206-
// the bit should now be stored in the buffer, lets see if it comes out
237+
238+
BitStream outStream = new BitStream(buffer);
239+
outStream.WriteInt64(someNumber);
207240

208241
BitStream inStream = new BitStream(buffer);
209-
int result = inStream.ReadInt32();
242+
long result = inStream.ReadInt64();
210243

211244
Assert.That(result, Is.EqualTo(someNumber));
212245
}
@@ -267,5 +300,68 @@ public void TestCapacityGrowth()
267300
Assert.That(inStream.Length, Is.EqualTo(5));
268301
Assert.That(inStream.Capacity, Is.GreaterThanOrEqualTo(5));
269302
}
303+
304+
[Test]
305+
public void TestWriteSingle()
306+
{
307+
float somenumber = 0.1f;
308+
BitStream outStream = new BitStream();
309+
310+
outStream.WriteSingle(somenumber);
311+
byte[] buffer = outStream.GetBuffer();
312+
313+
BitStream inStream = new BitStream(buffer);
314+
315+
Assert.That(inStream.ReadSingle(), Is.EqualTo(somenumber));
316+
}
317+
318+
[Test]
319+
public void TestWriteDouble()
320+
{
321+
double somenumber = Math.PI;
322+
BitStream outStream = new BitStream();
323+
324+
outStream.WriteDouble(somenumber);
325+
byte[] buffer = outStream.GetBuffer();
326+
327+
BitStream inStream = new BitStream(buffer);
328+
329+
Assert.That(inStream.ReadDouble(), Is.EqualTo(somenumber));
330+
331+
}
332+
333+
[Test]
334+
public void TestWriteMisaligned()
335+
{
336+
BitStream outStream = new BitStream();
337+
outStream.WriteBit(true);
338+
outStream.WriteBit(false);
339+
// now the stream is misalligned, lets write some bytes
340+
outStream.WriteByte(244);
341+
outStream.WriteByte(123);
342+
outStream.WriteInt16(-5457);
343+
outStream.WriteUInt64(4773753249);
344+
outStream.WriteUInt64Packed(5435285812313212);
345+
outStream.WriteInt64Packed(-5435285812313212);
346+
outStream.WriteBit(true);
347+
outStream.WriteByte(1);
348+
outStream.WriteByte(0);
349+
350+
byte[] buffer = outStream.GetBuffer();
351+
352+
BitStream inStream = new BitStream(buffer);
353+
354+
Assert.That(inStream.ReadBit(), Is.True);
355+
Assert.That(inStream.ReadBit(), Is.False);
356+
Assert.That(inStream.ReadByte(), Is.EqualTo(244));
357+
Assert.That(inStream.ReadByte(), Is.EqualTo(123));
358+
Assert.That(inStream.ReadInt16(), Is.EqualTo(-5457));
359+
Assert.That(inStream.ReadUInt64(), Is.EqualTo(4773753249));
360+
Assert.That(inStream.ReadUInt64Packed(), Is.EqualTo(5435285812313212));
361+
Assert.That(inStream.ReadInt64Packed(), Is.EqualTo(-5435285812313212));
362+
Assert.That(inStream.ReadBit(), Is.True);
363+
Assert.That(inStream.ReadByte(), Is.EqualTo(1));
364+
Assert.That(inStream.ReadByte(), Is.EqualTo(0));
365+
}
270366
}
271367
}

MLAPI/NetworkingManagerComponents/Binary/BitStream.cs

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public BitStream(byte[] target)
6767
{
6868
this.target = target;
6969
Resizable = false;
70-
BitLength = (ulong) (target.Length << 3);
70+
BitLength = (ulong)(target.Length << 3);
7171
}
7272

7373
/// <summary>
@@ -99,15 +99,16 @@ public BitStream(byte[] target)
9999
/// <summary>
100100
/// Current buffer size. The buffer will not be resized (if possible) until Position is equal to Capacity and an attempt to write data is made.
101101
/// </summary>
102-
public long Capacity {
102+
public long Capacity
103+
{
103104
get => target.LongLength; // Optimized CeilingExact
104105
set
105106
{
106107
if (value < Length) throw new ArgumentOutOfRangeException("New capcity too small!");
107108
SetCapacity(value);
108109
}
109110
}
110-
111+
111112
/// <summary>
112113
/// The current length of data considered to be "written" to the buffer.
113114
/// </summary>
@@ -116,7 +117,7 @@ public long Capacity {
116117
/// <summary>
117118
/// The index that will be written to when any call to write data is made to this stream.
118119
/// </summary>
119-
public override long Position { get => (long)(BitPosition>>3); set => BitPosition = (ulong)value << 3; }
120+
public override long Position { get => (long)(BitPosition >> 3); set => BitPosition = (ulong)value << 3; }
120121

121122
/// <summary>
122123
/// Bit offset into the buffer that new data will be written to.
@@ -146,7 +147,7 @@ public override void Flush() { } // NOP
146147
private byte ReadByteMisaligned()
147148
{
148149
int mod = (int)(BitPosition & 7);
149-
return (byte)((target[(int)Position++] >> mod) | (target[(int)Position] << (8 - mod)));
150+
return (byte)((target[(int)Position] >> mod) | (target[(int)(BitPosition += 8) >> 3] << (8 - mod)));
150151
}
151152
/// <summary>
152153
/// Read an aligned byte from the buffer. It's recommended to not use this when the BitPosition is byte-misaligned.
@@ -224,8 +225,9 @@ private void SetCapacity(long value)
224225
public override void SetLength(long value)
225226
{
226227
if (value < 0) throw new IndexOutOfRangeException("Cannot set a negative length!");
227-
if (value > Capacity) Grow(value-Capacity);
228+
if (value > Capacity) Grow(value - Capacity);
228229
BitLength = (ulong)value << 3;
230+
BitPosition = Math.Min((ulong)value << 3, BitPosition);
229231
}
230232

231233
/// <summary>
@@ -271,7 +273,7 @@ public void WriteBit(bool bit)
271273
{
272274
if (BitAligned && Position == target.Length) Grow(1);
273275
int offset = (int)(BitPosition & 7);
274-
ulong pos = BitPosition >> 3;
276+
long pos = Position;
275277
++BitPosition;
276278
target[pos] = (byte)(bit ? (target[pos] & ~(1 << offset)) | (1 << offset) : (target[pos] & ~(1 << offset)));
277279
UpdateLength();
@@ -313,7 +315,7 @@ public void WriteDouble(double value)
313315
/// <param name="value">Value to write</param>
314316
public void WriteSinglePacked(float value)
315317
{
316-
lock(holder_f)
318+
lock (holder_f)
317319
lock (holder_i)
318320
{
319321
holder_f[0] = value;
@@ -470,8 +472,8 @@ public void WriteRangedSingle(float value, float minValue, float maxValue, int b
470472
{
471473
if (bytes < 1 || bytes > 4) throw new ArgumentOutOfRangeException("Result must occupy between 1 and 4 bytes!");
472474
if (value < minValue || value > maxValue) throw new ArgumentOutOfRangeException("Given value does not match the given constraints!");
473-
uint result = (uint)(((value + minValue)/(maxValue+minValue))*((0x100*bytes) - 1));
474-
for (int i = 0; i < bytes; ++i) _WriteByte((byte)(result >> (i<<3)));
475+
uint result = (uint)(((value + minValue) / (maxValue + minValue)) * ((0x100 * bytes) - 1));
476+
for (int i = 0; i < bytes; ++i) _WriteByte((byte)(result >> (i << 3)));
475477
}
476478

477479
/// <summary>
@@ -485,7 +487,7 @@ public void WriteRangedDouble(double value, double minValue, double maxValue, in
485487
{
486488
if (bytes < 1 || bytes > 8) throw new ArgumentOutOfRangeException("Result must occupy between 1 and 8 bytes!");
487489
if (value < minValue || value > maxValue) throw new ArgumentOutOfRangeException("Given value does not match the given constraints!");
488-
ulong result = (ulong)(((value + minValue) / (maxValue+minValue)) * ((0x100 * bytes) - 1));
490+
ulong result = (ulong)(((value + minValue) / (maxValue + minValue)) * ((0x100 * bytes) - 1));
489491
for (int i = 0; i < bytes; ++i) _WriteByte((byte)(result >> (i << 3)));
490492
}
491493

@@ -497,7 +499,7 @@ public void WriteRangedDouble(double value, double minValue, double maxValue, in
497499
public void WriteRotation(Quaternion rotation, int bytesPerAngle)
498500
{
499501
if (bytesPerAngle < 1 || bytesPerAngle > 4) throw new ArgumentOutOfRangeException("Bytes per angle must be at least 1 byte and at most 4 bytes!");
500-
if (bytesPerAngle==4) WriteVector3(rotation.eulerAngles);
502+
if (bytesPerAngle == 4) WriteVector3(rotation.eulerAngles);
501503
else
502504
{
503505
Vector3 rot = rotation.eulerAngles;
@@ -539,15 +541,15 @@ public double ReadDouble()
539541
return holder_d[0];
540542
}
541543
}
542-
544+
543545
/// <summary>
544546
/// Read a single-precision floating point value from the stream from a varint
545547
/// </summary>
546548
/// <returns>The read value</returns>
547549
public float ReadSinglePacked()
548550
{
549551
uint read = ReadUInt32Packed();
550-
lock(holder_f)
552+
lock (holder_f)
551553
lock (holder_i)
552554
{
553555
holder_i[0] = BinaryHelpers.SwapEndian(read);
@@ -700,7 +702,7 @@ public void WriteNibble(byte value)
700702
value &= 0x0F;
701703
int offset = (int)(BitPosition & 7), offset_inv = 8 - offset;
702704
target[Position] = (byte)((target[Position] & (0xFF >> offset_inv)) | (byte)(value << offset));
703-
if(offset > 4) target[Position + 1] = (byte)((target[Position + 1] & (0xFF << (offset & 3))) | (byte)(value >> offset_inv));
705+
if (offset > 4) target[Position + 1] = (byte)((target[Position + 1] & (0xFF << (offset & 3))) | (byte)(value >> offset_inv));
704706
BitPosition += 4;
705707
}
706708
UpdateLength();
@@ -719,13 +721,13 @@ public void WriteNibble(byte value)
719721
/// <param name="bitCount">Amount of bits to write</param>
720722
public void WriteBits(ulong value, int bitCount)
721723
{
722-
if (BitPosition + (ulong)bitCount > ((ulong)target.LongLength << 3)) Grow(Div8Ceil(BitPosition+(ulong)bitCount));
724+
if (BitPosition + (ulong)bitCount > ((ulong)target.LongLength << 3)) Grow(Div8Ceil(BitPosition + (ulong)bitCount));
723725
if (bitCount > 64) throw new ArgumentOutOfRangeException("Cannot read more than 64 bits from a 64-bit value!");
724726
if (bitCount < 0) throw new ArgumentOutOfRangeException("Cannot read fewer than 0 bits!");
725727
int count = -8;
726-
while (bitCount > (count+=8)) _WriteULongByte(value >> count);
728+
while (bitCount > (count += 8)) _WriteULongByte(value >> count);
727729
BitPosition += (ulong)count;
728-
if((bitCount & 7) != 0) _WriteBits((byte)(value >> count), bitCount & 7);
730+
if ((bitCount & 7) != 0) _WriteBits((byte)(value >> count), bitCount & 7);
729731
UpdateLength();
730732
}
731733
/// <summary>
@@ -743,7 +745,7 @@ private void _WriteBits(byte value, int bitCount)
743745
target[Position] = (byte)(
744746
(target[Position] & (0xFF >> offset_inv)) | // Bits prior to value (lower)
745747
(target[Position] & (0xFF << (offset + bitCount))) | // Bits after value (higher)
746-
(value<<offset) // Bits to write
748+
(value << offset) // Bits to write
747749
);
748750
if (bitCount + offset > 8)
749751
target[Position + 1] = (byte)(
@@ -906,15 +908,15 @@ public void WriteUInt64Packed(ulong value)
906908
/// Read an unsigned long (UInt64) from the stream.
907909
/// </summary>
908910
/// <returns>Value read from stream.</returns>
909-
public ulong ReadUInt64() => (ulong)(
911+
public ulong ReadUInt64() => (
910912
_ReadByte() |
911-
(_ReadByte() << 8) |
912-
(_ReadByte() << 16) |
913-
(_ReadByte() << 24) |
914-
(_ReadByte() << 32) |
915-
(_ReadByte() << 40) |
916-
(_ReadByte() << 48) |
917-
(_ReadByte() << 56)
913+
((ulong)_ReadByte() << 8) |
914+
((ulong)_ReadByte() << 16) |
915+
((ulong)_ReadByte() << 24) |
916+
((ulong)_ReadByte() << 32) |
917+
((ulong)_ReadByte() << 40) |
918+
((ulong)_ReadByte() << 48) |
919+
((ulong)_ReadByte() << 56)
918920
);
919921
/// <summary>
920922
/// Read a signed long (Int64) from the stream.
@@ -982,7 +984,7 @@ private void _WriteMisaligned(byte value)
982984
{
983985
int off = (int)(BitPosition & 7);
984986
int shift1 = 8 - off;
985-
target[Position + 1] = (byte)((target[Position + 1] & (0xFF >> off)) | (value >> shift1));
987+
target[Position + 1] = (byte)((target[Position + 1] & (0xFF << off)) | (value >> shift1));
986988
target[Position] = (byte)((target[Position] & (0xFF >> shift1)) | (value << off));
987989

988990
BitPosition += 8;
@@ -1054,19 +1056,19 @@ public override void WriteByte(byte value)
10541056
/// <param name="count">How many bytes to read. Set to value less than one to read until ReadByte returns -1</param>
10551057
public void CopyFrom(Stream s, int count = -1)
10561058
{
1057-
if(s is BitStream b) Write(b.target, 0, count < 0 ? (int)b.Length : count);
1059+
if (s is BitStream b) Write(b.target, 0, count < 0 ? (int)b.Length : count);
10581060
else
10591061
{
10601062
int read;
10611063
bool readToEnd = count < 0;
1062-
while((readToEnd || count-- > 0) && (read = s.ReadByte()) != -1)
1064+
while ((readToEnd || count-- > 0) && (read = s.ReadByte()) != -1)
10631065
_WriteIntByte(read);
10641066
UpdateLength();
10651067
}
10661068
}
1067-
1069+
10681070
// TODO: Implement CopyFrom() for BitStream with bitCount parameter
1069-
1071+
10701072
/// <summary>
10711073
/// Update length of data considered to be "written" to the stream.
10721074
/// </summary>

0 commit comments

Comments
 (0)