Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 65 additions & 95 deletions convert.go → conv/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.

package swag
package conv

import (
"math"
"strconv"
"strings"
"unsafe"
)

// same as ECMA Number.MAX_SAFE_INTEGER and Number.MIN_SAFE_INTEGER
Expand All @@ -27,7 +28,7 @@ const (
epsilon float64 = 1e-9
)

// IsFloat64AJSONInteger allow for integers [-2^53, 2^53-1] inclusive
// IsFloat64AJSONInteger allows for integers [-2^53, 2^53-1] inclusive.
func IsFloat64AJSONInteger(f float64) bool {
if math.IsNaN(f) || math.IsInf(f, 0) || f < minJSONFloat || f > maxJSONFloat {
return false
Expand All @@ -51,53 +52,77 @@ func IsFloat64AJSONInteger(f float64) bool {
return diff/math.Min(fa+ga, math.MaxFloat64) < epsilon
}

var evaluatesAsTrue map[string]struct{}

func init() {
evaluatesAsTrue = map[string]struct{}{
"true": {},
"1": {},
"yes": {},
"ok": {},
"y": {},
"on": {},
"selected": {},
"checked": {},
"t": {},
"enabled": {},
// ConvertFloat turns a string into a float numerical value.
func ConvertFloat[T Float](str string) (T, error) {
// NOTE: [unsafe.SizeOf] simply returns the size in bytes of the value.
// For primitive types T, the generic stencil is precompiled and this value
// is resolved at compile time, resulting in an immediate call to [strconv.ParseFloat].
var v T
f, err := strconv.ParseFloat(str, int(unsafe.Sizeof(v))*8)
Comment on lines +57 to +61
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is good, but you are using unsafe.Sizeof in various place here in this file

Please consider:

  • creating a sizeof.go file
  • add a sizeOfNumber func
  • add this exact comment
  • call sizeOfNumber everywhere else

This way, only sizeof.go will import the unsafe package and it would be clearer

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you see this before merging ?

@fredbi

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok thanks. I'v been considering that wrapper func too. Perhaps in a follow-up. Now it is time to merge and move on to the next series of packages

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if err != nil {
return 0, err
}
}

// ConvertBool turn a string into a boolean
func ConvertBool(str string) (bool, error) {
_, ok := evaluatesAsTrue[strings.ToLower(str)]
return ok, nil
return T(f), nil
}

// ConvertFloat32 turn a string into a float32
func ConvertFloat32(str string) (float32, error) {
f, err := strconv.ParseFloat(str, 32)
// ConvertInteger turns a string into a signed integer.
func ConvertInteger[T Signed](str string) (T, error) {
var v T
f, err := strconv.ParseInt(str, 10, int(unsafe.Sizeof(v))*8)
if err != nil {
return 0, err
}
return float32(f), nil
}

// ConvertFloat64 turn a string into a float64
func ConvertFloat64(str string) (float64, error) {
return strconv.ParseFloat(str, 64)
return T(f), nil
}

// ConvertInt8 turn a string into an int8
func ConvertInt8(str string) (int8, error) {
i, err := strconv.ParseInt(str, 10, 8)
// ConvertUinteger turns a string into an unsigned integer.
func ConvertUinteger[T Unsigned](str string) (T, error) {
var v T
f, err := strconv.ParseUint(str, 10, int(unsafe.Sizeof(v))*8)
if err != nil {
return 0, err
}
return int8(i), nil

return T(f), nil
}

// ConvertInt16 turn a string into an int16
// ConvertBool turns a string into a boolean.
//
// It supports a few more "true" strings than [strconv.ParseBool]:
//
// - it is not case sensitive ("trUe" or "FalsE" work)
// - "ok", "yes", "y", "on", "selected", "checked", "enabled" are all true
// - everything that is not true is false: there is never an actual error returned
func ConvertBool(str string) (bool, error) {
switch strings.ToLower(str) {
case "true",
"1",
"yes",
"ok",
"y",
"on",
"selected",
"checked",
"t",
"enabled":
return true, nil
default:
return false, nil
}
}

// ConvertFloat32 turns a string into a float32.
func ConvertFloat32(str string) (float32, error) { return ConvertFloat[float32](str) }

// ConvertFloat64 turns a string into a float64
func ConvertFloat64(str string) (float64, error) { return ConvertFloat[float64](str) }

// ConvertInt8 turns a string into an int8
func ConvertInt8(str string) (int8, error) { return ConvertInteger[int8](str) }

// ConvertInt16 turns a string into an int16
func ConvertInt16(str string) (int16, error) {
i, err := strconv.ParseInt(str, 10, 16)
if err != nil {
Expand All @@ -106,7 +131,7 @@ func ConvertInt16(str string) (int16, error) {
return int16(i), nil
}

// ConvertInt32 turn a string into an int32
// ConvertInt32 turns a string into an int32
func ConvertInt32(str string) (int32, error) {
i, err := strconv.ParseInt(str, 10, 32)
if err != nil {
Expand All @@ -115,12 +140,12 @@ func ConvertInt32(str string) (int32, error) {
return int32(i), nil
}

// ConvertInt64 turn a string into an int64
// ConvertInt64 turns a string into an int64
func ConvertInt64(str string) (int64, error) {
return strconv.ParseInt(str, 10, 64)
}

// ConvertUint8 turn a string into an uint8
// ConvertUint8 turns a string into an uint8
func ConvertUint8(str string) (uint8, error) {
i, err := strconv.ParseUint(str, 10, 8)
if err != nil {
Expand All @@ -129,7 +154,7 @@ func ConvertUint8(str string) (uint8, error) {
return uint8(i), nil
}

// ConvertUint16 turn a string into an uint16
// ConvertUint16 turns a string into an uint16
func ConvertUint16(str string) (uint16, error) {
i, err := strconv.ParseUint(str, 10, 16)
if err != nil {
Expand All @@ -138,7 +163,7 @@ func ConvertUint16(str string) (uint16, error) {
return uint16(i), nil
}

// ConvertUint32 turn a string into an uint32
// ConvertUint32 turns a string into an uint32
func ConvertUint32(str string) (uint32, error) {
i, err := strconv.ParseUint(str, 10, 32)
if err != nil {
Expand All @@ -147,62 +172,7 @@ func ConvertUint32(str string) (uint32, error) {
return uint32(i), nil
}

// ConvertUint64 turn a string into an uint64
// ConvertUint64 turns a string into an uint64
func ConvertUint64(str string) (uint64, error) {
return strconv.ParseUint(str, 10, 64)
}

// FormatBool turns a boolean into a string
func FormatBool(value bool) string {
return strconv.FormatBool(value)
}

// FormatFloat32 turns a float32 into a string
func FormatFloat32(value float32) string {
return strconv.FormatFloat(float64(value), 'f', -1, 32)
}

// FormatFloat64 turns a float64 into a string
func FormatFloat64(value float64) string {
return strconv.FormatFloat(value, 'f', -1, 64)
}

// FormatInt8 turns an int8 into a string
func FormatInt8(value int8) string {
return strconv.FormatInt(int64(value), 10)
}

// FormatInt16 turns an int16 into a string
func FormatInt16(value int16) string {
return strconv.FormatInt(int64(value), 10)
}

// FormatInt32 turns an int32 into a string
func FormatInt32(value int32) string {
return strconv.Itoa(int(value))
}

// FormatInt64 turns an int64 into a string
func FormatInt64(value int64) string {
return strconv.FormatInt(value, 10)
}

// FormatUint8 turns an uint8 into a string
func FormatUint8(value uint8) string {
return strconv.FormatUint(uint64(value), 10)
}

// FormatUint16 turns an uint16 into a string
func FormatUint16(value uint16) string {
return strconv.FormatUint(uint64(value), 10)
}

// FormatUint32 turns an uint32 into a string
func FormatUint32(value uint32) string {
return strconv.FormatUint(uint64(value), 10)
}

// FormatUint64 turns an uint64 into a string
func FormatUint64(value uint64) string {
return strconv.FormatUint(value, 10)
}
Loading
Loading