github.com/iDigitalFlame/xmt@v0.5.4/util/text/rand.go (about)

     1  // Copyright (C) 2020 - 2023 iDigitalFlame
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU General Public License as published by
     5  // the Free Software Foundation, either version 3 of the License, or
     6  // any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU General Public License
    14  // along with this program.  If not, see <https://www.gnu.org/licenses/>.
    15  //
    16  
    17  // Package text is a simple package for generating random string values with
    18  // complex requirements and regular expressions.
    19  //
    20  // This package exposes a 'Rand' struct that can be used to generate multiple
    21  // types of string values.
    22  //
    23  // The other exported types allow for generation of mutable expressions that can
    24  // be used to generate matching regular expression values. These work well with
    25  // any package that works with stringers, such as the "wc2" package.
    26  package text
    27  
    28  import (
    29  	"github.com/iDigitalFlame/xmt/data"
    30  	"github.com/iDigitalFlame/xmt/util"
    31  )
    32  
    33  const (
    34  	max        = 63 / size
    35  	size       = 6
    36  	mask       = 1<<size - 1
    37  	lenUpper   = 52
    38  	lenLower   = 26
    39  	lenNumbers = 78
    40  )
    41  
    42  // Rand is the custom Random number generator, based on the 'util.Rand' choice.
    43  // This random can be used to create custom random string values.
    44  var Rand = random{s: util.Rand}
    45  
    46  var (
    47  	// All represents the string instruction set that contains all alphanumeric
    48  	// characters.
    49  	All set = [2]byte{0, 62}
    50  	// Upper represents the string instruction set that contains only uppercase
    51  	// non-numeric characters.
    52  	Upper set = [2]byte{26, 52}
    53  	// Lower represents the string instruction set that contains only lowercase
    54  	// non-numeric characters.
    55  	Lower set = [2]byte{0, 26}
    56  	// Numbers represents the string instruction set that contains only numeric
    57  	// characters.
    58  	Numbers set = [2]byte{52, 62}
    59  	// Characters represents the string instruction set that contains mixed case
    60  	// non-numeric characters.
    61  	Characters set = [2]byte{0, 52}
    62  )
    63  
    64  type set [2]byte
    65  type random struct {
    66  	_ [0]func()
    67  	s interface {
    68  		Intn(int) int
    69  		Int63() int64
    70  	}
    71  }
    72  
    73  func (s set) String(n int) string {
    74  	return Rand.StringEx(s, n, n)
    75  }
    76  func (r random) String(n int) string {
    77  	return r.StringEx(All, n, n)
    78  }
    79  func (r random) StringLower(n int) string {
    80  	return r.StringEx(Lower, n, n)
    81  }
    82  func (r random) StringUpper(n int) string {
    83  	return r.StringEx(Upper, n, n)
    84  }
    85  func (r random) StringNumber(n int) string {
    86  	return r.StringEx(Numbers, n, n)
    87  }
    88  func (r random) StringRange(m, x int) string {
    89  	return r.StringEx(All, m, x)
    90  }
    91  func (r random) StringCharacters(n int) string {
    92  	return r.StringEx(Characters, n, n)
    93  }
    94  func (r random) StringEx(t set, m, x int) string {
    95  	if m < 0 || x <= 0 || m > x || t[0] > All[1] || t[1] > All[1] || t[0] >= t[1] {
    96  		return ""
    97  	}
    98  	var n int
    99  	if m == x {
   100  		n = m
   101  	} else {
   102  		n = m + r.s.Intn(x)
   103  	}
   104  	if n > data.MaxSlice {
   105  		n = data.MaxSlice
   106  	}
   107  	s := make([]byte, n)
   108  	for i, c, x := n-1, r.s.Int63(), max; i >= 0; {
   109  		if x == 0 {
   110  			c, x = r.s.Int63(), max
   111  		}
   112  		if d := int(c & mask); d < len(alpha) && d < int(t[1]) && d > int(t[0]) {
   113  			s[i] = alpha[d]
   114  			i--
   115  		}
   116  		c >>= size
   117  		x--
   118  	}
   119  	return string(s)
   120  }
   121  func (r random) StringLowerRange(m, x int) string {
   122  	return r.StringEx(Lower, m, x)
   123  }
   124  func (r random) StringUpperRange(m, x int) string {
   125  	return r.StringEx(Upper, m, x)
   126  }
   127  func (r random) StringNumberRange(m, x int) string {
   128  	return r.StringEx(Numbers, m, x)
   129  }
   130  func (r random) StringCharactersRange(m, x int) string {
   131  	return r.StringEx(Characters, m, x)
   132  }