github.com/haraldrudell/parl@v0.4.176/ints/unsigned.go (about)

     1  /*
     2  © 2022–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/)
     3  ISC License
     4  */
     5  
     6  package ints
     7  
     8  import (
     9  	"errors"
    10  
    11  	"github.com/haraldrudell/parl/perrors"
    12  	"golang.org/x/exp/constraints"
    13  )
    14  
    15  // can be tested: errors.Is(err, ints.ErrToLarge)
    16  var ErrTooLarge = errors.New("value too large")
    17  
    18  // can be tested: errors.Is(err, ints.ErrNegative)
    19  var ErrNegative = errors.New("negative value")
    20  
    21  // Unsigned converts integer of type T to an unsigned value that fits the size of unsigned integer U
    22  //   - U is the unsigned integer returned
    23  //   - T is the input integer
    24  //   - integer T is of any integer size and may be signed
    25  //   - unsigned U is any size unsigned integer
    26  //   - error: if integer is negative or too large to be held in type U
    27  func Unsigned[U constraints.Unsigned, T constraints.Integer](integer T, label string) (unsigned U, err error) {
    28  
    29  	// check for negative value
    30  	//	- those come in signed integers
    31  	if isSigned, _, _, _ := IntProperties[T](); isSigned {
    32  		// whatever it is, it will fit into int64
    33  		if i64 := int64(integer); i64 < 0 {
    34  			if label == "" {
    35  				label = perrors.PackFunc()
    36  			}
    37  			err = perrors.Errorf("%s %w: %d -0x%x", label, ErrNegative, i64, -i64)
    38  			return
    39  		}
    40  	}
    41  	// integer is a positive number of a signed or unsigned integer
    42  
    43  	// check that positive value fits
    44  	var u64 = uint64(integer)
    45  	_, max, _, _ := IntProperties[U]()
    46  	if u64 > max {
    47  		if label == "" {
    48  			label = perrors.PackFunc()
    49  		}
    50  		err = perrors.Errorf("%s %w: %d 0x%[1]x max: %d 0x%[2]x", label, ErrTooLarge, u64, max)
    51  		return
    52  	}
    53  
    54  	unsigned = U(u64)
    55  
    56  	return
    57  }