[#170] accounting: Refactor and document package functionality

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
Leonard Lyubich 2022-03-12 19:15:26 +03:00 committed by Alex Vanin
parent a55ffa4796
commit 48150852f3
6 changed files with 109 additions and 63 deletions

View file

@ -3,67 +3,59 @@ package accounting
import "github.com/nspcc-dev/neofs-api-go/v2/accounting"
// Decimal represents decimal number for accounting operations.
//
// Decimal is mutually compatible with github.com/nspcc-dev/neofs-api-go/v2/accounting.Decimal
// message. See ReadFromMessageV2 / WriteToMessageV2 methods.
//
// Instances can be created using built-in var declaration.
//
// Note that direct typecast is not safe and may result in loss of compatibility:
// _ = Decimal(accounting.Decimal{}) // not recommended
type Decimal accounting.Decimal
// NewDecimal creates, initializes and returns empty Decimal instance.
// ReadFromMessageV2 reads Decimal from the accounting.Decimal message.
//
// Defaults:
// - value: 0
// - precision: 0
func NewDecimal() *Decimal {
return NewDecimalFromV2(new(accounting.Decimal))
// See also WriteToMessageV2.
func (d *Decimal) ReadFromMessageV2(m accounting.Decimal) {
*d = Decimal(m)
}
// NewDecimalFromV2 converts v2 Decimal to Decimal.
// WriteToMessageV2 writes Decimal to the accounting.Decimal message.
// The message must not be nil.
//
// Nil Decimal converts to nil.
func NewDecimalFromV2(d *accounting.Decimal) *Decimal {
return (*Decimal)(d)
}
// ToV2 returns the v2 Decimal message.
//
// Nil Decimal converts to nil.
func (d *Decimal) ToV2() *accounting.Decimal {
return (*accounting.Decimal)(d)
// See also ReadFromMessageV2.
func (d Decimal) WriteToMessageV2(m *accounting.Decimal) {
*m = (accounting.Decimal)(d)
}
// Value returns value of the decimal number.
func (d *Decimal) Value() int64 {
return (*accounting.Decimal)(d).GetValue()
//
// Zero Decimal has zero value.
//
// See also SetValue.
func (d Decimal) Value() int64 {
return (*accounting.Decimal)(&d).GetValue()
}
// SetValue sets value of the decimal number.
//
// See also Value.
func (d *Decimal) SetValue(v int64) {
(*accounting.Decimal)(d).SetValue(v)
}
// Precision returns precision of the decimal number.
func (d *Decimal) Precision() uint32 {
return (*accounting.Decimal)(d).GetPrecision()
//
// Zero Decimal has zero precision.
//
// See also SetPrecision.
func (d Decimal) Precision() uint32 {
return (*accounting.Decimal)(&d).GetPrecision()
}
// SetPrecision sets precision of the decimal number.
//
// See also Precision.
func (d *Decimal) SetPrecision(p uint32) {
(*accounting.Decimal)(d).SetPrecision(p)
}
// Marshal marshals Decimal into a protobuf binary form.
func (d *Decimal) Marshal() ([]byte, error) {
return (*accounting.Decimal)(d).StableMarshal(nil)
}
// Unmarshal unmarshalls protobuf binary representation of Decimal.
func (d *Decimal) Unmarshal(data []byte) error {
return (*accounting.Decimal)(d).Unmarshal(data)
}
// MarshalJSON encodes Decimal to protobuf JSON format.
func (d *Decimal) MarshalJSON() ([]byte, error) {
return (*accounting.Decimal)(d).MarshalJSON()
}
// UnmarshalJSON decodes Decimal from protobuf JSON format.
func (d *Decimal) UnmarshalJSON(data []byte) error {
return (*accounting.Decimal)(d).UnmarshalJSON(data)
}

View file

@ -3,15 +3,19 @@ package accounting_test
import (
"testing"
v2accounting "github.com/nspcc-dev/neofs-api-go/v2/accounting"
"github.com/nspcc-dev/neofs-sdk-go/accounting"
accountingtest "github.com/nspcc-dev/neofs-sdk-go/accounting/test"
"github.com/stretchr/testify/require"
)
func TestDecimal(t *testing.T) {
func TestDecimalData(t *testing.T) {
const v, p = 4, 2
d := accounting.NewDecimal()
var d accounting.Decimal
require.Zero(t, d.Value())
require.Zero(t, d.Precision())
d.SetValue(v)
d.SetPrecision(p)
@ -19,26 +23,24 @@ func TestDecimal(t *testing.T) {
require.EqualValues(t, p, d.Precision())
}
func TestDecimalEncoding(t *testing.T) {
d := accountingtest.Decimal()
func TestDecimalMessageV2(t *testing.T) {
var (
d accounting.Decimal
m v2accounting.Decimal
)
t.Run("binary", func(t *testing.T) {
data, err := d.Marshal()
require.NoError(t, err)
m.SetValue(7)
m.SetPrecision(8)
d2 := accounting.NewDecimal()
require.NoError(t, d2.Unmarshal(data))
d.ReadFromMessageV2(m)
require.Equal(t, d, d2)
})
require.EqualValues(t, m.GetValue(), d.Value())
require.EqualValues(t, m.GetPrecision(), d.Precision())
t.Run("json", func(t *testing.T) {
data, err := d.MarshalJSON()
require.NoError(t, err)
var m2 v2accounting.Decimal
d2 := accounting.NewDecimal()
require.NoError(t, d2.UnmarshalJSON(data))
d.WriteToMessageV2(&m2)
require.Equal(t, d, d2)
})
require.EqualValues(t, d.Value(), m2.GetValue())
require.EqualValues(t, d.Precision(), m2.GetPrecision())
}

33
accounting/doc.go Normal file
View file

@ -0,0 +1,33 @@
/*
Package accounting provides primitives to perform accounting operations in NeoFS.
Decimal type provides functionality to process user balances. For example, when
working with Fixed8 balance precision:
var dec accounting.Decimal
dec.SetValue(val)
dec.SetPrecision(8)
Instances can be also used to process NeoFS API V2 protocol messages
(see neo.fs.v2.accounting package in https://github.com/nspcc-dev/neofs-api).
On client side:
import "github.com/nspcc-dev/neofs-api-go/v2/accounting"
var msg accounting.Decimal
dec.WriteToMessageV2(&msg)
// send msg
On server side:
// recv msg
var dec accounting.Decimal
dec.ReadFromMessageV2(msg)
// process dec
Using package types in an application is recommended to potentially work with
different protocol versions with which these types are compatible.
*/
package accounting

View file

@ -8,9 +8,9 @@ import (
// Decimal returns random accounting.Decimal.
func Decimal() *accounting.Decimal {
d := accounting.NewDecimal()
var d accounting.Decimal
d.SetValue(rand.Int63())
d.SetPrecision(rand.Uint32())
return d
return &d
}

13
accounting/test/doc.go Normal file
View file

@ -0,0 +1,13 @@
/*
Package accountingtest provides functions for convenient testing of accounting package API.
Note that importing the package into source files is highly discouraged.
Random instance generation functions can be useful when testing expects any value, e.g.:
import accountingtest "github.com/nspcc-dev/neofs-sdk-go/accounting/test"
dec := accountingtest.Decimal()
// test the value
*/
package accountingtest

View file

@ -92,7 +92,13 @@ func (c *Client) BalanceGet(ctx context.Context, prm PrmBalanceGet) (*ResBalance
}
cc.result = func(r responseV2) {
resp := r.(*v2accounting.BalanceResponse)
res.setAmount(accounting.NewDecimalFromV2(resp.GetBody().GetBalance()))
if bal := resp.GetBody().GetBalance(); bal != nil {
var d accounting.Decimal
d.ReadFromMessageV2(*bal)
res.setAmount(&d)
}
}
// process call