diff --git a/src/crystal/system.cr b/src/crystal/system.cr deleted file mode 100644 index 5ef653370048..000000000000 --- a/src/crystal/system.cr +++ /dev/null @@ -1,18 +0,0 @@ -# :nodoc: -module Crystal::System - # Returns the hostname - # def self.hostname - - # Returns the number of logical processors available to the system. - # - # def self.cpu_count -end - -require "./system/unix/hostname" - -{% if flag?(:freebsd) || flag?(:openbsd) %} - require "./system/unix/sysctl_cpucount" -{% else %} - # TODO: restrict on flag?(:unix) after crystal > 0.22.0 is released - require "./system/unix/sysconf_cpucount" -{% end %} diff --git a/src/crystal/system/random.cr b/src/crystal/system/random.cr deleted file mode 100644 index b98458c88622..000000000000 --- a/src/crystal/system/random.cr +++ /dev/null @@ -1,20 +0,0 @@ -module Crystal::System::Random - # Fills *buffer* with random bytes from a secure source. - # def self.random_bytes(buffer : Bytes) : Nil - - # Returns a random unsigned integer from a secure source. Implementations - # may choose the integer size to return based on what the system source - # provides. They may choose to return a single byte (UInt8) in which case - # `::Random` will prefer `#random_bytes` to read as many bytes as required - # at once, avoiding multiple reads or reading too many bytes. - # def self.next_u -end - -{% if flag?(:linux) %} - require "./unix/getrandom" -{% elsif flag?(:openbsd) %} - require "./unix/arc4random" -{% else %} - # TODO: restrict on flag?(:unix) after crystal > 0.22.0 is released - require "./unix/urandom" -{% end %} diff --git a/src/crystal/system/time.cr b/src/crystal/system/time.cr deleted file mode 100644 index b0e76f43b8c2..000000000000 --- a/src/crystal/system/time.cr +++ /dev/null @@ -1,11 +0,0 @@ -module Crystal::System::Time - # Returns the number of seconds that you must add to UTC to get local time. - # *seconds* are measured from `0001-01-01 00:00:00`. - # def self.compute_utc_offset(seconds : Int64) : Int64 - - # Returns the current UTC time measured in `{seconds, tenth_microsecond}` - # since `0001-01-01 00:00:00`. - # def self.compute_utc_second_and_tenth_microsecond : {Int64, Int64} -end - -require "./unix/time" diff --git a/src/platform_specific/random.cr b/src/platform_specific/random.cr new file mode 100644 index 000000000000..7561c93dd849 --- /dev/null +++ b/src/platform_specific/random.cr @@ -0,0 +1,8 @@ +{% if flag?(:linux) %} + require "./unix/getrandom" +{% elsif flag?(:openbsd) %} + require "./unix/arc4random" +{% else %} + # TODO: restrict on flag?(:unix) after crystal > 0.22.0 is released + require "./unix/urandom" +{% end %} diff --git a/src/platform_specific/system.cr b/src/platform_specific/system.cr new file mode 100644 index 000000000000..c41ae344ed36 --- /dev/null +++ b/src/platform_specific/system.cr @@ -0,0 +1,8 @@ +require "./unix/hostname" + +{% if flag?(:freebsd) || flag?(:openbsd) %} + require "./unix/sysctl_cpucount" +{% else %} + # TODO: restrict on flag?(:unix) after crystal > 0.22.0 is released + require "./unix/sysconf_cpucount" +{% end %} diff --git a/src/platform_specific/time.cr b/src/platform_specific/time.cr new file mode 100644 index 000000000000..f35bff5a95a9 --- /dev/null +++ b/src/platform_specific/time.cr @@ -0,0 +1 @@ +require "./unix/time" diff --git a/src/crystal/system/unix/arc4random.cr b/src/platform_specific/unix/arc4random.cr similarity index 63% rename from src/crystal/system/unix/arc4random.cr rename to src/platform_specific/unix/arc4random.cr index 863c0978eb3f..412566d995be 100644 --- a/src/crystal/system/unix/arc4random.cr +++ b/src/platform_specific/unix/arc4random.cr @@ -2,11 +2,11 @@ require "c/stdlib" -module Crystal::System::Random - # Fills *buffer* with random bytes using arc4random. - # - # NOTE: only secure on OpenBSD and CloudABI +module Random::System def self.random_bytes(buffer : Bytes) : Nil + # Fills *buffer* with random bytes using arc4random. + # + # NOTE: only secure on OpenBSD and CloudABI LibC.arc4random_buf(buffer.to_unsafe.as(Void*), buffer.size) end diff --git a/src/crystal/system/unix/getrandom.cr b/src/platform_specific/unix/getrandom.cr similarity index 96% rename from src/crystal/system/unix/getrandom.cr rename to src/platform_specific/unix/getrandom.cr index 616345173347..15409f318287 100644 --- a/src/crystal/system/unix/getrandom.cr +++ b/src/platform_specific/unix/getrandom.cr @@ -3,7 +3,7 @@ require "c/unistd" require "c/sys/syscall" -module Crystal::System::Random +module Random::System @@initialized = false @@getrandom_available = false @@urandom : File? @@ -23,8 +23,8 @@ module Crystal::System::Random end end - # Reads n random bytes using the Linux `getrandom(2)` syscall. def self.random_bytes(buf : Bytes) : Nil + # Reads n random bytes using the Linux `getrandom(2)` syscall. init unless @@initialized if @@getrandom_available diff --git a/src/crystal/system/unix/hostname.cr b/src/platform_specific/unix/hostname.cr similarity index 91% rename from src/crystal/system/unix/hostname.cr rename to src/platform_specific/unix/hostname.cr index e803ef514185..b497dce7efd5 100644 --- a/src/crystal/system/unix/hostname.cr +++ b/src/platform_specific/unix/hostname.cr @@ -1,6 +1,6 @@ require "c/unistd" -module Crystal::System +module System def self.hostname String.new(255) do |buffer| unless LibC.gethostname(buffer, LibC::SizeT.new(255)) == 0 diff --git a/src/crystal/system/unix/sysconf_cpucount.cr b/src/platform_specific/unix/sysconf_cpucount.cr similarity index 86% rename from src/crystal/system/unix/sysconf_cpucount.cr rename to src/platform_specific/unix/sysconf_cpucount.cr index 58eed376da5c..4a615e78dca7 100644 --- a/src/crystal/system/unix/sysconf_cpucount.cr +++ b/src/platform_specific/unix/sysconf_cpucount.cr @@ -2,7 +2,7 @@ require "c/unistd" -module Crystal::System +module System def self.cpu_count LibC.sysconf(LibC::SC_NPROCESSORS_ONLN) end diff --git a/src/crystal/system/unix/sysctl_cpucount.cr b/src/platform_specific/unix/sysctl_cpucount.cr similarity index 93% rename from src/crystal/system/unix/sysctl_cpucount.cr rename to src/platform_specific/unix/sysctl_cpucount.cr index f5646b1b0377..8f92e8685a9e 100644 --- a/src/crystal/system/unix/sysctl_cpucount.cr +++ b/src/platform_specific/unix/sysctl_cpucount.cr @@ -2,7 +2,7 @@ require "c/sysctl" -module Crystal::System +module System def self.cpu_count mib = Int32[LibC::CTL_HW, LibC::HW_NCPU] ncpus = 0 diff --git a/src/crystal/system/unix/time.cr b/src/platform_specific/unix/time.cr similarity index 88% rename from src/crystal/system/unix/time.cr rename to src/platform_specific/unix/time.cr index 2017c200e78e..4615ae2276d5 100644 --- a/src/crystal/system/unix/time.cr +++ b/src/platform_specific/unix/time.cr @@ -1,10 +1,10 @@ require "c/sys/time" require "c/time" -module Crystal::System::Time +struct Time UnixEpochInSeconds = 62135596800_i64 - def self.compute_utc_offset(seconds : Int64) : Int64 + private def self.compute_utc_offset(seconds : Int64) : Int64 LibC.tzset offset = nil @@ -26,7 +26,7 @@ module Crystal::System::Time offset end - def self.compute_utc_second_and_tenth_microsecond : {Int64, Int64} + private def self.compute_utc_second_and_tenth_microsecond : {Int64, Int64} {% if LibC.methods.includes?("clock_gettime".id) %} ret = LibC.clock_gettime(LibC::CLOCK_REALTIME, out timespec) raise Errno.new("clock_gettime") unless ret == 0 diff --git a/src/crystal/system/unix/urandom.cr b/src/platform_specific/unix/urandom.cr similarity index 96% rename from src/crystal/system/unix/urandom.cr rename to src/platform_specific/unix/urandom.cr index 424641890d40..0843013078d7 100644 --- a/src/crystal/system/unix/urandom.cr +++ b/src/platform_specific/unix/urandom.cr @@ -1,7 +1,7 @@ # TODO: replace with `flag?(:unix) && !flag?(:openbsd) && !flag?(:linux)` after crystal > 0.22.0 is released {% skip_file() if flag?(:openbsd) && flag?(:linux) %} -module Crystal::System::Random +module Random::System @@initialized = false @@urandom : File? diff --git a/src/random/isaac.cr b/src/random/isaac.cr index 03b5f7a994bf..54ead6a2c0d5 100644 --- a/src/random/isaac.cr +++ b/src/random/isaac.cr @@ -1,4 +1,4 @@ -require "crystal/system/random" +require "random/system" # (c) Bob Jenkins, March 1996, Public Domain # You may use this code in any way you wish, and it is free. No warrantee. @@ -17,7 +17,7 @@ class Random::ISAAC private def random_seeds result = uninitialized Seeds result_slice = result.unsafe_as(StaticArray(UInt8, sizeof(Seeds))).to_slice - Crystal::System::Random.random_bytes(result_slice) + Random::System.random_bytes(result_slice) result end diff --git a/src/random/system.cr b/src/random/system.cr index 54fdbebfd440..f12411ef7b05 100644 --- a/src/random/system.cr +++ b/src/random/system.cr @@ -1,5 +1,3 @@ -require "crystal/system/random" - # Generates random numbers from a secure source of the system. # # For example `arc4random` is used on OpenBSD, whereas on Linux it uses @@ -12,17 +10,26 @@ require "crystal/system/random" # ``` module Random::System extend Random - extend self - def next_u - Crystal::System::Random.next_u + # Fills *buffer* with random bytes from a secure source. + def self.random_bytes(buffer : Bytes) : Nil + {% raise "Not implemented for this system" %} + end + + # Returns a random unsigned integer from a secure source. Implementations + # may choose the integer size to return based on what the system source + # provides. They may choose to return a single byte (UInt8) in which case + # `::Random` will prefer `#random_bytes` to read as many bytes as required + # at once, avoiding multiple reads or reading too many bytes. + def self.next_u + {% raise "Not implemented for this system" %} end {% for type in [UInt8, UInt16, UInt32, UInt64] %} # Generates a random integer of a given type. The number of bytes to # generate can be limited; by default it will generate as many bytes as # needed to fill the integer size. - private def rand_type(type : {{type}}.class, needed_parts = nil) : {{type}} + private def self.rand_type(type : {{type}}.class, needed_parts = nil) : {{type}} needed_bytes = if needed_parts needed_parts * sizeof(typeof(next_u)) @@ -34,22 +41,24 @@ module Random::System if needed_bytes < sizeof({{type}}) bytes = Slice.new(buf.to_unsafe, needed_bytes) - Crystal::System::Random.random_bytes(bytes) + random_bytes(bytes) bytes.reduce({{type}}.new(0)) do |result, byte| (result << 8) | byte end else - Crystal::System::Random.random_bytes(buf.to_slice) + random_bytes(buf.to_slice) buf.to_unsafe.as({{type}}*).value end end {% end %} {% for type in [Int8, Int16, Int32, Int64] %} - private def rand_type(type : {{type}}.class, needed_bytes = sizeof({{type}})) : {{type}} + private def self.rand_type(type : {{type}}.class, needed_bytes = sizeof({{type}})) : {{type}} result = rand_type({{"U#{type}".id}}, needed_bytes) {{type}}.new(result) end {% end %} end + +require "platform_specific/random" diff --git a/src/secure_random.cr b/src/secure_random.cr index d713f1a95a38..7867bb59681a 100644 --- a/src/secure_random.cr +++ b/src/secure_random.cr @@ -1,5 +1,4 @@ require "base64" -require "crystal/system/random" # The `SecureRandom` module is an interface for creating cryptography secure # random values in different formats. @@ -74,7 +73,7 @@ module SecureRandom # slice # => [217, 118, 38, 196] # ``` def self.random_bytes(buf : Bytes) : Nil - Crystal::System::Random.random_bytes(buf) + Random::System.random_bytes(buf) end # Generates a UUID (Universally Unique Identifier). diff --git a/src/system.cr b/src/system.cr index 6746651caeb0..1b8198cf1680 100644 --- a/src/system.cr +++ b/src/system.cr @@ -1,5 +1,3 @@ -require "crystal/system" - module System # Returns the hostname. # @@ -11,7 +9,7 @@ module System # System.hostname # => "host.example.org" # ``` def self.hostname - Crystal::System.hostname + {% raise "Not implemented for this system" %} end # Returns the number of logical processors available to the system. @@ -20,6 +18,8 @@ module System # System.cpu_count # => 4 # ``` def self.cpu_count - Crystal::System.cpu_count + {% raise "Not implemented for this system" %} end end + +require "platform_specific/system" diff --git a/src/time.cr b/src/time.cr index 9d2c270f1148..737d8d3db082 100644 --- a/src/time.cr +++ b/src/time.cr @@ -1,5 +1,3 @@ -require "crystal/system/time" - # `Time` represents an instance in time. Here are some examples: # # ### Basic Usage @@ -600,12 +598,25 @@ struct Time end private def self.compute_offset(second) - Crystal::System::Time.compute_utc_offset(second) / 60 * Span::TicksPerMinute + compute_utc_offset(second) / 60 * Span::TicksPerMinute end private def self.compute_second_and_tenth_microsecond - Crystal::System::Time.compute_utc_second_and_tenth_microsecond + compute_utc_second_and_tenth_microsecond + end + + # Returns the number of seconds that you must add to UTC to get local time. + # *seconds* are measured from `0001-01-01 00:00:00`. + private def self.compute_utc_offset(seconds : Int64) : Int64 + {% raise "Not implemented for this system" %} + end + + # Returns the current UTC time measured in `{seconds, tenth_microsecond}` + # since `0001-01-01 00:00:00`. + private def self.compute_utc_second_and_tenth_microsecond : {Int64, Int64} + {% raise "Not implemented for this system" %} end end require "./time/**" +require "platform_specific/time"