Repository: edgexfoundry/device-sdk-go
Pull request #1378 (2023-03-14 06:17:18)

refactor!: update data types in ResourceProperties
BREAKING CHANGE: support mask,shift,base,scale,offset in numeric data type

related to edgexfoundry/go-mod-core-contracts#770

<!-- Expected Commit Message Description (imported automatically by GitHub) -->
<!-- Must conform to [conventional commits guidelines](https://github.com/edgexfoundry/device-sdk-go/blob/main/.github/Contributing.md) -->
<!-- Expected Commit message must contain Closes/Fixes #IssueNumber statement when there is a related issue -->

<!-- Add additional detailed description of need for change if no related issue -->

**If your build fails** due to your commit message not passing the build checks, please review the guidelines here: https://github.com/edgexfoundry/device-sdk-go/blob/main/.github/Contributing.md

## PR Checklist
Please check if your PR fulfills the following requirements:

- [ ] I am not introducing a breaking change (if you are, flag in conventional commit message with `BREAKING CHANGE:` describing the break)
- [x] I am not introducing a new dependency (add notes below if you are)
- [ ] I have added unit tests for the new feature or bug fix (if not, why?)
- [ ] I have fully tested (add details below) this the new feature or bug fix (if not, why?)
- [x] I have opened a PR for the related docs change (if not, why?)
  https://github.com/edgexfoundry/edgex-docs/pull/982

## Testing Instructions
<!-- How can the reviewers test your change? -->

## New Dependency Instructions (If applicable)
<!-- Please follow [vetting instructions](https://wiki.edgexfoundry.org/display/FA/Vetting+Process+for+3rd+Party+Dependencies) and place results here -->


Patch:
diff --git a/go.mod b/go.mod
index adcd90d8..050e8518 100644
--- a/go.mod
+++ b/go.mod
@@ -5,7 +5,7 @@ go 1.18
 require (
 	github.com/OneOfOne/xxhash v1.2.8
 	github.com/edgexfoundry/go-mod-bootstrap/v3 v3.0.0-dev.44
-	github.com/edgexfoundry/go-mod-core-contracts/v3 v3.0.0-dev.26
+	github.com/edgexfoundry/go-mod-core-contracts/v3 v3.0.0-dev.28
 	github.com/edgexfoundry/go-mod-messaging/v3 v3.0.0-dev.16
 	github.com/google/uuid v1.3.0
 	github.com/gorilla/mux v1.8.0
diff --git a/go.sum b/go.sum
index b0326b39..fff94fb1 100644
--- a/go.sum
+++ b/go.sum
@@ -31,8 +31,8 @@ github.com/edgexfoundry/go-mod-bootstrap/v3 v3.0.0-dev.44 h1:bzROMV3XZzFB5uBFTeQ
 github.com/edgexfoundry/go-mod-bootstrap/v3 v3.0.0-dev.44/go.mod h1:qiG4HABtB+mnFBOby/ZUpIWcQD0TZa8jIG7p/jeVuzc=
 github.com/edgexfoundry/go-mod-configuration/v3 v3.0.0-dev.7 h1:pOH2GLDg1KB4EmAzo6IEvl4NEVFAw3ywxPUMa5Wi1Vw=
 github.com/edgexfoundry/go-mod-configuration/v3 v3.0.0-dev.7/go.mod h1:ZZbOu7K0/P8B1VKhZygVujLQyhvWuPe0E2vC/k2yscw=
-github.com/edgexfoundry/go-mod-core-contracts/v3 v3.0.0-dev.26 h1:vTTaaM3NErQRoNQKkbQ9f9x/FMJqzZX6OAQuXvU6HN8=
-github.com/edgexfoundry/go-mod-core-contracts/v3 v3.0.0-dev.26/go.mod h1:QBzXOAoyLzBm5k9CshgH9CR9nWMNXxZjknBFMnGJN/A=
+github.com/edgexfoundry/go-mod-core-contracts/v3 v3.0.0-dev.28 h1:aNHlmF2uPcwUr7VKvNVJXdxMDaI41j2laoGxZy5H95g=
+github.com/edgexfoundry/go-mod-core-contracts/v3 v3.0.0-dev.28/go.mod h1:SYoD+tmUP/zwWuuIySmsQSjPx6MHP+2w9FsLgm0IR7A=
 github.com/edgexfoundry/go-mod-messaging/v3 v3.0.0-dev.16 h1:JdZiqZ6CAboZ3+GuWZLyXc42y8HfsH1CmsIKNPY+0PY=
 github.com/edgexfoundry/go-mod-messaging/v3 v3.0.0-dev.16/go.mod h1:3q+Ys51HwpR9/kOv6sT7+EwAANgOfFWi509sEP5iPEo=
 github.com/edgexfoundry/go-mod-registry/v3 v3.0.0-dev.5 h1:FUUfsQUKHJqSwOXEj0j/qAn+uoWzM8nV7IOapGf7D80=
diff --git a/internal/transformer/transformparam.go b/internal/transformer/transformparam.go
index 2f533720..b0d78772 100644
--- a/internal/transformer/transformparam.go
+++ b/internal/transformer/transformparam.go
@@ -1,6 +1,6 @@
 // -*- Mode: Go; indent-tabs-mode: t -*-
 //
-// Copyright (C) 2018-2021 IOTech Ltd
+// Copyright (C) 2018-2023 IOTech Ltd
 //
 // SPDX-License-Identifier: Apache-2.0
 
@@ -39,19 +39,19 @@ func TransformWriteParameter(cv *dsModels.CommandValue, pv models.ResourceProper
 			return errors.NewCommonEdgeXWrapper(err)
 		}
 	}
-	if pv.Offset != "" && pv.Offset != defaultOffset {
+	if pv.Offset != 0 && pv.Offset != defaultOffset {
 		newValue, err = transformOffset(newValue, pv.Offset, false)
 		if err != nil {
 			return errors.NewCommonEdgeXWrapper(err)
 		}
 	}
-	if pv.Scale != "" && pv.Scale != defaultScale {
+	if pv.Scale != 0 && pv.Scale != defaultScale {
 		newValue, err = transformScale(newValue, pv.Scale, false)
 		if err != nil {
 			return errors.NewCommonEdgeXWrapper(err)
 		}
 	}
-	if pv.Base != "" && pv.Base != defaultBase {
+	if pv.Base != 0 && pv.Base != defaultBase {
 		newValue, err = transformBase(newValue, pv.Base, false)
 		if err != nil {
 			return errors.NewCommonEdgeXWrapper(err)
diff --git a/internal/transformer/transformresult.go b/internal/transformer/transformresult.go
index ec4ba749..337a3217 100644
--- a/internal/transformer/transformresult.go
+++ b/internal/transformer/transformresult.go
@@ -1,6 +1,6 @@
 // -*- Mode: Go; indent-tabs-mode: t -*-
 //
-// Copyright (C) 2019-2021 IOTech Ltd
+// Copyright (C) 2019-2023 IOTech Ltd
 //
 // SPDX-License-Identifier: Apache-2.0
 
@@ -9,7 +9,6 @@ package transformer
 import (
 	"fmt"
 	"math"
-	"strconv"
 
 	"github.com/edgexfoundry/go-mod-core-contracts/v3/clients/interfaces"
 	"github.com/edgexfoundry/go-mod-core-contracts/v3/clients/logger"
@@ -22,11 +21,11 @@ import (
 )
 
 const (
-	defaultBase   string = "0"
-	defaultScale  string = "1.0"
-	defaultOffset string = "0.0"
-	defaultMask   string = "0"
-	defaultShift  string = "0"
+	defaultBase   float64 = 0.0
+	defaultScale  float64 = 1.0
+	defaultOffset float64 = 0.0
+	defaultMask   uint64  = 0
+	defaultShift  int64   = 0
 
 	Overflow = "overflow"
 	NaN      = "NaN"
@@ -50,33 +49,33 @@ func TransformReadResult(cv *sdkModels.CommandValue, pv models.ResourcePropertie
 	}
 	newValue := value
 
-	if pv.Mask != "" && pv.Mask != defaultMask &&
+	if pv.Mask != 0 && pv.Mask != defaultMask &&
 		(cv.Type == common.ValueTypeUint8 || cv.Type == common.ValueTypeUint16 || cv.Type == common.ValueTypeUint32 || cv.Type == common.ValueTypeUint64) {
 		newValue, err = transformReadMask(newValue, pv.Mask)
 		if err != nil {
 			return errors.NewCommonEdgeXWrapper(err)
 		}
 	}
-	if pv.Shift != "" && pv.Shift != defaultShift &&
+	if pv.Shift != 0 && pv.Shift != defaultShift &&
 		(cv.Type == common.ValueTypeUint8 || cv.Type == common.ValueTypeUint16 || cv.Type == common.ValueTypeUint32 || cv.Type == common.ValueTypeUint64) {
 		newValue, err = transformReadShift(newValue, pv.Shift)
 		if err != nil {
 			return errors.NewCommonEdgeXWrapper(err)
 		}
 	}
-	if pv.Base != "" && pv.Base != defaultBase {
+	if pv.Base != 0 && pv.Base != defaultBase {
 		newValue, err = transformBase(newValue, pv.Base, true)
 		if err != nil {
 			return errors.NewCommonEdgeXWrapper(err)
 		}
 	}
-	if pv.Scale != "" && pv.Scale != defaultScale {
+	if pv.Scale != 0 && pv.Scale != defaultScale {
 		newValue, err = transformScale(newValue, pv.Scale, true)
 		if err != nil {
 			return errors.NewCommonEdgeXWrapper(err)
 		}
 	}
-	if pv.Offset != "" && pv.Offset != defaultOffset {
+	if pv.Offset != 0 && pv.Offset != defaultOffset {
 		newValue, err = transformOffset(newValue, pv.Offset, true)
 		if err != nil {
 			return errors.NewCommonEdgeXWrapper(err)
@@ -89,13 +88,7 @@ func TransformReadResult(cv *sdkModels.CommandValue, pv models.ResourcePropertie
 	return nil
 }
 
-func transformBase(value interface{}, base string, read bool) (interface{}, errors.EdgeX) {
-	b, err := strconv.ParseFloat(base, 64)
-	if err != nil {
-		errMsg := fmt.Sprintf("the base value %s of PropertyValue cannot be parsed to float64", base)
-		return value, errors.NewCommonEdgeX(errors.KindServerError, errMsg, err)
-	}
-
+func transformBase(value any, base float64, read bool) (any, errors.EdgeX) {
 	var valueFloat64 float64
 	switch v := value.(type) {
 	case uint8:
@@ -121,9 +114,9 @@ func transformBase(value interface{}, base string, read bool) (interface{}, erro
 	}
 
 	if read {
-		valueFloat64 = math.Pow(b, valueFloat64)
+		valueFloat64 = math.Pow(base, valueFloat64)
 	} else {
-		valueFloat64 = math.Log(valueFloat64) / math.Log(b)
+		valueFloat64 = math.Log(valueFloat64) / math.Log(base)
 	}
 	inRange := checkTransformedValueInRange(value, valueFloat64)
 	if !inRange {
@@ -156,13 +149,7 @@ func transformBase(value interface{}, base string, read bool) (interface{}, erro
 	return value, nil
 }
 
-func transformScale(value interface{}, scale string, read bool) (interface{}, errors.EdgeX) {
-	s, err := strconv.ParseFloat(scale, 64)
-	if err != nil {
-		errMsg := fmt.Sprintf("the scale value %s of PropertyValue cannot be parsed to float64", scale)
-		return value, errors.NewCommonEdgeX(errors.KindServerError, errMsg, err)
-	}
-
+func transformScale(value any, scale float64, read bool) (any, errors.EdgeX) {
 	var valueFloat64 float64
 	switch v := value.(type) {
 	case uint8:
@@ -188,9 +175,9 @@ func transformScale(value interface{}, scale string, read bool) (interface{}, er
 	}
 
 	if read {
-		valueFloat64 = valueFloat64 * s
+		valueFloat64 = valueFloat64 * scale
 	} else {
-		valueFloat64 = valueFloat64 / s
+		valueFloat64 = valueFloat64 / scale
 	}
 	inRange := checkTransformedValueInRange(value, valueFloat64)
 	if !inRange {
@@ -201,75 +188,69 @@ func transformScale(value interface{}, scale string, read bool) (interface{}, er
 	switch v := value.(type) {
 	case uint8:
 		if read {
-			value = v * uint8(s)
+			value = v * uint8(scale)
 		} else {
-			value = v / uint8(s)
+			value = v / uint8(scale)
 		}
 	case uint16:
 		if read {
-			value = v * uint16(s)
+			value = v * uint16(scale)
 		} else {
-			value = v / uint16(s)
+			value = v / uint16(scale)
 		}
 	case uint32:
 		if read {
-			value = v * uint32(s)
+			value = v * uint32(scale)
 		} else {
-			value = v / uint32(s)
+			value = v / uint32(scale)
 		}
 	case uint64:
 		if read {
-			value = v * uint64(s)
+			value = v * uint64(scale)
 		} else {
-			value = v / uint64(s)
+			value = v / uint64(scale)
 		}
 	case int8:
 		if read {
-			value = v * int8(s)
+			value = v * int8(scale)
 		} else {
-			value = v / int8(s)
+			value = v / int8(scale)
 		}
 	case int16:
 		if read {
-			value = v * int16(s)
+			value = v * int16(scale)
 		} else {
-			value = v / int16(s)
+			value = v / int16(scale)
 		}
 	case int32:
 		if read {
-			value = v * int32(s)
+			value = v * int32(scale)
 		} else {
-			value = v / int32(s)
+			value = v / int32(scale)
 		}
 	case int64:
 		if read {
-			value = v * int64(s)
+			value = v * int64(scale)
 		} else {
-			value = v / int64(s)
+			value = v / int64(scale)
 		}
 	case float32:
 		if read {
-			value = v * float32(s)
+			value = v * float32(scale)
 		} else {
-			value = v / float32(s)
+			value = v / float32(scale)
 		}
 	case float64:
 		if read {
-			value = v * s
+			value = v * scale
 		} else {
-			value = v / s
+			value = v / scale
 		}
 	}
 	return value, nil
 }
 
-func transformOffset(value interface{}, offset string, read bool) (interface{}, errors.EdgeX) {
-	o, err := strconv.ParseFloat(offset, 64)
-	if err != nil {
-		errMsg := fmt.Sprintf("the offset value %s of PropertyValue cannot be parsed to float64", offset)
-		return value, errors.NewCommonEdgeX(errors.KindServerError, errMsg, err)
-	}
-
+func transformOffset(value any, offset float64, read bool) (any, errors.EdgeX) {
 	var valueFloat64 float64
 	switch v := value.(type) {
 	case uint8:
@@ -295,9 +276,9 @@ func transformOffset(value interface{}, offset string, read bool) (interface{},
 	}
 
 	if read {
-		valueFloat64 = valueFloat64 + o
+		valueFloat64 = valueFloat64 + offset
 	} else {
-		valueFloat64 = valueFloat64 - 0
+		valueFloat64 = valueFloat64 - offset
 	}
 	inRange := checkTransformedValueInRange(value, valueFloat64)
 	if !inRange {
@@ -308,148 +289,108 @@ func transformOffset(value interface{}, offset string, read bool) (interface{},
 	switch v := value.(type) {
 	case uint8:
 		if read {
-			value = v + uint8(o)
+			value = v + uint8(offset)
 		} else {
-			value = v - uint8(o)
+			value = v - uint8(offset)
 		}
 	case uint16:
 		if read {
-			value = v + uint16(o)
+			value = v + uint16(offset)
 		} else {
-			value = v - uint16(o)
+			value = v - uint16(offset)
 		}
 	case uint32:
 		if read {
-			value = v + uint32(o)
+			value = v + uint32(offset)
 		} else {
-			value = v - uint32(o)
+			value = v - uint32(offset)
 		}
 	case uint64:
 		if read {
-			value = v + uint64(o)
+			value = v + uint64(offset)
 		} else {
-			value = v - uint64(o)
+			value = v - uint64(offset)
 		}
 	case int8:
 		if read {
-			value = v + int8(o)
+			value = v + int8(offset)
 		} else {
-			value = v - int8(o)
+			value = v - int8(offset)
 		}
 	case int16:
 		if read {
-			value = v + int16(o)
+			value = v + int16(offset)
 		} else {
-			value = v - int16(o)
+			value = v - int16(offset)
 		}
 	case int32:
 		if read {
-			value = v + int32(o)
+			value = v + int32(offset)
 		} else {
-			value = v - int32(o)
+			value = v - int32(offset)
 		}
 	case int64:
 		if read {
-			value = v + int64(o)
+			value = v + int64(offset)
 		} else {
-			value = v - int64(o)
+			value = v - int64(offset)
 		}
 	case float32:
 		if read {
-			value = v + float32(o)
+			value = v + float32(offset)
 		} else {
-			value = v - float32(o)
+			value = v - float32(offset)
 		}
 	case float64:
 		if read {
-			value = v + o
+			value = v + offset
 		} else {
-			value = v - o
+			value = v - offset
 		}
 	}
 	return value, nil
 }
 
-func transformReadMask(value interface{}, mask string) (interface{}, errors.EdgeX) {
+func transformReadMask(value any, mask uint64) (any, errors.EdgeX) {
 	switch v := value.(type) {
 	case uint8:
-		m, err := strconv.ParseUint(mask, 10, 8)
-		if err != nil {
-			errMsg := fmt.Sprintf("the mask value %s of PropertyValue cannot be parsed to %T", mask, v)
-			return value, errors.NewCommonEdgeX(errors.KindServerError, errMsg, err)
-		}
-		value = v & uint8(m)
+		value = v & uint8(mask)
 	case uint16:
-		m, err := strconv.ParseUint(mask, 10, 16)
-		if err != nil {
-			errMsg := fmt.Sprintf("the mask value %s of PropertyValue cannot be parsed to %T", mask, v)
-			return value, errors.NewCommonEdgeX(errors.KindServerError, errMsg, err)
-		}
-		value = v & uint16(m)
+		value = v & uint16(mask)
 	case uint32:
-		m, err := strconv.ParseUint(mask, 10, 32)
-		if err != nil {
-			errMsg := fmt.Sprintf("the mask value %s of PropertyValue cannot be parsed to %T", mask, v)
-			return value, errors.NewCommonEdgeX(errors.KindServerError, errMsg, err)
-		}
-		value = v & uint32(m)
+		value = v & uint32(mask)
 	case uint64:
-		m, err := strconv.ParseUint(mask, 10, 64)
-		if err != nil {
-			errMsg := fmt.Sprintf("the mask value %s of PropertyValue cannot be parsed to %T", mask, v)
-			return value, errors.NewCommonEdgeX(errors.KindServerError, errMsg, err)
-		}
-		value = v & m
+		value = v & mask
 	}
 
 	return value, nil
 }
 
-func transformReadShift(value interface{}, shift string) (interface{}, errors.EdgeX) {
+func transformReadShift(value any, shift int64) (any, errors.EdgeX) {
 	switch v := value.(type) {
 	case uint8:
-		s, err := strconv.ParseInt(shift, 10, 8)
-		if err != nil {
-			errMsg := fmt.Sprintf("the shift value %s of PropertyValue cannot be parsed to %T", shift, v)
-			return value, errors.NewCommonEdgeX(errors.KindServerError, errMsg, err)
-		}
-		if s > 0 {
-			value = v << s
+		if shift > 0 {
+			value = v << int8(shift)
 		} else {
-			value = v >> (-s)
+			value = v >> int8(-shift)
 		}
 	case uint16:
-		s, err := strconv.ParseInt(shift, 10, 16)
-		if err != nil {
-			errMsg := fmt.Sprintf("the shift value %s of PropertyValue cannot be parsed to %T", shift, v)
-			return value, errors.NewCommonEdgeX(errors.KindServerError, errMsg, err)
-		}
-		if s > 0 {
-			value = v << s
+		if shift > 0 {
+			value = v << int16(shift)
 		} else {
-			value = v >> (-s)
+			value = v >> int16(-shift)
 		}
 	case uint32:
-		s, err := strconv.ParseInt(shift, 10, 32)
-		if err != nil {
-			errMsg := fmt.Sprintf("the shift value %s of PropertyValue cannot be parsed to %T", shift, v)
-			return value, errors.NewCommonEdgeX(errors.KindServerError, errMsg, err)
-		}
-		if s > 0 {
-			value = v << s
+		if shift > 0 {
+			value = v << int32(shift)
 		} else {
-			value = v >> (-s)
+			value = v >> int32(-shift)
 		}
 	case uint64:
-		s, err := strconv.ParseInt(shift, 10, 64)
-		if err != nil {
-			errMsg := fmt.Sprintf("the shift value %s of PropertyValue cannot be parsed to %T", shift, v)
-			return value, errors.NewCommonEdgeX(errors.KindServerError, errMsg, err)
-		}
-		if s > 0 {
-			value = v << s
+		if shift > 0 {
+			value = v << shift
 		} else {
-			value = v >> (-s)
+			value = v >> (-shift)
 		}
 	}
 


Test patch:
diff --git a/internal/transformer/transformresult_test.go b/internal/transformer/transformresult_test.go
index 46aa7eb0..1a1e3fb3 100644
--- a/internal/transformer/transformresult_test.go
+++ b/internal/transformer/transformresult_test.go
@@ -1,13 +1,12 @@
 // -*- Mode: Go; indent-tabs-mode: t -*-
 //
-// Copyright (C) 2019-2021 IOTech Ltd
+// Copyright (C) 2019-2023 IOTech Ltd
 //
 // SPDX-License-Identifier: Apache-2.0
 
 package transformer
 
 import (
-	"fmt"
 	"math"
 	"testing"
 
@@ -23,30 +22,30 @@ func Test_transformReadBase(t *testing.T) {
 	tests := []struct {
 		name        string
 		value       interface{}
-		base        string
+		base        float64
 		expected    interface{}
 		expectedErr bool
 	}{
-		{"valid - uint8 base transformation", uint8(2), "10", uint8(100), false},
-		{"invalid - uint8 base transformation overflow", uint8(10), "10", nil, true},
-		{"valid - uint16 base transformation", uint16(2), "100", uint16(10000), false},
-		{"invalid - uint16 base transformation overflow", uint16(100), "10", nil, true},
-		{"valid - uint32 base transformation", uint32(2), "10000", uint32(100000000), false},
-		{"invalid - uint32 base transformation overflow", uint32(10000), "10", nil, true},
-		{"valid - uint64 base transformation", uint64(2), "100000", uint64(10000000000), false},
-		{"invalid - uint64 base transformation overflow", uint64(100000000), "10", nil, true},
-		{"valid - int8 base transformation", int8(2), "10", int8(100), false},
-		{"invalid - int8 base transformation overflow", int8(10), "10", nil, true},
-		{"valid - int16 base transformation", int16(2), "100", int16(10000), false},
-		{"invalid - int16 base transformation overflow", int16(100), "10", nil, true},
-		{"valid - int32 base transformation", int32(2), "10000", int32(100000000), false},
-		{"invalid - int32 base transformation overflow", int32(10000), "10", nil, true},
-		{"valid - int64 base transformation", int64(2), "100000", int64(10000000000), false},
-		{"invalid - int64 base transformation overflow", int64(100000000), "10", nil, true},
-		{"valid - float32 base transformation", float32(1.1), "2", float32(2.143547), false},
-		{"invalid - float32 base transformation overflow", math.MaxFloat32, "2", nil, true},
-		{"valid - float64 base transformation", float64(1.1), "2", float64(2.1435469250725863), false},
-		{"invalid - float64 base transformation overflow", math.MaxFloat64, "2", nil, true},
+		{"valid - uint8 base transformation", uint8(2), 10, uint8(100), false},
+		{"invalid - uint8 base transformation overflow", uint8(10), 10, nil, true},
+		{"valid - uint16 base transformation", uint16(2), 100, uint16(10000), false},
+		{"invalid - uint16 base transformation overflow", uint16(100), 10, nil, true},
+		{"valid - uint32 base transformation", uint32(2), 10000, uint32(100000000), false},
+		{"invalid - uint32 base transformation overflow", uint32(10000), 10, nil, true},
+		{"valid - uint64 base transformation", uint64(2), 100000, uint64(10000000000), false},
+		{"invalid - uint64 base transformation overflow", uint64(100000000), 10, nil, true},
+		{"valid - int8 base transformation", int8(2), 10, int8(100), false},
+		{"invalid - int8 base transformation overflow", int8(10), 10, nil, true},
+		{"valid - int16 base transformation", int16(2), 100, int16(10000), false},
+		{"invalid - int16 base transformation overflow", int16(100), 10, nil, true},
+		{"valid - int32 base transformation", int32(2), 10000, int32(100000000), false},
+		{"invalid - int32 base transformation overflow", int32(10000), 10, nil, true},
+		{"valid - int64 base transformation", int64(2), 100000, int64(10000000000), false},
+		{"invalid - int64 base transformation overflow", int64(100000000), 10, nil, true},
+		{"valid - float32 base transformation", float32(1.1), 2, float32(2.143547), false},
+		{"invalid - float32 base transformation overflow", math.MaxFloat32, 2, nil, true},
+		{"valid - float64 base transformation", float64(1.1), 2, float64(2.1435469250725863), false},
+		{"invalid - float64 base transformation overflow", math.MaxFloat64, 2, nil, true},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
@@ -66,28 +65,28 @@ func Test_transformReadScale(t *testing.T) {
 	tests := []struct {
 		name        string
 		value       interface{}
-		scale       string
+		scale       float64
 		expected    interface{}
 		expectedErr bool
 	}{
-		{"valid - uint8 scale transformation", uint8(math.MaxUint8 / 5), "5", uint8(math.MaxUint8), false},
-		{"invalid - uint8 scale transformation overflow", uint8(math.MaxUint8 / 5), "6", nil, true},
-		{"valid - uint16 scale transformation", uint16(math.MaxUint16 / 5), "5", uint16(math.MaxUint16), false},
-		{"invalid - uint16 scale transformation overflow", uint16(math.MaxUint16 / 5), "6", nil, true},
-		{"valid - uint32 scale transformation", uint32(math.MaxUint32 / 5), "5", uint32(math.MaxUint32), false},
-		{"invalid - uint32 scale transformation overflow", uint32(math.MaxUint32 / 5), "6", nil, true},
-		{"valid - uint64 scale transformation", uint64(math.MaxUint64 / 5), "5", uint64(math.MaxUint64), false},
-		{"valid - int8 scale transformation", int8(10), "10", int8(100), false},
-		{"invalid - int8 scale transformation overflow", int8(10), "30", nil, true},
-		{"valid - int16 scale transformation", int16(10000), "3", int16(30000), false},
-		{"invalid - int16 scale transformation overflow", int16(10000), "4", nil, true},
-		{"valid - int32 scale transformation", int32(1000000000), "2", int32(2000000000), false},
-		{"invalid - int32 scale transformation overflow", int32(1000000000), "3", nil, true},
-		{"valid - int64 scale transformation", int64(1000000000), "1000000000", int64(1000000000000000000), false},
-		{"valid - float32 scale transformation", float32(12.1), "10", float32(121), false},
-		{"invalid - float32 scale transformation overflow", float32(math.MaxFloat32 / 2), "3", nil, true},
-		{"valid - float64 scale transformation", float64(111111111.1), "2", float64(222222222.2), false},
-		{"invalid - float64 scale transformation overflow", float64(math.MaxFloat64), "2", nil, true},
+		{"valid - uint8 scale transformation", uint8(math.MaxUint8 / 5), 5, uint8(math.MaxUint8), false},
+		{"invalid - uint8 scale transformation overflow", uint8(math.MaxUint8 / 5), 6, nil, true},
+		{"valid - uint16 scale transformation", uint16(math.MaxUint16 / 5), 5, uint16(math.MaxUint16), false},
+		{"invalid - uint16 scale transformation overflow", uint16(math.MaxUint16 / 5), 6, nil, true},
+		{"valid - uint32 scale transformation", uint32(math.MaxUint32 / 5), 5, uint32(math.MaxUint32), false},
+		{"invalid - uint32 scale transformation overflow", uint32(math.MaxUint32 / 5), 6, nil, true},
+		{"valid - uint64 scale transformation", uint64(math.MaxUint64 / 5), 5, uint64(math.MaxUint64), false},
+		{"valid - int8 scale transformation", int8(10), 10, int8(100), false},
+		{"invalid - int8 scale transformation overflow", int8(10), 30, nil, true},
+		{"valid - int16 scale transformation", int16(10000), 3, int16(30000), false},
+		{"invalid - int16 scale transformation overflow", int16(10000), 4, nil, true},
+		{"valid - int32 scale transformation", int32(1000000000), 2, int32(2000000000), false},
+		{"invalid - int32 scale transformation overflow", int32(1000000000), 3, nil, true},
+		{"valid - int64 scale transformation", int64(1000000000), 1000000000, int64(1000000000000000000), false},
+		{"valid - float32 scale transformation", float32(12.1), 10, float32(121), false},
+		{"invalid - float32 scale transformation overflow", float32(math.MaxFloat32 / 2), 3, nil, true},
+		{"valid - float64 scale transformation", float64(111111111.1), 2, float64(222222222.2), false},
+		{"invalid - float64 scale transformation overflow", float64(math.MaxFloat64), 2, nil, true},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
@@ -107,27 +106,27 @@ func Test_transformReadOffset(t *testing.T) {
 	tests := []struct {
 		name        string
 		value       interface{}
-		offset      string
+		offset      float64
 		expected    interface{}
 		expectedErr bool
 	}{
-		{"valid - uint8 offset transformation", uint8(math.MaxUint8 - 1), "1", uint8(math.MaxUint8), false},
-		{"invalid - uint8 offset transformation overflow", uint8(math.MaxUint8), "1", nil, true},
-		{"valid - uint16 offset transformation", uint16(math.MaxUint16 - 1), "1", uint16(math.MaxUint16), false},
-		{"invalid - uint16 offset transformation overflow", uint16(math.MaxUint16), "1", nil, true},
-		{"valid - uint32 offset transformation", uint32(math.MaxUint32 - 1), "1", uint32(math.MaxUint32), false},
-		{"invalid - uint32 offset transformation overflow", uint32(math.MaxUint32), "1", nil, true},
-		{"valid - uint64 offset transformation", uint64(math.MaxUint64) - uint64(1), "1", uint64(math.MaxUint64), false},
-		{"valid - int8 offset transformation", int8(math.MaxInt8 - 1), "1", int8(math.MaxInt8), false},
-		{"invalid - int8 offset transformation overflow", int8(math.MaxInt8), "1", nil, true},
-		{"valid - int16 offset transformation", int16(math.MaxInt16 - 1), "1", int16(math.MaxInt16), false},
-		{"invalid - int16 offset transformation overflow", int16(math.MaxInt16), "1", nil, true},
-		{"valid - int32 offset transformation", int32(math.MaxInt32 - 1), "1", int32(math.MaxInt32), false},
-		{"invalid - int32 offset transformation overflow", int32(math.MaxInt32), "1", nil, true},
-		{"valid - int64 offset transformation", int64(math.MaxInt64 - 1), "1", int64(math.MaxInt64), false},
-		{"valid - float32 offset transformation", float32(1.1), "1", float32(2.1), false},
-		{"invalid - float32 offset transformation overflow", float32(math.MaxFloat32), fmt.Sprintf("%v", math.MaxFloat32), nil, true},
-		{"valid - float64 offset transformation", float64(1.1), "1", float64(2.1), false},
+		{"valid - uint8 offset transformation", uint8(math.MaxUint8 - 1), 1, uint8(math.MaxUint8), false},
+		{"invalid - uint8 offset transformation overflow", uint8(math.MaxUint8), 1, nil, true},
+		{"valid - uint16 offset transformation", uint16(math.MaxUint16 - 1), 1, uint16(math.MaxUint16), false},
+		{"invalid - uint16 offset transformation overflow", uint16(math.MaxUint16), 1, nil, true},
+		{"valid - uint32 offset transformation", uint32(math.MaxUint32 - 1), 1, uint32(math.MaxUint32), false},
+		{"invalid - uint32 offset transformation overflow", uint32(math.MaxUint32), 1, nil, true},
+		{"valid - uint64 offset transformation", uint64(math.MaxUint64) - uint64(1), 1, uint64(math.MaxUint64), false},
+		{"valid - int8 offset transformation", int8(math.MaxInt8 - 1), 1, int8(math.MaxInt8), false},
+		{"invalid - int8 offset transformation overflow", int8(math.MaxInt8), 1, nil, true},
+		{"valid - int16 offset transformation", int16(math.MaxInt16 - 1), 1, int16(math.MaxInt16), false},
+		{"invalid - int16 offset transformation overflow", int16(math.MaxInt16), 1, nil, true},
+		{"valid - int32 offset transformation", int32(math.MaxInt32 - 1), 1, int32(math.MaxInt32), false},
+		{"invalid - int32 offset transformation overflow", int32(math.MaxInt32), 1, nil, true},
+		{"valid - int64 offset transformation", int64(math.MaxInt64 - 1), 1, int64(math.MaxInt64), false},
+		{"valid - float32 offset transformation", float32(1.1), 1, float32(2.1), false},
+		{"invalid - float32 offset transformation overflow", float32(math.MaxFloat32), math.MaxFloat32, nil, true},
+		{"valid - float64 offset transformation", float64(1.1), 1, float64(2.1), false},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
@@ -147,15 +146,14 @@ func Test_transformReadMask(t *testing.T) {
 	tests := []struct {
 		name        string
 		value       interface{}
-		mask        string
+		mask        uint64
 		expected    interface{}
 		expectedErr bool
 	}{
-		{"valid - uint8 mask transformation", uint8(math.MaxUint8), "15", uint8(15), false},
-		{"valid - uint16 mask transformation", uint16(math.MaxUint16), "256", uint16(256), false},
-		{"valid - uint32 mask transformation", uint32(math.MaxUint32), "256", uint32(256), false},
-		{"valid - uint64 mask transformation", uint64(math.MaxUint64), "256", uint64(256), false},
-		{"invalid - mask value needs to be unsigned integer", uint8(math.MaxInt8), "-256", nil, true},
+		{"valid - uint8 mask transformation", uint8(math.MaxUint8), 15, uint8(15), false},
+		{"valid - uint16 mask transformation", uint16(math.MaxUint16), 256, uint16(256), false},
+		{"valid - uint32 mask transformation", uint32(math.MaxUint32), 256, uint32(256), false},
+		{"valid - uint64 mask transformation", uint64(math.MaxUint64), 256, uint64(256), false},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
@@ -174,20 +172,18 @@ func Test_transformReadShift(t *testing.T) {
 	tests := []struct {
 		name        string
 		value       interface{}
-		shift       string
+		shift       int64
 		expected    interface{}
 		expectedErr bool
 	}{
-		{"valid - uint8 shift transformation with positive shift value", uint8(0b1), "4", uint8(0b10000), false},
-		{"valid - uint8 shift transformation with negative shift value", uint8(0b11111111), "-4", uint8(0b00001111), false},
-		{"valid - uint16 shift transformation with positive shift value", uint16(0b1), "8", uint16(0b100000000), false},
-		{"valid - uint16 shift transformation with negative shift value", uint16(0b1111111100000000), "-8", uint16(0b0000000011111111), false},
-		{"valid - uint32 shift transformation with positive shift value", uint32(0b1), "16", uint32(0b10000000000000000), false},
-		{"valid - uint32 shift transformation with negative shift value", uint32(0b11111111111111110000000000000000), "-16", uint32(0b00000000000000001111111111111111), false},
-		{"valid - uint64 shift transformation with positive shift value", uint64(0b1), "32", uint64(0b100000000000000000000000000000000), false},
-		{"valid - uint64 shift transformation with negative shift value", uint64(0b1111111111111111111111111111111100000000000000000000000000000000), "-32", uint64(0b0000000000000000000000000000000011111111111111111111111111111111), false},
-		{"invalid - shift value needs to be integer value", uint8(8), "12.34", nil, true},
-		{"invalid - shift value needs to be integer value", uint8(8), "+-4", nil, true},
+		{"valid - uint8 shift transformation with positive shift value", uint8(0b1), 4, uint8(0b10000), false},
+		{"valid - uint8 shift transformation with negative shift value", uint8(0b11111111), -4, uint8(0b00001111), false},
+		{"valid - uint16 shift transformation with positive shift value", uint16(0b1), 8, uint16(0b100000000), false},
+		{"valid - uint16 shift transformation with negative shift value", uint16(0b1111111100000000), -8, uint16(0b0000000011111111), false},
+		{"valid - uint32 shift transformation with positive shift value", uint32(0b1), 16, uint32(0b10000000000000000), false},
+		{"valid - uint32 shift transformation with negative shift value", uint32(0b11111111111111110000000000000000), -16, uint32(0b00000000000000001111111111111111), false},
+		{"valid - uint64 shift transformation with positive shift value", uint64(0b1), 32, uint64(0b100000000000000000000000000000000), false},
+		{"valid - uint64 shift transformation with negative shift value", uint64(0b1111111111111111111111111111111100000000000000000000000000000000), -32, uint64(0b0000000000000000000000000000000011111111111111111111111111111111), false},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {