lib/iostruct.rb
def read src, size = nil
      size ||= const_get 'SIZE'
      data =
        if src.respond_to?(:read)
          src.read(size).to_s
        elsif src.respond_to?(:unpack)
          src
        else
          raise "[?] don't know how to read from #{src.inspect}"
        end
      if data.size < size
        $stderr.puts "[!] #{self.to_s} want #{size} bytes, got #{data.size}"
      end
      new(*data.unpack(const_get('FORMAT')))
    end
def read src, size = nil
      size ||= const_get 'SIZE'
      data =
        if src.respond_to?(:read)
          src.read(size).to_s
        elsif src.respond_to?(:unpack)
          src
        else
          raise "[?] don't know how to read from #{src.inspect}"
        end
      if data.size < size
        $stderr.puts "[!] #{self.to_s} want #{size} bytes, got #{data.size}"
      end
      new(*data.unpack(const_get('FORMAT')))
    end
src can be IO or String, or anything that responds to :read or :unpack