     (.setReadCapacityUnits  (long read-units))
     (.setWriteCapacityUnits (long write-units))))
 
-;;;; Coercions
+;;;; Coercion - values
+
+;; TODO Nippy support (will require special marker bin-wrapping), incl.
+;; Serialized (boxed) type (should allow empty strings & ANY type of set)
+;; Maybe require special wrapper types for writing bins/serialized
 
 (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."
-  ;; TODO Nippy support
   [^AttributeValue x]
   (or (.getS x)
       (some->> (.getN  x) str->num)

     (.setTableName (str name))
     (.setProvisionedThroughput (provisioned-throughput throughput)))))

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

(extend-protocol AsMap
  KeySchemaElement
  (as-map [element]
    {:name (.getAttributeName element)
     :type (-> (.getAttributeType element)
               (str/lower-case)
               (keyword))})
  KeySchema
  (as-map [schema]
    (merge
     (when-let [e (.getHashKeyElement schema)]  {:hash-key  (as-map e)})
     (when-let [e (.getRangeKeyElement schema)] {:range-key (as-map e)})))
  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))}))
  BatchWriteResponse
  (as-map [result]
    {:consumed-capacity-units (.getConsumedCapacityUnits result)})
  BatchWriteItemResult
  (as-map [result]
    {:responses         (utils/fmap as-map (into {} (.getResponses result)))
     :unprocessed-items (.getUnprocessedItems result)})
  BatchResponse
  (as-map [result]
    {:consumed-capacity-units (.getConsumedCapacityUnits result)
     :items (some->> (.getItems result)
                     (into [])
                     (utils/fmap #(utils/fmap db-val->clj-val (into {} %))))})
  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)))}))

(defn describe-table
  "Returns a map describing the table in DynamoDB with the given name, or nil
  if the table doesn't exist."


(defn- clj-val->db-val
  "Returns an AttributeValue object for given Clojure value."
  [x]
  (cond
   (string? x)          (if (.isEmpty ^String x)
