Following the avro schema documentation for decimals I've created a method to turn a decimal into a byte array. The goals are:
- Should be represented by a non-scaled integer
- Should be big-endian
I've tested the code I wrote, but I'd like to know if the program still works in any unforeseen corner cases.
private static byte[] ToBigEndianByteArray(decimal value, int scale)
{
var bigInteger = new BigInteger(value * (decimal)Math.Pow(10, scale));
var bytes = bigInteger.ToByteArray();
return BitConverter.IsLittleEndian ? bytes.Reverse().Select(ReverseEndianness).ToArray() : bytes;
static byte ReverseEndianness(byte input)
{
const int bits = 8;
return (byte)Enumerable.Range(0, bits - 1)
.Aggregate(0, (accumulator, index) =>
BitAtIndexIsSet(input, index)
? SetBitAtIndex(accumulator, bits - 1 - index)
: accumulator);
static int SetBitAtIndex(int value, int index) => value | 1 << index;
static bool BitAtIndexIsSet(int value, int index) => (value & (1 << index)) != 0;
}
}
Example usage: ToBigEndianByteArray(8.45m, 2) produces 0000001101001101 (845 in decimal).