diff --git a/lib/securerandom.rb b/lib/securerandom.rb index 476f5e1..21964f7 100644 --- a/lib/securerandom.rb +++ b/lib/securerandom.rb @@ -297,4 +297,68 @@ module SecureRandom ary[3] = (ary[3] & 0x3fff) | 0x8000 "%08x-%04x-%04x-%04x-%04x%08x" % ary end + + # SecureRandom.choose generates a string that randomly draws from a source array of + # characters. + # + # The argument _source_ specifies the array of characters from which to generate the + # string. The argument _n_ specifies the length, in characters, of the string to be + # generated. + # + # If _n_ is not specified or is nil, 16 is assumed. + # It may be larger in the future. + # + # The result may contain whatever characters are in the source array. + # + # p SecureRandom.choose([*'l'..'r']) #=> "lmrqpoonmmlqlron" + # p SecureRandom.choose([*'0'..'9'], 5) #=> "27309" + # + # If a secure random number generator is not available, + # +NotImplementedError+ is raised. + def self.choose(source, n=nil) + n = 16 if n.nil? + size = source.size + n.times.map {source[random_number(size)]}.join('') + end + + GRAPH = [*'!'..'~'] unless defined? GRAPH + # SecureRandom.graph generates a random graph string that contains all the printable + # ASCII characters except for space. + # + # The argument _n_ specifies the length, in characters, of the string to be + # generated. + # + # If _n_ is not specified or is nil, 16 is assumed. + # It may be larger in the future. + # + # The result may contain all the printable ASCII characters except for space. + # + # p SecureRandom.graph #=> "$|yjZXTSXL\Tg+ip" + # p SecureRandom.graph(10) #=> "<8Qz@py?LG" + # + # If a secure random number generator is not available, + # +NotImplementedError+ is raised. + def self.graph(n=nil) + choose(GRAPH, n) + end + + ALPHANUMERIC = [*'A'..'Z', *'a'..'z', *'0'..'9'] unless defined? ALPHANUMERIC + # SecureRandom.alphanumeric generates a random alphanumeric string. + # + # The argument _n_ specifies the length, in characters, of the alphanumeric + # string to be generated. + # + # If _n_ is not specified or is nil, 16 is assumed. + # It may be larger in the future. + # + # The result may contain A-Z, a-z and 0-9. + # + # p SecureRandom.alphanumeric #=> "2BuBuLf3WfSKyQbR" + # p SecureRandom.alphanumeric(10) #=> "i6K93NdqiH" + # + # If a secure random number generator is not available, + # +NotImplementedError+ is raised. + def self.alphanumeric(n=nil) + choose(ALPHANUMERIC, n) + end end