/
encoding.clj
52 lines (47 loc) · 1.54 KB
/
encoding.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
(ns aleph.http.encoding
(:require
[clj-commons.byte-streams :as bs]
[clj-commons.primitive-math :as p])
(:import
[io.netty.buffer
ByteBuf
Unpooled]
[io.netty.handler.codec.base64
Base64]))
(set! *unchecked-math* true)
(defn qp-byte [^long b]
(if (and (not= b 61) (or (= b 9) (<= 32 b 126)))
(str (char b))
(str "=" (.toUpperCase (Long/toHexString b)))))
(let [^objects encodings (->> (range 256) (map qp-byte) into-array)]
(defn encode-qp [val]
(let [sb (StringBuffer.)
^bytes ary (bs/to-byte-array val)
len (alength ary)]
(loop [i 0, newline 71]
(when (p/< i len)
(let [b (p/byte->ubyte (aget ary i))]
(.append sb ^String (aget encodings b))
(if (p/< newline (.length sb))
(do
(.append sb "=\n")
(recur (p/inc i) (p/+ newline 76)))
(recur (p/inc i) newline)))))
(str sb))))
(defn encode-base64 [val]
(let [cb (-> val bs/to-byte-buffer Unpooled/wrappedBuffer)
encoded (Base64/encode cb)
r (byte-array (.capacity ^ByteBuf encoded))
_ (.getBytes ^ByteBuf encoded 0 r)]
(.release ^ByteBuf cb)
(.release ^ByteBuf encoded)
(bs/to-byte-buffer r)))
(defn encode [val encoding]
(case encoding
:base64 (encode-base64 val)
:quoted-printable (encode-qp val)
:qp (encode-qp val)
;; "binary" effectively means "do nothing"
:binary val
(throw (IllegalArgumentException.
(str "unsupported encodiing given:" (pr-str encoding))))))