   (:refer-clojure :exclude [type read float double long short byte bytes repeat])
   (:require [octet.buffer :as buffer]))
 
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Abstraction definition
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; --- Protocols
 
 (defprotocol ISpec
   "Basic abstraction for something that can be work like a Spec."

     (alter-meta! #'->AssociativeSpec assoc :private true)
     (alter-meta! #'->IndexedSpec assoc :private true)))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Spec Constructors
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defmulti spec
  "Polymorphic constructor for Spec instances.

  Spec is a some kind of composition of arbitrary


  The same rules applies for writing data into a
  buffer."
  [& params]
  (let [numparams (count params)]
    (cond
      (every? #(satisfies? ISpec %) params)
      (apply indexed-spec params)

      (and (even? numparams)
           (keyword? (first params))
           (satisfies? ISpec (second params)))
      (apply associative-spec params)

      :else
      (throw (ex-info "Invalid arguments" {})))))

(defn repeat
  "Creare a composed typespec that repeats `n` times
