From 48150852f3d71fbd1629df3a85afbed18e638494 Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Sat, 12 Mar 2022 19:15:26 +0300 Subject: [PATCH] [#170] accounting: Refactor and document package functionality Signed-off-by: Leonard Lyubich --- accounting/decimal.go | 74 +++++++++++++++++--------------------- accounting/decimal_test.go | 40 +++++++++++---------- accounting/doc.go | 33 +++++++++++++++++ accounting/test/decimal.go | 4 +-- accounting/test/doc.go | 13 +++++++ client/accounting.go | 8 ++++- 6 files changed, 109 insertions(+), 63 deletions(-) create mode 100644 accounting/doc.go create mode 100644 accounting/test/doc.go diff --git a/accounting/decimal.go b/accounting/decimal.go index 8678202..3581542 100644 --- a/accounting/decimal.go +++ b/accounting/decimal.go @@ -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) -} diff --git a/accounting/decimal_test.go b/accounting/decimal_test.go index 264c186..1705988 100644 --- a/accounting/decimal_test.go +++ b/accounting/decimal_test.go @@ -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()) } diff --git a/accounting/doc.go b/accounting/doc.go new file mode 100644 index 0000000..42de312 --- /dev/null +++ b/accounting/doc.go @@ -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 diff --git a/accounting/test/decimal.go b/accounting/test/decimal.go index 65978b9..1c8f0f0 100644 --- a/accounting/test/decimal.go +++ b/accounting/test/decimal.go @@ -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 } diff --git a/accounting/test/doc.go b/accounting/test/doc.go new file mode 100644 index 0000000..bdabe46 --- /dev/null +++ b/accounting/test/doc.go @@ -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 diff --git a/client/accounting.go b/client/accounting.go index f29b711..eda81b8 100644 --- a/client/accounting.go +++ b/client/accounting.go @@ -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