Search code examples
crystal-lang

Add the CRC32 checksum value of each character of a string, into an array


I'm trying to loop through a string and get the CRC32 checksum of each character into an array. I'm doing so by using the .each_char method:

def calculate_signature(data)
  signature = [] of UInt32
  data.each_char do |c|
    signature << CRC32.checksum(c)
  end
end

When I run this I get a really long unhelpful error message.

Error in sigwaf.cr:4: instantiating 'calculate_signature(String)'

calculate_signature("yrdy")
^~~~~~~~~~~~~~~~~~~

in lib/settings.cr:17: instantiating 'String#each_char()'

  data.each_char do |c|
       ^~~~~~~~~

in /usr/local/Cellar/crystal/0.29.0/src/string.cr:3773: instantiating 'each_byte()'

      each_byte do |byte|
      ^~~~~~~~~

in /usr/local/Cellar/crystal/0.29.0/src/string.cr:3881: instantiating 'Slice(UInt8)#each()'

    to_slice.each do |byte|
             ^~~~

in /usr/local/Cellar/crystal/0.29.0/src/indexable.cr:187: instantiating 'each_index()'

    each_index do |i|
    ^~~~~~~~~~

in /usr/local/Cellar/crystal/0.29.0/src/indexable.cr:187: instantiating 'each_index()'

    each_index do |i|
    ^~~~~~~~~~

in /usr/local/Cellar/crystal/0.29.0/src/string.cr:3881: instantiating 'Slice(UInt8)#each()'

    to_slice.each do |byte|
             ^~~~

in /usr/local/Cellar/crystal/0.29.0/src/string.cr:3773: instantiating 'each_byte()'

      each_byte do |byte|
      ^~~~~~~~~

in lib/settings.cr:17: instantiating 'String#each_char()'

  data.each_char do |c|
       ^~~~~~~~~

in lib/settings.cr:18: instantiating 'CRC32:Module#checksum(Char)'

    signature >> CRC32.checksum(c)
                       ^~~~~~~~

in /usr/local/Cellar/crystal/0.29.0/src/crc32/crc32.cr:9: instantiating 'update(Char, UInt32)'

    update(data, initial)
    ^~~~~~

in /usr/local/Cellar/crystal/0.29.0/src/crc32/crc32.cr:13: undefined method 'to_slice' for Char

    slice = data.to_slice
                 ^~~~~~~~

Rerun with --error-trace to show a complete error trace.

How can I successfully add the crc32 checksum into an array?


Solution

  • Try this:

    require "crc32"
    
    def calculate_signature(data)
      signature = [] of UInt32
      data.chars.each do |c|
        signature << CRC32.checksum(c.to_s)
      end
      signature
    end
    
    puts calculate_signature("string")
    

    You got the error because Char is not an array of String, it is another type array of Chars. The Char does not have method .to_slice calling by CRC32 on this row and it raising errors. I just add .to_s for Chart in each and it works. Also you can replace .chars to .split("") and got the same result.

    Error message «undefined method 'to_slice' for Char» exactly about it.