Skip to content
This repository has been archived by the owner on May 25, 2021. It is now read-only.

Commit

Permalink
corrected DecimalType byte array for Big Endian support in Java to co…
Browse files Browse the repository at this point in the history
…rrect

issue #83
  • Loading branch information
nberardi committed Nov 5, 2012
1 parent 2054160 commit d05b40e
Show file tree
Hide file tree
Showing 8 changed files with 200 additions and 8 deletions.
3 changes: 3 additions & 0 deletions src/System/Numerics/BigDecimal.cs
Expand Up @@ -71,6 +71,9 @@ public BigDecimal(byte[] value)
public bool IsZero { get { return _unscaledValue.IsZero; } }
public int Sign { get { return _unscaledValue.Sign; } }

public BigInteger UnscaledValue { get { return _unscaledValue; } }
public int Scale { get { return _scale; } }

public override string ToString()
{
var number = _unscaledValue.ToString("G");
Expand Down
8 changes: 0 additions & 8 deletions src/Types/CassandraConversionHelper.cs
Expand Up @@ -54,13 +54,5 @@ internal static Guid ToGuidFromBigEndianBytes(this byte[] value)
ReverseHighFieldTimestamp(buffer);
return new Guid(buffer);
}

internal static BigDecimal ToBigDecimalFromBigEndianBytes(this byte[] value)
{
var buffer = (byte[])value.Clone();
Array.Reverse(buffer);

return new BigDecimal(buffer);
}
}
}
3 changes: 3 additions & 0 deletions src/Types/CassandraObject.cs
Expand Up @@ -120,6 +120,7 @@ private static CassandraObject ConvertFrom(object o)
public static implicit operator CassandraObject(DateTime o) { return ConvertFrom(o); }
public static implicit operator CassandraObject(DateTimeOffset o) { return ConvertFrom(o); }
public static implicit operator CassandraObject(BigInteger o) { return ConvertFrom(o); }
public static implicit operator CassandraObject(BigDecimal o) { return ConvertFrom(o); }

public static implicit operator byte[](CassandraObject o) { return ConvertTo<byte[]>(o); }
public static implicit operator char[](CassandraObject o) { return ConvertTo<char[]>(o); }
Expand All @@ -142,6 +143,7 @@ private static CassandraObject ConvertFrom(object o)
public static implicit operator DateTime(CassandraObject o) { return ConvertTo<DateTime>(o); }
public static implicit operator DateTimeOffset(CassandraObject o) { return ConvertTo<DateTimeOffset>(o); }
public static implicit operator BigInteger(CassandraObject o) { return ConvertTo<BigInteger>(o); }
public static implicit operator BigDecimal(CassandraObject o) { return ConvertTo<BigDecimal>(o); }

public static implicit operator byte?(CassandraObject o) { return ConvertTo<byte?>(o); }
public static implicit operator sbyte?(CassandraObject o) { return ConvertTo<sbyte?>(o); }
Expand All @@ -161,6 +163,7 @@ private static CassandraObject ConvertFrom(object o)
public static implicit operator DateTime?(CassandraObject o) { return ConvertTo<DateTime?>(o); }
public static implicit operator DateTimeOffset?(CassandraObject o) { return ConvertTo<DateTimeOffset?>(o); }
public static implicit operator BigInteger?(CassandraObject o) { return ConvertTo<BigInteger?>(o); }
public static implicit operator BigDecimal?(CassandraObject o) { return ConvertTo<BigDecimal?>(o); }

public static explicit operator object[](CassandraObject o) { return ConvertTo<object[]>(o); }
public static explicit operator List<object>(CassandraObject o) { return ConvertTo<List<object>>(o); }
Expand Down
36 changes: 36 additions & 0 deletions src/Types/DecimalTypeConverter.cs
Expand Up @@ -94,5 +94,41 @@ public override object ConvertToInternal(BigDecimal value, Type destinationType)

return null;
}

public override byte[] ToBigEndian(BigDecimal value)
{
var scale = value.Scale;
var number = value.UnscaledValue;

var int32Converter = new Int32TypeConverter();
var bigIntegerConverter = new IntegerTypeConverter();

var scaleBytes = int32Converter.ToBigEndian(scale);
var numberBytes = bigIntegerConverter.ToBigEndian(number);

var bytes = new byte[scaleBytes.Length + numberBytes.Length];

Array.Copy(scaleBytes, 0, bytes, 0, scaleBytes.Length);
Array.Copy(numberBytes, 0, bytes, scaleBytes.Length, numberBytes.Length);

return bytes;
}

public override BigDecimal FromBigEndian(byte[] value)
{
var scaleBytes = new byte[4];
var numberBytes = new byte[value.Length - 4];

Array.Copy(value, 0, scaleBytes, 0, scaleBytes.Length);
Array.Copy(value, scaleBytes.Length, numberBytes, 0, numberBytes.Length);

var int32Converter = new Int32TypeConverter();
var bigIntegerConverter = new IntegerTypeConverter();

var scale = int32Converter.FromBigEndian(scaleBytes);
var number = bigIntegerConverter.FromBigEndian(numberBytes);

return new BigDecimal(number, scale);
}
}
}
4 changes: 4 additions & 0 deletions test/FluentCassandra.Tests/CassandraDatabaseSetup.cs
Expand Up @@ -82,6 +82,10 @@ public void ResetDatabase()
keyspace.TryCreateColumnFamily<TimeUUIDType>("StandardTimeUUIDType");
keyspace.TryCreateColumnFamily<UTF8Type>("StandardUTF8Type");
keyspace.TryCreateColumnFamily<UUIDType>("StandardUUIDType");
keyspace.TryCreateColumnFamily(new CassandraColumnFamilySchema {
FamilyName = "StandardDecimalType",
ColumnNameType = CassandraType.DecimalType
});
keyspace.TryCreateColumnFamily(new CassandraColumnFamilySchema {
FamilyName = "StandardCompositeType",
ColumnNameType = CassandraType.CompositeType(new[] { CassandraType.AsciiType, CassandraType.DoubleType })
Expand Down
2 changes: 2 additions & 0 deletions test/FluentCassandra.Tests/FluentCassandra.Tests.csproj
Expand Up @@ -76,6 +76,7 @@
<Compile Include="TypesToDatabase\AsciiTypeTest.cs" />
<Compile Include="TypesToDatabase\BytesTypeTest.cs" />
<Compile Include="TypesToDatabase\CompositeTypeTest.cs" />
<Compile Include="TypesToDatabase\DecimalTypeTest.cs" />
<Compile Include="TypesToDatabase\DynamicCompositeTypeTest.cs" />
<Compile Include="TypesToDatabase\TimeUUIDTypeTest.cs" />
<Compile Include="TypesToDatabase\LexicalUUIDTypeTest.cs" />
Expand All @@ -84,6 +85,7 @@
<Compile Include="TypesToDatabase\UTF8TypeTest.cs" />
<Compile Include="Types\CompositeTypeTest.cs" />
<Compile Include="Types\CassandraTypeTest.cs" />
<Compile Include="Types\DecimalTypeTest.cs" />
<Compile Include="Types\DynamicCompositeTypeTest.cs" />
<Compile Include="Types\IntegerTypeTest.cs" />
<Compile Include="CassandraDatabaseSetup.cs" />
Expand Down
110 changes: 110 additions & 0 deletions test/FluentCassandra.Tests/Types/DecimalTypeTest.cs
@@ -0,0 +1,110 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using Xunit;

namespace FluentCassandra.Types
{
public class DecimalTypeTest
{
private readonly BigDecimal bigDecimal = 100002334.4563D;
private readonly byte[] dotNetByteOrder = new byte[] { 179, 69, 9, 214, 232, 0, 4, 0, 0, 0 };
private readonly byte[] javaByteOrder = new byte[] { 0, 0, 0, 4, 0, 232, 214, 9, 69, 179 };

[Fact]
public void CassandraType_Cast()
{
// arrange
BigDecimal expected = bigDecimal;
DecimalType actualType = expected;

// act
CassandraObject actual = actualType;

// assert
Assert.Equal(expected, (BigDecimal)actual);
}

[Fact]
public void Implicit_ByteArray_Cast()
{
// arrange
byte[] expected = dotNetByteOrder;

// act
DecimalType actualType = expected;
byte[] actual = actualType;

// assert
Assert.True(expected.SequenceEqual(actual));
}

[Fact]
public void Implicit_BigDecimal_Cast()
{
// arrange
BigDecimal expected = bigDecimal;

// act
DecimalType actual = expected;

// assert
Assert.Equal(expected, (BigDecimal)actual);
}

[Fact]
public void Operator_EqualTo()
{
// arrange
var value = bigDecimal;
DecimalType type = value;

// act
bool actual = type.Equals(value);

// assert
Assert.True(actual);
}

[Fact]
public void Operator_NotEqualTo()
{
// arrange
var value = bigDecimal;
DecimalType type = value;

// act
bool actual = !type.Equals(value);

// assert
Assert.False(actual);
}

[Fact]
public void BigDecimal_To_JavaBytes()
{
// arrange

// act
DecimalType actual = bigDecimal;

// assert
Assert.True(actual.ToBigEndian().SequenceEqual(javaByteOrder));
}

[Fact]
public void JavaBytes_To_BigDecimal()
{
// arrange

// act
DecimalType actual = new DecimalType();
actual.SetValueFromBigEndian(javaByteOrder);

// assert
Assert.Equal(bigDecimal, (BigDecimal)actual);
}
}
}
42 changes: 42 additions & 0 deletions test/FluentCassandra.Tests/TypesToDatabase/DecimalTypeTest.cs
@@ -0,0 +1,42 @@
using System;
using System.Numerics;
using Xunit;
using FluentCassandra.Types;

namespace FluentCassandra.TypesToDatabase
{

public class DecimalTypeTest : IUseFixture<CassandraDatabaseSetupFixture>, IDisposable
{
private CassandraContext _db;

public void SetFixture(CassandraDatabaseSetupFixture data)
{
var setup = data.DatabaseSetup();
_db = setup.DB;
}

public void Dispose()
{
_db.Dispose();
}

public const string FamilyName = "StandardDecimalType";
public const string TestKey = "Test1";

[Fact]
public void Save_BigDecimal()
{
// arrange
var family = _db.GetColumnFamily(FamilyName);
BigDecimal expected = 100002334.4563D;

// act
family.InsertColumn(TestKey, expected, Math.PI);
var actual = family.GetColumn(TestKey, expected);

// assert
Assert.Equal(expected, (BigDecimal)actual.ColumnName);
}
}
}

0 comments on commit d05b40e

Please sign in to comment.