;;;; util.lisp -- functions that come in handy in crypto applications

(in-package :crypto)

(defun byte-array-to-hex-string (vector &key (start 0) end (element-type 'character))
  "Return a string containing the hexadecimal representation of the
subsequence of VECTOR between START and END.  ELEMENT-TYPE controls
the element-type of the returned string."
  (let* ((end (or end (length vector)))
         (length (- end start))
         (hexdigits "0123456789abcdef"))
    (loop with string = (make-string (* length 2)
                                     :element-type element-type)
          for i from start below end
          for j from 0 below (* length 2) by 2
          do (let ((byte (aref vector i)))
               (setf (aref string j)
                     (aref hexdigits (ldb (byte 4 4) byte))
                     (aref string (1+ j))
                     (aref hexdigits (ldb (byte 4 0) byte))))
          finally (return string))))

(defun ascii-string-to-byte-array (string &key (start 0) end)
  "Convert STRING to a (VECTOR (UNSIGNED-BYTE 8)).  It is an error if
STRING contains any character whose CHAR-CODE is greater than 255."
  (let ((vec (make-array (length string) :element-type '(unsigned-byte 8)))
        (end (or end (length string))))
    (loop for i from start below end do
          (let ((byte (char-code (char string i))))
            (unless (< byte 256)
              (error "~A is not an ASCII character" (char string i)))
            (setf (aref vec i) byte))
          finally (return vec))))
