       .listTables
       .getTableNames
       seq))
+
+;;;; TODO Code walk-through below
 
 ;;;; API - items
 


;;;; Coercion - objects

(defn- db-map->clj-map [x] (when x (utils/fmap db-val->clj-val (into {} x))))

(defprotocol AsMap (as-map [x]))

(extend-protocol AsMap

  java.util.ArrayList (as-map [alist] (into [] (map as-map alist)))
  java.util.HashMap   (as-map [hmap] (utils/fmap as-map (into {} hmap)))
  AttributeValue      (as-map [aval] (db-val->clj-val aval))
  KeySchemaElement    (as-map [element] {:name (.getAttributeName element)})

  ProvisionedThroughputDescription
  (as-map [throughput] {:read  (.getReadCapacityUnits throughput)
                        :write (.getWriteCapacityUnits throughput)
                        :last-decrease (.getLastDecreaseDateTime throughput)
                        :last-increase (.getLastIncreaseDateTime throughput)})

  DescribeTableResult
  (as-map [result] (let [table (.getTable result)]
                     {:name          (.getTableName table)
                      :creation-date (.getCreationDateTime table)
                      :item-count    (.getItemCount table)
                      :key-schema    (as-map (.getKeySchema table))
                      :throughput    (as-map (.getProvisionedThroughput table))
                      :status        (-> (.getTableStatus table)
                                         (str/lower-case)
                                         (keyword))}))

  BatchWriteItemResult
  (as-map [result] {:unprocessed-items (into {} (.getUnprocessedItems result))})

  KeysAndAttributes
  (as-map [result]
    (merge
     (when-let [a (.getAttributesToGet result)] {:attrs (into [] a)})
     (when-let [c (.getConsistentRead result)]  {:consistent c})
     (when-let [k (.getKeys result)]            {:keys (utils/fmap as-map (into [] k))})))

  BatchGetItemResult
  (as-map [result]
    {:responses        (utils/fmap as-map (into {} (.getResponses result)))
     :unprocessed-keys (utils/fmap as-map (into {} (.getUnprocessedKeys result)))})

  GetItemResult (as-map [result] (db-map->clj-map (.getItem result)))

  QueryResult
  (as-map [results] {:items    (map db-map->clj-map (.getItems results))
                     :count    (.getCount results)
                     :last-key (as-map (.getLastEvaluatedKey results))})

  ScanResult
  (as-map [results] {:items    (map db-map->clj-map (.getItems results))
                     :count    (.getCount results)
                     :last-key (as-map (.getLastEvaluatedKey results))})

  nil (as-map [_] nil))

;;;; API - tables


(defn- str->num [^String s] (if (.contains s ".") (Double. s) (Long. s)))
(defn- bb->ba   [^ByteBuffer bb] (.array bb))

(defn- db-val->clj-val "Returns the Clojure value of given AttributeValue object."
  [^AttributeValue x]
  (or (.getS x)
      (some->> (.getN  x) str->num)
