From b13caced863da1b72ba14afb71c4313c8390af5d Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Tue, 3 Dec 2019 13:43:57 -0500 Subject: [PATCH] SortableDecBytes --- types/decimal.go | 22 ++++++++++++++++++++++ types/decimal_test.go | 19 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/types/decimal.go b/types/decimal.go index 03934e2145ab..f226d0c25013 100644 --- a/types/decimal.go +++ b/types/decimal.go @@ -551,6 +551,28 @@ func (d Dec) Ceil() Dec { //___________________________________________________________________________________ +// Ensures that an sdk.Dec is within the sortable bounds +// Dec can't have precision of less that 10^-18 +func ValidSortableDec(dec Dec) bool { + return dec.LTE(OneDec().Quo(SmallestDec())) +} + +// FormattingStringSortableBytes is the string used in Sprintf to left and right pad the sdk.Dec +// It adjusts based on the Precision constant +var FormattingStringSortableBytes = fmt.Sprintf("%%0%ds", Precision*2+1) + +// Returns a byte slice representation of an sdk.Dec that can be sorted. +// Left and right pads with 0s so there are 18 digits to left and right of decimal point +// For this reason, there is a maximum and minimum value for this, enforced by ValidSortableDec +func SortableDecBytes(dec Dec) []byte { + if !ValidSortableDec(dec) { + panic("dec must be within bounds") + } + return []byte(fmt.Sprintf(FormattingStringSortableBytes, dec.String())) +} + +//___________________________________________________________________________________ + // reuse nil values var ( nilAmino string diff --git a/types/decimal_test.go b/types/decimal_test.go index e51c48fc7fee..67353870813c 100644 --- a/types/decimal_test.go +++ b/types/decimal_test.go @@ -443,3 +443,22 @@ func TestApproxSqrt(t *testing.T) { require.Equal(t, tc.expected, res, "unexpected result for test case %d, input: %v", i, tc.input) } } + +func TestDecSortableBytes(t *testing.T) { + tests := []struct { + d Dec + want []byte + }{ + {NewDec(0), []byte("000000000000000000.000000000000000000")}, + {NewDec(1), []byte("000000000000000001.000000000000000000")}, + {NewDec(10), []byte("000000000000000010.000000000000000000")}, + {NewDec(12340), []byte("000000000000012340.000000000000000000")}, + {NewDecWithPrec(12340, 4), []byte("000000000000000001.234000000000000000")}, + {NewDecWithPrec(12340, 5), []byte("000000000000000000.123400000000000000")}, + {NewDecWithPrec(12340, 8), []byte("000000000000000000.000123400000000000")}, + {NewDecWithPrec(1009009009009009009, 17), []byte("000000000000000010.090090090090090090")}, + } + for tcIndex, tc := range tests { + assert.Equal(t, tc.want, SortableDecBytes(tc.d), "bad String(), index: %v", tcIndex) + } +}