4 , GeneralizedNewtypeDeriving
5 , MultiParamTypeClasses
11 module Data.URI.Internal.Scheme
15 import Data.Ascii (AsciiBuilder, CIAscii)
16 import qualified Data.Ascii as A
17 import Data.Attoparsec.Char8
18 import qualified Data.ByteString.Char8 as BS
19 import Data.CaseInsensitive
20 import Data.Convertible.Base
24 import Data.URI.Internal
26 import Prelude hiding (takeWhile)
27 import Prelude.Unicode
29 -- |'Scheme' names consist of a non-empty sequence of characters
30 -- beginning with a letter and followed by any combination of letters,
31 -- digits, plus (\'+\'), period (\'.\'), or hyphen (\'-\'). Comparison
32 -- of 'Scheme's are always case-insensitive. See:
33 -- <http://tools.ietf.org/html/rfc3986#section-3.1>
34 newtype Scheme = Scheme CIAscii
43 -- |'fromString' is a fast but unsafe way to create 'Scheme' such that
44 -- no validation on the string is performed.
45 deriving instance IsString Scheme
47 instance Default (Parser Scheme) where
48 {-# INLINEABLE def #-}
49 def = do x ← satisfy first
50 xs ← takeWhile nonFirst
51 return ∘ fromBS $ x `BS.cons` xs
57 {-# INLINE nonFirst #-}
65 fromBS = Scheme ∘ A.toCIAscii ∘ A.unsafeFromByteString
67 -- |Extract a 'CIAscii' with all letters lowercased.
68 instance ConvertSuccess Scheme CIAscii where
69 {-# INLINE convertSuccess #-}
70 convertSuccess (Scheme s) = foldCase s
72 -- |Create an 'AsciiBuilder' with all letters lowercased.
73 instance ConvertSuccess Scheme AsciiBuilder where
74 {-# INLINE convertSuccess #-}
75 convertSuccess = A.toAsciiBuilder ∘ A.fromCIAscii ∘ cs
77 -- |Try to parse a 'Scheme' from 'CIAscii'.
78 instance ConvertAttempt CIAscii Scheme where
79 {-# INLINE convertAttempt #-}
80 convertAttempt = parseAttempt' def ∘ A.fromCIAscii
82 deriveAttempts [ ([t| Scheme |], [t| AsciiBuilder |])
83 , ([t| Scheme |], [t| CIAscii |])