public void LargeClassTest() { byte[] array = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD7, 0xBF, 0xC0, 0xC9, 0xFD, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x0D, }; var reader = new PackedBitReader(array); var serializer = new PackedBitSerializer(typeof(BitPackingTest)); var result = serializer.Deserialize(reader) as BitPackingTest; var trueValues = typeof(BitPackingTest). GetProperties(BindingFlags.Instance | BindingFlags.Public). Where(p => p.Name.StartsWith("ShouldBeTrue")). Select(p => Tuple.Create(p.Name, (bool)p.GetValue(result))); Assert.All(trueValues, tv => tv.Item2); var falseValues = typeof(BitPackingTest). GetProperties(BindingFlags.Instance | BindingFlags.Public). Where(p => p.Name.StartsWith("ShouldBeFalse")). Select(p => Tuple.Create(p.Name, (bool)p.GetValue(result))); Assert.All(falseValues, fv => !fv.Item2); Assert.Equal(result.ShouldBe0, (byte)0); Assert.Equal(result.ShouldBe0Second, (uint)0); Assert.Equal(result.ShouldBe0Third, (byte)0); Assert.Equal(result.ShouldBe4, (byte)4); }
public void ArgumentValidation() { var reader = new PackedBitReader(sPackedBitWriterOutput); string output; Assert.ThrowsExact <ArgumentNullException>(() => reader.TryRead(out output, null)); }
public void Decode() { byte[] bytes = AlphabetMapper.TranslateMetroidStringToComputerBytes(Encoded); byte checksum = bytes[ChecksumByte - 1]; byte shift = bytes[ShiftByte - 1]; byte[] decoded = new byte[ChecksumByteCount]; Buffer.BlockCopy(bytes, 0, decoded, 0, ChecksumByteCount); decoded = decoded.RotateLeft(shift); byte verifyChecksum = CalculateChecksum(decoded, shift); if (verifyChecksum != checksum) { throw new ChecksumException("Invalid Metroid password"); } // The bitpacking we use assumes that information is packed from the left which means that it makes a big difference for a byte full of bools // Information is actually packed from the right of the byte // Ergo we just have to flip each byte // However first we handle the only 32-bit value (which can't be fixed by a naive flip) if (!BitConverter.IsLittleEndian) { // The game age value comes in little-endian format Swap(decoded, GameAgeStartByteIndex, GameAgeEndByteIndex); Swap(decoded, GameAgeStartByteIndex + 1, GameAgeEndByteIndex - 1); } for (int i = 0; i < decoded.Length; i++) { if (i >= GameAgeStartByteIndex && i <= GameAgeEndByteIndex) { continue; } decoded[i] = decoded[i].ReverseBits(); } var reader = new PackedBitReader(decoded); var serializer = new PackedBitSerializer(typeof(PasswordProperties)); Properties = serializer.Deserialize(reader) as PasswordProperties; Properties.Checksum = checksum; Properties.Shift = shift; }
public void Basics() { PackedBitReader reader = null; bool boolValue = false; sbyte signedByte = 0; byte unsignedByte = 0; short signedShort = 0; ushort unsignedShort = 0; int signedInt = 0; uint unsignedInt = 0; long signedLong = 0; ulong unsignedLong = 0; string stringValue = null; double doubleValue = 0; float floatValue = 0; bool success = false; Assert.DoesNotThrow(() => reader = new PackedBitReader(sPackedBitWriterOutput)); Assert.DoesNotThrow(() => success = reader.TryRead(out boolValue)); Assert.True(success); Assert.True(boolValue); Assert.DoesNotThrow(() => success = reader.TryRead(out boolValue)); Assert.True(success); Assert.False(boolValue); Assert.DoesNotThrow(() => success = reader.TryRead(out boolValue)); Assert.True(success); Assert.False(boolValue); Assert.DoesNotThrow(() => success = reader.TryRead(out boolValue)); Assert.True(success); Assert.True(boolValue); Assert.DoesNotThrow(() => success = reader.TryRead(out boolValue)); Assert.True(success); Assert.True(boolValue); Assert.DoesNotThrow(() => success = reader.TryRead(out boolValue)); Assert.True(success); Assert.True(boolValue); Assert.DoesNotThrow(() => success = reader.TryRead(out boolValue)); Assert.True(success); Assert.True(boolValue); Assert.DoesNotThrow(() => success = reader.TryRead(out boolValue)); Assert.True(success); Assert.False(boolValue); Assert.DoesNotThrow(() => success = reader.TryRead(out boolValue)); Assert.True(success); Assert.False(boolValue); Assert.DoesNotThrow(() => success = reader.TryRead(out boolValue)); Assert.True(success); Assert.True(boolValue); Assert.DoesNotThrow(() => success = reader.TryRead(4, out signedByte)); Assert.True(success); Assert.Equal(signedByte, (sbyte)3); Assert.DoesNotThrow(() => success = reader.TryRead(4, out unsignedByte)); Assert.True(success); Assert.Equal(unsignedByte, (byte)4); Assert.DoesNotThrow(() => success = reader.TryRead(6, out signedShort)); Assert.True(success); Assert.Equal(signedShort, (short)13); Assert.DoesNotThrow(() => success = reader.TryRead(6, out unsignedShort)); Assert.True(success); Assert.Equal(unsignedShort, (ushort)14); Assert.DoesNotThrow(() => success = reader.TryRead(6, out signedInt)); Assert.True(success); Assert.Equal(signedInt, (int)23); Assert.DoesNotThrow(() => success = reader.TryRead(6, out unsignedInt)); Assert.True(success); Assert.Equal(unsignedInt, (uint)24); Assert.DoesNotThrow(() => success = reader.TryRead(8, out signedLong)); Assert.True(success); Assert.Equal(signedLong, (long)33); Assert.DoesNotThrow(() => success = reader.TryRead(8, out unsignedLong)); Assert.True(success); Assert.Equal(unsignedLong, (ulong)34); Assert.DoesNotThrow(() => success = reader.TryRead(out boolValue)); Assert.True(success); Assert.False(boolValue); Assert.DoesNotThrow(() => success = reader.TryRead(out boolValue)); Assert.True(success); Assert.True(boolValue); Assert.DoesNotThrow(() => success = reader.TryRead(out boolValue)); Assert.True(success); Assert.True(boolValue); Assert.DoesNotThrow(() => success = reader.TryRead(out boolValue)); Assert.True(success); Assert.True(boolValue); Assert.DoesNotThrow(() => success = reader.TryRead(out boolValue)); Assert.True(success); Assert.True(boolValue); Assert.DoesNotThrow(() => success = reader.TryRead(out boolValue)); Assert.True(success); Assert.False(boolValue); Assert.DoesNotThrow(() => success = reader.TryRead(out boolValue)); Assert.True(success); Assert.False(boolValue); Assert.DoesNotThrow(() => success = reader.TryRead(out boolValue)); Assert.True(success); Assert.True(boolValue); Assert.DoesNotThrow(() => success = reader.TryReadSigned(4, out signedByte)); Assert.True(success); Assert.Equal(signedByte, (sbyte)-3); Assert.DoesNotThrow(() => success = reader.TryRead(out doubleValue)); Assert.True(success); Assert.Equal(doubleValue, 2.4d); Assert.DoesNotThrow(() => success = reader.TryRead(out floatValue)); Assert.True(success); Assert.Equal(floatValue, 88.4f); Assert.DoesNotThrow(() => success = reader.TryReadSigned(6, out signedShort)); Assert.True(success); Assert.Equal(signedShort, (short)-13); Assert.DoesNotThrow(() => success = reader.TryReadSigned(6, out signedInt)); Assert.True(success); Assert.Equal(signedInt, (int)-23); Assert.DoesNotThrow(() => success = reader.TryReadSigned(8, out signedLong)); Assert.True(success); Assert.Equal(signedLong, (long)-33); Assert.DoesNotThrow(() => success = reader.TryRead(out stringValue)); Assert.True(success); Assert.Equal(stringValue, "datà"); Assert.DoesNotThrow(() => success = reader.TryRead(out stringValue, Encoding.ASCII)); Assert.True(success); Assert.Equal(stringValue, "data"); Assert.DoesNotThrow(() => success = reader.TryRead(2, out signedByte)); Assert.True(success); Assert.Equal(signedByte, (sbyte)3); Assert.DoesNotThrow(() => success = reader.TryRead(out boolValue)); Assert.False(success); }
private void ReadImperativeBits(PackedBitReader reader, object value, IEnumerable <PropertyInfo> properties, Func <PropertyInfo, BitPair> getBitPair) { foreach (PropertyInfo prop in properties) { if (prop.PropertyType == typeof(bool)) { prop.SetValue(value, reader.ReadBool(), null); } else { BitPair read = getBitPair(prop); int bitRange = read.Count; if (read.Signed) { if (prop.PropertyType == typeof(sbyte)) { prop.SetValue(value, reader.ReadSignedInt8(bitRange), null); } else if (prop.PropertyType == typeof(short)) { prop.SetValue(value, reader.ReadSignedInt16(bitRange), null); } else if (prop.PropertyType == typeof(int)) { prop.SetValue(value, reader.ReadSignedInt32(bitRange), null); } else if (prop.PropertyType == typeof(long)) { prop.SetValue(value, reader.ReadSignedInt64(bitRange), null); } else { throw CodePath.Unreachable; } } else { if (prop.PropertyType == typeof(sbyte)) { prop.SetValue(value, reader.ReadInt8(bitRange), null); } else if (prop.PropertyType == typeof(short)) { prop.SetValue(value, reader.ReadInt16(bitRange), null); } else if (prop.PropertyType == typeof(int)) { prop.SetValue(value, reader.ReadInt32(bitRange), null); } else if (prop.PropertyType == typeof(long)) { prop.SetValue(value, reader.ReadInt64(bitRange), null); } else if (prop.PropertyType == typeof(byte)) { prop.SetValue(value, reader.ReadUInt8(bitRange), null); } else if (prop.PropertyType == typeof(ushort)) { prop.SetValue(value, reader.ReadUInt16(bitRange), null); } else if (prop.PropertyType == typeof(uint)) { prop.SetValue(value, reader.ReadUInt32(bitRange), null); } else if (prop.PropertyType == typeof(ulong)) { prop.SetValue(value, reader.ReadUInt64(bitRange), null); } else { throw CodePath.Unreachable; } } } } }
/// <summary> /// Deserializes a PackedBitReader stream to an object. /// </summary> /// <param name="reader">The stream to deserialize.</param> /// <returns>An object populated by the stream.</returns> /// <exception cref="ArgumentNullException"><paramref name="reader" /> is null.</exception> public object Deserialize(PackedBitReader reader) { if (object.ReferenceEquals(reader, null)) { throw new ArgumentNullException(nameof(reader)); } object ret = Activator.CreateInstance(SerializeType); if (ImplementsInterface) { ((IPackedBitSerializable)ret).Deserialize(reader); } else { var properties = GetProperties(SerializeType); if (HasOrder) { properties = properties.OrderBy(p => p.GetCustomAttribute <PackedBitOrderAttribute>().LowBit); ReadImperativeBits(reader, ret, properties, (prop) => { PackedBitOrderAttribute bitOrderAttr = prop.GetCustomAttribute <PackedBitOrderAttribute>(); return(new BitPair() { Count = bitOrderAttr.BitCount, Signed = bitOrderAttr.Signed, }); }); } else if (HasRange) { properties = properties.OrderBy(p => p.GetCustomAttribute <PackedBitRangeAttribute>().LowBit); ReadImperativeBits(reader, ret, properties, (prop) => { PackedBitRangeAttribute bitRangeAttr = prop.GetCustomAttribute <PackedBitRangeAttribute>(); return(new BitPair() { Count = bitRangeAttr.HasHighBit ? bitRangeAttr.HighBit - (bitRangeAttr.LowBit - 1) : 1, Signed = bitRangeAttr.Signed, }); }); } else if (HasSize) { ReadImperativeBits(reader, ret, properties, (prop) => { PackedBitSizeAttribute bitSizeAttr = prop.GetCustomAttribute <PackedBitSizeAttribute>(); return(new BitPair() { Count = bitSizeAttr.BitCount, Signed = bitSizeAttr.Signed, }); }); } else { throw CodePath.Unreachable; } } return(ret); }
public void Deserialize(PackedBitReader reader) { throw new NotImplementedException(); }