Skip to content

Instantly share code, notes, and snippets.

@sniperliu
Last active March 28, 2016 05:48
Show Gist options
  • Save sniperliu/91993c79e03f52831c6b to your computer and use it in GitHub Desktop.
Save sniperliu/91993c79e03f52831c6b to your computer and use it in GitHub Desktop.
(ns clj-bt.bencoding
(:require [clojure.string :as s]
[the.parsatron :as p :refer [defparser let->> >>]]))
;; decoding
(defparser zero [] (>> (p/char \0) (p/always 0)))
(defparser non-zero [] (p/token #{\1 \2 \3 \4 \5 \6 \7 \8 \9}))
(defparser positive []
(let->> [fst (non-zero)
rst (p/many (p/digit))]
(p/always (Integer/parseInt (apply str (conj rst fst))))))
(defparser negative []
(let->> [_ (p/char \-)
num (positive)]
(p/always (- num))))
(defparser integer []
(p/choice (positive) (zero) (negative)))
(declare ben-string ben-integer ben-list ben-map ben-value)
(defparser ben-string []
(let->> [length (positive)
_ (p/char \:)
chs (p/times length (p/any-char))]
(p/always (apply str chs))))
(defparser ben-integer []
(p/between (p/char \i) (p/char \e) (integer)))
(defparser ben-list []
(p/between (p/char \l) (p/char \e) (p/many (ben-value))))
(defparser ben-map []
(let->> [ds (p/between (p/char \d)
(p/char \e)
(p/many1 (let->> [k (ben-string)
v (ben-value)]
(p/always [k v]))))]
(p/always (into (sorted-map) ds))))
(defparser ben-value []
(p/choice (ben-string) (ben-integer) (ben-list) (ben-map)))
(defn decode [s]
(p/run (ben-value) s))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment