on master help sign in
Add servant-cassava.
commit9cea7902dfdc152de93010c5b09fd96f2a6d56b9 authorJulian K. Arni <jkarni@gmail.com> dateWed 4 Nov 2015, 15:47 (11 years ago) parentf525f5b
5 files changed+150
servant-cassava/LICENSE+30 servant-cassava/Setup.hs+2 servant-cassava/servant-cassava.cabal+29 servant-cassava/src/Servant/CSV/Cassava.hs+88 sources.txt+1
servant-cassava/LICENSEnew file+30
@@ -0,0 +1,30 @@
1+Copyright (c) 2015, Julian K. Arni
2+
3+All rights reserved.
4+
5+Redistribution and use in source and binary forms, with or without
6+modification, are permitted provided that the following conditions are met:
7+
8+ * Redistributions of source code must retain the above copyright
9+ notice, this list of conditions and the following disclaimer.
10+
11+ * Redistributions in binary form must reproduce the above
12+ copyright notice, this list of conditions and the following
13+ disclaimer in the documentation and/or other materials provided
14+ with the distribution.
15+
16+ * Neither the name of Julian K. Arni nor the names of other
17+ contributors may be used to endorse or promote products derived
18+ from this software without specific prior written permission.
19+
20+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
servant-cassava/Setup.hsnew file+2
@@ -0,0 +1,2 @@
1+import Distribution.Simple
2+main = defaultMain
servant-cassava/servant-cassava.cabalnew file+29
@@ -0,0 +1,29 @@
1+-- Initial servant-cassava.cabal generated by cabal init. For further
2+-- documentation, see http://haskell.org/cabal/users-guide/
3+
4+name: servant-cassava
5+version: 0.4.4.2
6+synopsis: Servant CSV content-type for cassava
7+-- description:
8+homepage: http://haskell-servant.github.io/
9+license: BSD3
10+license-file: LICENSE
11+author: Julian K. Arni
12+maintainer: jkarni@gmail.com
13+-- copyright:
14+-- category:
15+build-type: Simple
16+-- extra-source-files:
17+cabal-version: >=1.10
18+
19+library
20+ exposed-modules: Servant.CSV.Cassava
21+ -- other-modules:
22+ -- other-extensions:
23+ build-depends: base >=4.6 && <5
24+ , cassava >0.4 && <0.5
25+ , servant ==0.5.*
26+ , http-media
27+ , vector
28+ hs-source-dirs: src
29+ default-language: Haskell2010
servant-cassava/src/Servant/CSV/Cassava.hsnew file+88
@@ -0,0 +1,88 @@
1+{-# LANGUAGE DeriveDataTypeable #-}
2+{-# LANGUAGE DeriveGeneric #-}
3+{-# LANGUAGE FlexibleInstances #-}
4+{-# LANGUAGE MultiParamTypeClasses #-}
5+{-# LANGUAGE OverloadedStrings #-}
6+{-# LANGUAGE ScopedTypeVariables #-}
7+
8+-- | A @CSV@ empty datatype with `MimeRender` and `MimeUnrender` instances for
9+-- @cassava@'s encoding and decoding classes.
10+--
11+-- >>> type Eg = Get '[(CSV', MyEncodeOptions)] [(Int, String)]
12+--
13+-- Default encoding and decoding options are also provided, along with the
14+-- @CSV@ type synonym that uses them.
15+--
16+-- >>> type EgDefault = Get '[CSV] [(Int, String)]
17+module Servant.CSV.Cassava where
18+
19+import Data.Csv
20+import Data.Proxy (Proxy (..))
21+import Data.Typeable (Typeable)
22+import Data.Vector (Vector)
23+import GHC.Generics (Generic)
24+import qualified Network.HTTP.Media as M
25+import Servant.API (Accept (..), MimeRender (..),
26+ MimeUnrender (..))
27+
28+data CSV' deriving (Typeable, Generic)
29+
30+type CSV = (CSV', DefaultDecodeOpts)
31+
32+-- | @text/csv;charset=utf-8@
33+instance Accept (CSV', a) where
34+ contentType _ = "text" M.// "csv" M./: ("charset", "utf-8")
35+
36+-- * Encoding
37+
38+-- ** Instances
39+
40+-- | Encode with 'encodeByNameWith'. The 'Header' param is used for determining
41+-- the order of headers and fields.
42+instance ( ToNamedRecord a, EncodeOpts opt
43+ ) => MimeRender (CSV', opt) (Header, [a]) where
44+ mimeRender _ (hdr, vals) = encodeByNameWith (encodeOpts p) hdr vals
45+ where p = Proxy :: Proxy opt
46+
47+-- | Encode with 'encodeDefaultOrderedByNameWith'
48+instance ( DefaultOrdered a, ToNamedRecord a, EncodeOpts opt
49+ ) => MimeRender (CSV', opt) [a] where
50+ mimeRender _ = encodeDefaultOrderedByNameWith (encodeOpts p)
51+ where p = Proxy :: Proxy opt
52+
53+
54+-- ** Encode Options
55+
56+class EncodeOpts a where
57+ encodeOpts :: Proxy a -> EncodeOptions
58+
59+data DefaultEncodeOpts deriving (Typeable, Generic)
60+
61+instance EncodeOpts DefaultEncodeOpts where
62+ encodeOpts _ = defaultEncodeOptions
63+
64+-- * Decoding
65+
66+-- ** Instances
67+
68+-- | Decode with 'decodeByNameWith'
69+instance ( FromNamedRecord a, DecodeOpts opt
70+ ) => MimeUnrender (CSV', opt) (Header, Vector a) where
71+ mimeUnrender _ = decodeByNameWith (decodeOpts p)
72+ where p = Proxy :: Proxy opt
73+
74+-- | Decode with 'decodeWith'. Assumes data has headers, which are stripped.
75+instance ( FromRecord a, DecodeOpts opt
76+ ) => MimeUnrender (CSV', opt) (Vector a) where
77+ mimeUnrender _ = decodeWith (decodeOpts p) HasHeader
78+ where p = Proxy :: Proxy opt
79+
80+-- ** Decode Options
81+
82+class DecodeOpts a where
83+ decodeOpts :: Proxy a -> DecodeOptions
84+
85+data DefaultDecodeOpts deriving (Typeable, Generic)
86+
87+instance DecodeOpts DefaultDecodeOpts where
88+ decodeOpts _ = defaultDecodeOptions
sources.txt+1
@@ -1,4 +1,5 @@
11servant
2+servant-cassava
23servant-client
34servant-docs
45servant-jquery