;;;; This module wraps some fast_xml functionality, making results a little
;;;; easier to work with.
;;;;
(defmodule lxml-fast
  (export
   (parse 1) (parse 2)))

;;; Public functions

(defun parse (bytes)
  (parse bytes #m()))

(defun parse (bytes opts)
  (el->tuple (fxml_stream:parse_element bytes)
             opts))

;;; Private functions

(defun els->tuple (els)
  (els->tuple els #m() '()))

(defun els->tuple
  (('() _ acc)
   acc)
  ((`(,el . ,tail) opts acc)
   (els->tuple tail opts (append-acc acc (el->tuple el opts)))))

(defun el->tuple (el)
  (el->tuple el #m()))

(defun el->tuple
  ((`#(xmlel ,name ,attrs ,children) opts)
   `#(,(name name opts)
      ,(maps:from_list attrs)
      ,(els->tuple children opts '())))
  ((`#(xmlcdata ,data) _)
   (lutil-bin:trim-trailing-ws data))
  ((xml _)
   `#(error no-match ,xml)))

(defun name
  ((n `#m(atom-keys? ,akey?)) (when (is_binary n))
   (if akey?
     (list_to_atom (binary_to_list n))
     n))
  ((n _)
   n))

(defun append-acc
  ((acc #"")
   acc)
  ((acc '())
   acc)
  ((acc el) (when (is_list el))
   (++ acc el))
  ((acc el)
   (append-acc acc (list el))))
