1
1
module Functora.Rfc2397
2
- ( Media (.. ),
3
- Encoding (.. ),
2
+ ( Rfc2397 (.. ),
3
+ Rfc2397Encoding (.. ),
4
4
encodeRfc2397 ,
5
5
decodeRfc2397 ,
6
6
)
@@ -12,92 +12,96 @@ import qualified Network.URI as URI
12
12
import qualified Network.URI.Encode as UE
13
13
import qualified Prelude
14
14
15
- data Media = Media
16
- { mediaMime :: String ,
17
- mediaBytes :: ByteString ,
18
- mediaEncoding :: Encoding
15
+ data Rfc2397 = Rfc2397
16
+ { rfc2397Mime :: Unicode ,
17
+ rfc2397Bytes :: ByteString ,
18
+ rfc2397Encoding :: Rfc2397Encoding
19
19
}
20
20
deriving stock (Eq , Ord , Show , Data , Generic )
21
21
22
- instance Binary Media
22
+ instance Binary Rfc2397
23
23
24
- data Encoding = B64Encoding | UrlEncoding
24
+ data Rfc2397Encoding
25
+ = Rfc2397EncodingB64
26
+ | Rfc2397EncodingUrl
25
27
deriving stock (Eq , Ord , Show , Read , Data , Generic , Bounded , Enum )
26
28
27
- instance Binary Encoding
29
+ instance Binary Rfc2397Encoding
28
30
29
- encodeRfc2397 :: Media -> String
30
- encodeRfc2397 Media {mediaMime = mime, mediaBytes = bs, mediaEncoding = enc} =
31
- " data:"
32
- <> mime
33
- <> ( case enc of
34
- B64Encoding -> " ;base64"
35
- UrlEncoding -> mempty
36
- )
37
- <> " ,"
38
- <> ( case enc of
39
- B64Encoding ->
40
- either impureThrow id
41
- . decodeUtf8Strict
42
- $ B64. encode bs
43
- UrlEncoding ->
44
- either impureThrow (UE. encodeWith URI. isAllowedInURI)
45
- $ decodeUtf8Strict bs
46
- )
31
+ encodeRfc2397 :: Rfc2397 -> Unicode
32
+ encodeRfc2397
33
+ Rfc2397
34
+ { rfc2397Mime = mime,
35
+ rfc2397Bytes = bs,
36
+ rfc2397Encoding = enc
37
+ } =
38
+ " data:"
39
+ <> mime
40
+ <> ( case enc of
41
+ Rfc2397EncodingB64 -> " ;base64"
42
+ Rfc2397EncodingUrl -> mempty
43
+ )
44
+ <> " ,"
45
+ <> ( case enc of
46
+ Rfc2397EncodingB64 ->
47
+ either impureThrow id
48
+ . decodeUtf8Strict
49
+ $ B64. encode bs
50
+ Rfc2397EncodingUrl ->
51
+ either
52
+ impureThrow
53
+ ( from @ String @ Unicode
54
+ . UE. encodeWith URI. isAllowedInURI
55
+ )
56
+ $ decodeUtf8Strict bs
57
+ )
47
58
48
- decodeRfc2397 :: String -> Maybe Media
49
- decodeRfc2397 url =
50
- let (scheme, rest) = break (== ' :' ) url
51
- in case rest of
52
- ' :' : contents | scheme == " data" -> decodeContents contents
53
- _ -> Nothing
59
+ decodeRfc2397 :: Unicode -> Maybe Rfc2397
60
+ decodeRfc2397 xs =
61
+ case break (== ' :' ) xs of
62
+ (" data" , rhs) | not (null rhs) -> decodeContents $ drop 1 rhs
63
+ _ -> Nothing
54
64
55
- decodeContents :: String -> Maybe Media
65
+ decodeContents :: Unicode -> Maybe Rfc2397
56
66
decodeContents xs =
57
- let (prefix, restdata) = break (== ' ,' ) xs
58
- in case restdata of
59
- ' ,' : thedata -> decodePrefix prefix thedata
60
- _ -> Nothing
67
+ case break (== ' ,' ) xs of
68
+ (lhs, rhs) | not (null rhs) -> decodePrefix lhs $ drop 1 rhs
69
+ _ -> Nothing
61
70
62
- decodePrefix :: String -> String -> Maybe Media
71
+ decodePrefix :: Unicode -> Unicode -> Maybe Rfc2397
63
72
decodePrefix prefix thedata =
64
- let fragments = breakList (== ' ;' ) prefix
65
- enc = case reverse fragments of
66
- (" base64" : _) -> B64Encoding
67
- _ -> UrlEncoding
68
- mediapart
69
- | enc == B64Encoding = Prelude. init fragments
70
- | otherwise = fragments
71
- in case mediapart of
72
- (xs : _) ->
73
- case break (== ' /' ) xs of
74
- (_, [] ) -> decodeData (" text/plain" : mediapart) enc thedata
75
- _ -> decodeData mediapart enc thedata
76
- _ -> decodeData [" text/plain" , " charset=US-ASCII" ] enc thedata
73
+ case mediapart of
74
+ [] -> decodeData [" text/plain" , " charset=US-ASCII" ] enc thedata
75
+ (xs : _) ->
76
+ case break (== ' /' ) xs of
77
+ (_, [] ) -> decodeData (" text/plain" : mediapart) enc thedata
78
+ _ -> decodeData mediapart enc thedata
79
+ where
80
+ fragments = breakList (== ' ;' ) prefix
81
+ enc = case reverse fragments of
82
+ (" base64" : _) -> Rfc2397EncodingB64
83
+ _ -> Rfc2397EncodingUrl
84
+ mediapart
85
+ | enc == Rfc2397EncodingB64 = Prelude. init fragments
86
+ | otherwise = fragments
77
87
78
- decodeData :: [String ] -> Encoding -> String -> Maybe Media
88
+ decodeData :: [Unicode ] -> Rfc2397Encoding -> Unicode -> Maybe Rfc2397
79
89
decodeData mediatype enc thedata = do
80
90
bs <-
81
91
case enc of
82
- UrlEncoding ->
83
- pure . encodeUtf8 $ UE. decode thedata
84
- B64Encoding ->
92
+ Rfc2397EncodingUrl ->
93
+ pure . encodeUtf8 . UE. decode $ from @ Unicode @ String thedata
94
+ Rfc2397EncodingB64 ->
85
95
either (const Nothing ) Just . B64. decode $ encodeUtf8 thedata
86
96
pure
87
- Media
88
- { mediaMime = unparse mediatype,
89
- mediaBytes = bs,
90
- mediaEncoding = enc
97
+ Rfc2397
98
+ { rfc2397Mime = intercalate " ; " mediatype,
99
+ rfc2397Bytes = bs,
100
+ rfc2397Encoding = enc
91
101
}
92
102
93
- breakList :: (x -> Bool ) -> [x ] -> [[x ]]
94
- breakList p xs =
95
- let (pre, post) = break p xs
96
- in case post of
97
- [] -> [pre]
98
- _ : ys -> pre : breakList p ys
99
-
100
- unparse :: [String ] -> String
101
- unparse [] = " "
102
- unparse [xs] = xs
103
- unparse (xs : xss) = xs ++ ' ;' : unparse xss
103
+ breakList :: (Char -> Bool ) -> Unicode -> [Unicode ]
104
+ breakList f xs =
105
+ case break f xs of
106
+ (lhs, rhs) | null rhs -> [lhs]
107
+ (lhs, rhs) -> lhs : breakList f (drop 1 rhs)
0 commit comments