safecast

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 19, 2024 License: Apache-2.0 Imports: 3 Imported by: 13

README

safecast

Go Report Card GoDoc codecov Maintainability CI Checks

Avoid accidental overflow of numbers during go type conversions (e.g instead of shorter := bigger.(int8) type conversions use shorter := safecast.MustConvert[int8](bigger).

Safecast allows you to safely convert between numeric types in Go and return errors (or panic when using the Must* variants) when the cast would result in a loss of precision, range or sign.

See https://pkg.go.dev/fortio.org/safecast for docs and example. This is usable from any go with generics (1.18 or later) though our CI uses the latest go.

safecast is about avoiding gosec G115 and CWE-190: Integer Overflow or Wraparound class of overflow and loss of precision bugs, extended to float64/float32 issues.

Credit for the idea (and a finding a bug in the first implementation) goes to @ccoVeille, Please see https://github.com/ccoVeille/go-safecast for an different style API and implementation to pick whichever fits your style best.

Documentation

Overview

Package safecast allows you to safely cast between numeric types in Go and return errors (or panic when using the Must* variants) when the cast would result in a loss of precision, range or sign.

Example
package main

import (
	"fmt"

	"fortio.org/safecast"
)

func main() {
	var in int16 = 256
	// will error out
	out, err := safecast.Convert[uint8](in)
	fmt.Println(out, err)
	// will be fine
	out = safecast.MustRound[uint8](255.4)
	fmt.Println(out)
	// Also fine
	out = safecast.MustTruncate[uint8](255.6)
	fmt.Println(out)
}
Output:

0 out of range
255
255

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrOutOfRange = errors.New("out of range")

Functions

func Convert

func Convert[NumOut Number, NumIn Number](orig NumIn) (converted NumOut, err error)

Convert converts a number from one type to another, returning an error if the conversion would result in a loss of precision, range or sign (overflow). In other words if the converted number is not equal to the original number. Do not use for identity (same type in and out) but in particular this will error for Convert[uint64](uint64(math.MaxUint64)) because it needs to when converting to any float.

func MustConvert

func MustConvert[NumOut Number, NumIn Number](orig NumIn) NumOut

Same as Convert but panics if there is an error.

func MustRound

func MustRound[NumOut Number, NumIn Float](orig NumIn) NumOut

Same as Round but panics if there is an error.

Example
package main

import (
	"fmt"

	"fortio.org/safecast"
)

func main() {
	defer func() {
		if r := recover(); r != nil {
			fmt.Println("panic:", r)
		}
	}()
	out := safecast.MustRound[int8](-128.6)
	fmt.Println("not reached", out) // not reached
}
Output:

panic: safecast: out of range for -128.6 (float64) to int8

func MustTruncate

func MustTruncate[NumOut Number, NumIn Float](orig NumIn) NumOut

Same as Truncate but panics if there is an error.

func Round

func Round[NumOut Number, NumIn Float](orig NumIn) (converted NumOut, err error)

Converts a float to an integer by rounding to the nearest integer. Returns an error if the conversion would result in a loss of precision.

func Truncate

func Truncate[NumOut Number, NumIn Float](orig NumIn) (converted NumOut, err error)

Converts a float to an integer by truncating the fractional part. Returns an error if the conversion would result in a loss of precision.

Types

type Float

type Float interface {
	~float32 | ~float64
}

type Integer

type Integer interface {
	~int | ~uint | ~int8 | ~uint8 | ~int16 | ~uint16 | ~int32 | ~uint32 | ~int64 | ~uint64 | ~uintptr
}

type Number

type Number interface {
	Integer | Float
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL