packages feed

burrito 2.0.1.2 → 2.0.1.3

raw patch · 24 files changed

+1823/−1813 lines, 24 filesdep ~basedep ~bytestringdep ~containersPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base, bytestring, containers, template-haskell, text

API changes (from Hackage documentation)

Files

LICENSE.markdown view
@@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 Taylor Fausak+Copyright (c) 2023 Taylor Fausak  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal
burrito.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.2  name: burrito-version: 2.0.1.2+version: 2.0.1.3  synopsis: Parse and render URI templates. description:@@ -39,12 +39,12 @@  common library   build-depends:-    , base >= 4.13.0 && < 4.18-    , bytestring >= 0.10.10 && < 0.12-    , containers >= 0.6.2 && < 0.7+    , base >= 4.15.0 && < 4.18+    , bytestring >= 0.10.12 && < 0.12+    , containers >= 0.6.4 && < 0.7     , parsec >= 3.1.14 && < 3.2-    , template-haskell >= 2.15.0 && < 2.20-    , text >= 1.2.4 && < 1.3 || >= 2.0 && < 2.1+    , template-haskell >= 2.17.0 && < 2.20+    , text >= 1.2.5 && < 1.3 || >= 2.0 && < 2.1     , transformers >= 0.5.6 && < 0.6   default-language: Haskell2010   ghc-options:@@ -54,21 +54,18 @@     -Wno-missed-specialisations     -Wno-missing-deriving-strategies     -Wno-missing-exported-signatures+    -Wno-missing-safe-haskell-mode+    -Wno-prepositive-qualified-module     -Wno-safe     -Wno-unsafe -  if flag(pedantic)-    ghc-options: -Werror--  if impl(ghc >= 8.10)-    ghc-options:-      -Wno-missing-safe-haskell-mode-      -Wno-prepositive-qualified-module-   if impl(ghc >= 9.2)     ghc-options:       -Wno-missing-kind-signatures +  if flag(pedantic)+    ghc-options: -Werror+ common executable   import: library @@ -105,7 +102,7 @@     Burrito.Internal.Type.Variable   hs-source-dirs: source/library -test-suite test+test-suite burrito-test-suite   import: executable    build-depends:
source/library/Burrito.hs view
@@ -27,19 +27,20 @@ -- -- In short, use @parse@ to parse templates and @expand@ to render them. module Burrito-  ( Parse.parse-  , Template.render-  , Expand.expand-  , Expand.expandWith-  , Match.match-  , TH.uriTemplate-  , TH.expandTH-  , Template.Template-  , Value.Value-  , stringValue-  , listValue-  , dictionaryValue-  ) where+  ( Parse.parse,+    Template.render,+    Expand.expand,+    Expand.expandWith,+    Match.match,+    TH.uriTemplate,+    TH.expandTH,+    Template.Template,+    Value.Value,+    stringValue,+    listValue,+    dictionaryValue,+  )+where  import qualified Burrito.Internal.Expand as Expand import qualified Burrito.Internal.Match as Match
source/library/Burrito/Internal/Expand.hs view
@@ -43,9 +43,10 @@ expand :: [(String, Value.Value)] -> Template.Template -> String expand values =   let m = Map.mapKeys Text.pack $ Map.fromList values-  in-    Render.builderToString . Identity.runIdentity . expandWith-      (pure . flip Map.lookup m)+   in Render.builderToString+        . Identity.runIdentity+        . expandWith+          (pure . flip Map.lookup m)  -- | This is like @expand@ except that it gives you more control over how -- variables are expanded. If you can, use @expand@. It's simpler.@@ -68,20 +69,20 @@ -- >>> expandWith (\ x -> do { putStrLn $ "-- expanding " <> show x; pure . Just $ Burrito.stringValue "A" }) template -- -- expanding "a" -- "AA"-expandWith-  :: Monad m-  => (Text.Text -> m (Maybe Value.Value))-  -> Template.Template-  -> m Builder.Builder+expandWith ::+  (Monad m) =>+  (Text.Text -> m (Maybe Value.Value)) ->+  Template.Template ->+  m Builder.Builder expandWith f = flip State.evalStateT Map.empty . template (cached f)  type CacheT = State.StateT (Map.Map Text.Text (Maybe Value.Value)) -cached-  :: Monad m-  => (Text.Text -> m (Maybe Value.Value))-  -> Name.Name-  -> CacheT m (Maybe Value.Value)+cached ::+  (Monad m) =>+  (Text.Text -> m (Maybe Value.Value)) ->+  Name.Name ->+  CacheT m (Maybe Value.Value) cached f x = do   let key = LazyText.toStrict . Builder.toLazyText $ name x   cache <- State.get@@ -92,39 +93,38 @@       State.modify $ Map.insert key result       pure result -template-  :: Monad m-  => (Name.Name -> CacheT m (Maybe Value.Value))-  -> Template.Template-  -> CacheT m Builder.Builder+template ::+  (Monad m) =>+  (Name.Name -> CacheT m (Maybe Value.Value)) ->+  Template.Template ->+  CacheT m Builder.Builder template f = fmap mconcat . traverse (token f) . Template.tokens -token-  :: Monad m-  => (Name.Name -> CacheT m (Maybe Value.Value))-  -> Token.Token-  -> CacheT m Builder.Builder+token ::+  (Monad m) =>+  (Name.Name -> CacheT m (Maybe Value.Value)) ->+  Token.Token ->+  CacheT m Builder.Builder token f x = case x of   Token.Expression y -> expression f y   Token.Literal y -> pure $ literal y -expression-  :: Monad m-  => (Name.Name -> CacheT m (Maybe Value.Value))-  -> Expression.Expression-  -> CacheT m Builder.Builder+expression ::+  (Monad m) =>+  (Name.Name -> CacheT m (Maybe Value.Value)) ->+  Expression.Expression ->+  CacheT m Builder.Builder expression f ex =   let op = Expression.operator ex-  in-    fmap-      (mconcat-      . (\xs -> if null xs then xs else prefix op : xs)-      . List.intersperse (separator op)-      . Maybe.catMaybes-      )-    . traverse (variable f op)-    . NonEmpty.toList-    $ Expression.variables ex+   in fmap+        ( mconcat+            . (\xs -> if null xs then xs else prefix op : xs)+            . List.intersperse (separator op)+            . Maybe.catMaybes+        )+        . traverse (variable f op)+        . NonEmpty.toList+        $ Expression.variables ex  separator :: Operator.Operator -> Builder.Builder separator op = Builder.singleton $ case op of@@ -148,79 +148,79 @@   Operator.Semicolon -> Builder.singleton ';'   Operator.Solidus -> Builder.singleton '/' -variable-  :: Monad m-  => (Name.Name -> CacheT m (Maybe Value.Value))-  -> Operator.Operator-  -> Variable.Variable-  -> CacheT m (Maybe Builder.Builder)+variable ::+  (Monad m) =>+  (Name.Name -> CacheT m (Maybe Value.Value)) ->+  Operator.Operator ->+  Variable.Variable ->+  CacheT m (Maybe Builder.Builder) variable f op var = do   res <- f $ Variable.name var   pure $ case res of     Nothing -> Nothing     Just val -> value op var val -value-  :: Operator.Operator-  -> Variable.Variable-  -> Value.Value-  -> Maybe Builder.Builder+value ::+  Operator.Operator ->+  Variable.Variable ->+  Value.Value ->+  Maybe Builder.Builder value op var val = case val of   Value.Dictionary xs -> dictionaryValue op var $ Map.toAscList xs   Value.List xs -> listValue op var xs   Value.String x -> Just $ stringValue op var x -dictionaryValue-  :: Operator.Operator-  -> Variable.Variable-  -> [(Text.Text, Text.Text)]-  -> Maybe Builder.Builder+dictionaryValue ::+  Operator.Operator ->+  Variable.Variable ->+  [(Text.Text, Text.Text)] ->+  Maybe Builder.Builder dictionaryValue = items $ \op var (k, v) ->   let f = string op Modifier.None-  in-    case Variable.modifier var of-      Modifier.Asterisk -> [f k <> Builder.singleton '=' <> f v]-      _ -> [f k, f v]+   in case Variable.modifier var of+        Modifier.Asterisk -> [f k <> Builder.singleton '=' <> f v]+        _ -> [f k, f v] -listValue-  :: Operator.Operator-  -> Variable.Variable-  -> [Text.Text]-  -> Maybe Builder.Builder-listValue = items $ \op var -> pure . stringValue-  (case Variable.modifier var of-    Modifier.Asterisk -> op-    _ -> Operator.None-  )-  var { Variable.modifier = Modifier.None }+listValue ::+  Operator.Operator ->+  Variable.Variable ->+  [Text.Text] ->+  Maybe Builder.Builder+listValue = items $ \op var ->+  pure+    . stringValue+      ( case Variable.modifier var of+          Modifier.Asterisk -> op+          _ -> Operator.None+      )+      var {Variable.modifier = Modifier.None} -items-  :: (Operator.Operator -> Variable.Variable -> a -> [Builder.Builder])-  -> Operator.Operator-  -> Variable.Variable-  -> [a]-  -> Maybe Builder.Builder+items ::+  (Operator.Operator -> Variable.Variable -> a -> [Builder.Builder]) ->+  Operator.Operator ->+  Variable.Variable ->+  [a] ->+  Maybe Builder.Builder items f op var xs =-  let-    md = Variable.modifier var-    sep = case md of-      Modifier.Asterisk -> separator op-      _ -> Builder.singleton ','-    p = case md of-      Modifier.Asterisk -> False-      _ -> case op of-        Operator.Ampersand -> True-        Operator.QuestionMark -> True-        Operator.Semicolon -> True-        _ -> False-  in if null xs-    then Nothing-    else-      Just-      . mconcat-      . (if p then (label True var :) else id)-      . List.intersperse sep-      $ concatMap (f op var) xs+  let md = Variable.modifier var+      sep = case md of+        Modifier.Asterisk -> separator op+        _ -> Builder.singleton ','+      p = case md of+        Modifier.Asterisk -> False+        _ -> case op of+          Operator.Ampersand -> True+          Operator.QuestionMark -> True+          Operator.Semicolon -> True+          _ -> False+   in if null xs+        then Nothing+        else+          Just+            . mconcat+            . (if p then (label True var :) else id)+            . List.intersperse sep+            $ concatMap (f op var) xs  label :: Bool -> Variable.Variable -> Builder.Builder label p v =@@ -242,29 +242,27 @@   Character.Encoded y z -> Render.encodedCharacter y z   Character.Unencoded y -> unencodedCharacter f y -stringValue-  :: Operator.Operator -> Variable.Variable -> Text.Text -> Builder.Builder+stringValue ::+  Operator.Operator -> Variable.Variable -> Text.Text -> Builder.Builder stringValue op var str =-  let-    pre = case op of-      Operator.Ampersand -> label True var-      Operator.QuestionMark -> label True var-      Operator.Semicolon -> label (not $ Text.null str) var-      _ -> mempty-  in pre <> string op (Variable.modifier var) str+  let pre = case op of+        Operator.Ampersand -> label True var+        Operator.QuestionMark -> label True var+        Operator.Semicolon -> label (not $ Text.null str) var+        _ -> mempty+   in pre <> string op (Variable.modifier var) str -string-  :: Operator.Operator -> Modifier.Modifier -> Text.Text -> Builder.Builder+string ::+  Operator.Operator -> Modifier.Modifier -> Text.Text -> Builder.Builder string op md =-  let-    allowed x = case op of-      Operator.NumberSign -> isAllowed x-      Operator.PlusSign -> isAllowed x-      _ -> isUnreserved x-    trim = case md of-      Modifier.Colon ml -> Text.take $ MaxLength.count ml-      _ -> id-  in foldMap (unencodedCharacter allowed) . Text.unpack . trim+  let allowed x = case op of+        Operator.NumberSign -> isAllowed x+        Operator.PlusSign -> isAllowed x+        _ -> isUnreserved x+      trim = case md of+        Modifier.Colon ml -> Text.take $ MaxLength.count ml+        _ -> id+   in foldMap (unencodedCharacter allowed) . Text.unpack . trim  isAllowed :: Char -> Bool isAllowed x = isUnreserved x || isReserved x@@ -300,9 +298,10 @@   _ -> False  unencodedCharacter :: (Char -> Bool) -> Char -> Builder.Builder-unencodedCharacter f x = if f x-  then Builder.singleton x-  else foldMap (uncurry Render.encodedCharacter) $ encodeCharacter x+unencodedCharacter f x =+  if f x+    then Builder.singleton x+    else foldMap (uncurry Render.encodedCharacter) $ encodeCharacter x  encodeCharacter :: Char -> [(Digit.Digit, Digit.Digit)] encodeCharacter =
source/library/Burrito/Internal/Match.hs view
@@ -70,8 +70,8 @@     Just (Render.builderToString $ Render.name n, Value.String v)   Match.Undefined -> Nothing -keepConsistent-  :: [(Name.Name, Match.Match)] -> Maybe [(Name.Name, Match.Match)]+keepConsistent ::+  [(Name.Name, Match.Match)] -> Maybe [(Name.Name, Match.Match)] keepConsistent xs = case xs of   [] -> Just xs   (k, v) : ys -> do@@ -90,8 +90,8 @@     Match.Prefix n t -> case y of       Match.Defined u | t == Text.take (MaxLength.count n) u -> combine y zs       Match.Prefix m u-        | let c = MaxLength.count (min n m) in Text.take c t == Text.take c u-        -> combine (if m > n then y else x) zs+        | let c = MaxLength.count (min n m) in Text.take c t == Text.take c u ->+            combine (if m > n then y else x) zs       _ -> Nothing     Match.Undefined -> case y of       Match.Undefined -> combine x zs@@ -111,10 +111,10 @@ expression :: Expression.Expression -> ReadP.ReadP [(Name.Name, Match.Match)] expression x = variables (Expression.operator x) (Expression.variables x) -variables-  :: Operator.Operator-  -> NonEmpty.NonEmpty Variable.Variable-  -> ReadP.ReadP [(Name.Name, Match.Match)]+variables ::+  Operator.Operator ->+  NonEmpty.NonEmpty Variable.Variable ->+  ReadP.ReadP [(Name.Name, Match.Match)] variables op vs = case op of   Operator.Ampersand -> vars vs (Just '&') '&' varEq   Operator.FullStop -> vars vs (Just '.') '.' $ variable Expand.isUnreserved@@ -130,43 +130,41 @@       variable Expand.isUnreserved v   Operator.Solidus -> vars vs (Just '/') '/' $ variable Expand.isUnreserved -vars-  :: NonEmpty.NonEmpty Variable.Variable-  -> Maybe Char-  -> Char-  -> (Variable.Variable -> ReadP.ReadP [(Name.Name, Match.Match)])-  -> ReadP.ReadP [(Name.Name, Match.Match)]+vars ::+  NonEmpty.NonEmpty Variable.Variable ->+  Maybe Char ->+  Char ->+  (Variable.Variable -> ReadP.ReadP [(Name.Name, Match.Match)]) ->+  ReadP.ReadP [(Name.Name, Match.Match)] vars vs m c f = do-  let-    ctx = case m of-      Nothing -> id-      Just o -> \p -> ReadP.option (undef <$> NonEmpty.toList vs) $ do-        char_ o-        xs <- p-        Monad.guard . not $ all isUndefined xs-        pure xs+  let ctx = case m of+        Nothing -> id+        Just o -> \p -> ReadP.option (undef <$> NonEmpty.toList vs) $ do+          char_ o+          xs <- p+          Monad.guard . not $ all isUndefined xs+          pure xs   ctx . vars' c f $ NonEmpty.toList vs  isUndefined :: (Name.Name, Match.Match) -> Bool isUndefined = (== Match.Undefined) . snd -vars'-  :: Char-  -> (Variable.Variable -> ReadP.ReadP [(Name.Name, Match.Match)])-  -> [Variable.Variable]-  -> ReadP.ReadP [(Name.Name, Match.Match)]+vars' ::+  Char ->+  (Variable.Variable -> ReadP.ReadP [(Name.Name, Match.Match)]) ->+  [Variable.Variable] ->+  ReadP.ReadP [(Name.Name, Match.Match)] vars' c f vs = case vs of   [] -> pure []   v : ws ->-    let-      this = do-        x <- f v-        xs <- ReadP.option (undef <$> ws) $ do-          char_ c-          vars' c f ws-        pure $ x <> xs-      that = (undef v :) <$> vars' c f ws-    in this ReadP.+++ that+    let this = do+          x <- f v+          xs <- ReadP.option (undef <$> ws) $ do+            char_ c+            vars' c f ws+          pure $ x <> xs+        that = (undef v :) <$> vars' c f ws+     in this ReadP.+++ that  undef :: Variable.Variable -> (Name.Name, Match.Match) undef v = (Variable.name v, Match.Undefined)@@ -183,10 +181,10 @@ name :: Name.Name -> ReadP.ReadP () name = Monad.void . ReadP.string . Render.builderToString . Render.name -variable-  :: (Char -> Bool)-  -> Variable.Variable-  -> ReadP.ReadP [(Name.Name, Match.Match)]+variable ::+  (Char -> Bool) ->+  Variable.Variable ->+  ReadP.ReadP [(Name.Name, Match.Match)] variable f x = do   v <- case Variable.modifier x of     Modifier.Asterisk -> ReadP.pfail@@ -196,9 +194,8 @@  manyCharacters :: (Char -> Bool) -> ReadP.ReadP Text.Text manyCharacters f = do-  let-    f1 = (:) <$> someEncodedCharacters <*> ReadP.option [] f2-    f2 = (:) <$> someUnencodedCharacters f <*> ReadP.option [] f1+  let f1 = (:) <$> someEncodedCharacters <*> ReadP.option [] f2+      f2 = (:) <$> someUnencodedCharacters f <*> ReadP.option [] f1   fmap mconcat . ReadP.option [] $ f1 ReadP.<++ f2  someEncodedCharacters :: ReadP.ReadP Text.Text@@ -268,6 +265,7 @@   Digit.OxF Case.Lower -> 'f'  unencodedCharacter :: (Char -> Bool) -> Char -> ReadP.ReadP ()-unencodedCharacter f x = if f x-  then char_ x-  else mapM_ (uncurry encodedCharacter) $ Expand.encodeCharacter x+unencodedCharacter f x =+  if f x+    then char_ x+    else mapM_ (uncurry encodedCharacter) $ Expand.encodeCharacter x
source/library/Burrito/Internal/Parse.hs view
@@ -1,6 +1,5 @@-{-# OPTIONS_GHC -Wno-missing-export-lists #-}- {-# LANGUAGE FlexibleContexts #-}+{-# OPTIONS_GHC -Wno-missing-export-lists #-}  module Burrito.Internal.Parse where @@ -37,72 +36,74 @@ parse :: String -> Maybe Template.Template parse = either (const Nothing) Just . Parsec.parse template "" -template :: Parsec.Stream s m Char => Parsec.ParsecT s u m Template.Template+template :: (Parsec.Stream s m Char) => Parsec.ParsecT s u m Template.Template template = Template.Template <$> Parsec.many token <* Parsec.eof -token :: Parsec.Stream s m Char => Parsec.ParsecT s u m Token.Token+token :: (Parsec.Stream s m Char) => Parsec.ParsecT s u m Token.Token token = choice (Token.Expression <$> expression) (Token.Literal <$> literal) -choice-  :: Parsec.ParsecT s u m a -> Parsec.ParsecT s u m a -> Parsec.ParsecT s u m a+choice ::+  Parsec.ParsecT s u m a -> Parsec.ParsecT s u m a -> Parsec.ParsecT s u m a choice = (Parsec.<|>) -expression-  :: Parsec.Stream s m Char => Parsec.ParsecT s u m Expression.Expression+expression ::+  (Parsec.Stream s m Char) => Parsec.ParsecT s u m Expression.Expression expression =-  Parsec.between (Parsec.char '{') (Parsec.char '}')-    $ Expression.Expression-    <$> operator-    <*> sepBy1 variable (Parsec.char ',')+  Parsec.between (Parsec.char '{') (Parsec.char '}') $+    Expression.Expression+      <$> operator+      <*> sepBy1 variable (Parsec.char ',') -operator :: Parsec.Stream s m Char => Parsec.ParsecT s u m Operator.Operator-operator = Parsec.option Operator.None $ Parsec.choice-  [ Operator.Ampersand <$ Parsec.char '&'-  , Operator.FullStop <$ Parsec.char '.'-  , Operator.NumberSign <$ Parsec.char '#'-  , Operator.PlusSign <$ Parsec.char '+'-  , Operator.QuestionMark <$ Parsec.char '?'-  , Operator.Semicolon <$ Parsec.char ';'-  , Operator.Solidus <$ Parsec.char '/'-  ]+operator :: (Parsec.Stream s m Char) => Parsec.ParsecT s u m Operator.Operator+operator =+  Parsec.option Operator.None $+    Parsec.choice+      [ Operator.Ampersand <$ Parsec.char '&',+        Operator.FullStop <$ Parsec.char '.',+        Operator.NumberSign <$ Parsec.char '#',+        Operator.PlusSign <$ Parsec.char '+',+        Operator.QuestionMark <$ Parsec.char '?',+        Operator.Semicolon <$ Parsec.char ';',+        Operator.Solidus <$ Parsec.char '/'+      ] -sepBy1-  :: Parsec.ParsecT s u m a-  -> Parsec.ParsecT s u m x-  -> Parsec.ParsecT s u m (NonEmpty.NonEmpty a)+sepBy1 ::+  Parsec.ParsecT s u m a ->+  Parsec.ParsecT s u m x ->+  Parsec.ParsecT s u m (NonEmpty.NonEmpty a) sepBy1 p s = (NonEmpty.:|) <$> p <*> Parsec.many (s *> p) -variable :: Parsec.Stream s m Char => Parsec.ParsecT s u m Variable.Variable+variable :: (Parsec.Stream s m Char) => Parsec.ParsecT s u m Variable.Variable variable = Variable.Variable <$> name <*> modifier -name :: Parsec.Stream s m Char => Parsec.ParsecT s u m Name.Name+name :: (Parsec.Stream s m Char) => Parsec.ParsecT s u m Name.Name name = Name.Name <$> sepBy1 field (Parsec.char '.') -field :: Parsec.Stream s m Char => Parsec.ParsecT s u m Field.Field+field :: (Parsec.Stream s m Char) => Parsec.ParsecT s u m Field.Field field = Field.Field <$> nonEmpty fieldCharacter -nonEmpty-  :: Parsec.ParsecT s u m a -> Parsec.ParsecT s u m (NonEmpty.NonEmpty a)+nonEmpty ::+  Parsec.ParsecT s u m a -> Parsec.ParsecT s u m (NonEmpty.NonEmpty a) nonEmpty p = (NonEmpty.:|) <$> p <*> Parsec.many p -fieldCharacter-  :: Parsec.Stream s m Char-  => Parsec.ParsecT s u m (Character.Character Field.Field)+fieldCharacter ::+  (Parsec.Stream s m Char) =>+  Parsec.ParsecT s u m (Character.Character Field.Field) fieldCharacter = choice encodedCharacter (unencodedCharacter isFieldCharacter) -encodedCharacter-  :: Parsec.Stream s m Char => Parsec.ParsecT s u m (Character.Character tag)+encodedCharacter ::+  (Parsec.Stream s m Char) => Parsec.ParsecT s u m (Character.Character tag) encodedCharacter = Parsec.char '%' >> Character.Encoded <$> digit <*> digit -digit :: Parsec.Stream s m Char => Parsec.ParsecT s u m Digit.Digit+digit :: (Parsec.Stream s m Char) => Parsec.ParsecT s u m Digit.Digit digit = do   x <- Parsec.satisfy Char.isHexDigit   maybe (fail "invalid Digit") pure $ Digit.fromChar x -unencodedCharacter-  :: Parsec.Stream s m Char-  => (Char -> Bool)-  -> Parsec.ParsecT s u m (Character.Character tag)+unencodedCharacter ::+  (Parsec.Stream s m Char) =>+  (Char -> Bool) ->+  Parsec.ParsecT s u m (Character.Character tag) unencodedCharacter = fmap Character.Unencoded . Parsec.satisfy  isFieldCharacter :: Char -> Bool@@ -110,14 +111,16 @@   '_' -> True   _ -> Char.isAsciiUpper x || Char.isAsciiLower x || Char.isDigit x -modifier :: Parsec.Stream s m Char => Parsec.ParsecT s u m Modifier.Modifier-modifier = Parsec.option Modifier.None $ Parsec.choice-  [ Modifier.Asterisk <$ Parsec.char '*'-  , Parsec.char ':' >> Modifier.Colon <$> maxLength-  ]+modifier :: (Parsec.Stream s m Char) => Parsec.ParsecT s u m Modifier.Modifier+modifier =+  Parsec.option Modifier.None $+    Parsec.choice+      [ Modifier.Asterisk <$ Parsec.char '*',+        Parsec.char ':' >> Modifier.Colon <$> maxLength+      ] -maxLength-  :: Parsec.Stream s m Char => Parsec.ParsecT s u m MaxLength.MaxLength+maxLength ::+  (Parsec.Stream s m Char) => Parsec.ParsecT s u m MaxLength.MaxLength maxLength = do   x <- Parsec.satisfy $ Ix.inRange ('1', '9')   xs <- Parsec.many $ Parsec.satisfy Char.isDigit@@ -129,12 +132,12 @@ isMaxLength :: Int -> Bool isMaxLength = Ix.inRange (1, 9999) -literal :: Parsec.Stream s m Char => Parsec.ParsecT s u m Literal.Literal+literal :: (Parsec.Stream s m Char) => Parsec.ParsecT s u m Literal.Literal literal = Literal.Literal <$> nonEmpty literalCharacter -literalCharacter-  :: Parsec.Stream s m Char-  => Parsec.ParsecT s u m (Character.Character Literal.Literal)+literalCharacter ::+  (Parsec.Stream s m Char) =>+  Parsec.ParsecT s u m (Character.Character Literal.Literal) literalCharacter =   choice encodedCharacter (unencodedCharacter isLiteralCharacter) 
source/library/Burrito/Internal/Render.hs view
@@ -45,11 +45,11 @@   Operator.Semicolon -> Builder.singleton ';'   Operator.Solidus -> Builder.singleton '/' -sepBy1-  :: (a -> Builder.Builder)-  -> Builder.Builder-  -> NonEmpty.NonEmpty a-  -> Builder.Builder+sepBy1 ::+  (a -> Builder.Builder) ->+  Builder.Builder ->+  NonEmpty.NonEmpty a ->+  Builder.Builder sepBy1 f x = mconcat . List.intersperse x . fmap f . NonEmpty.toList  variable :: Variable.Variable -> Builder.Builder
source/library/Burrito/Internal/TH.hs view
@@ -1,7 +1,8 @@ module Burrito.Internal.TH-  ( expandTH-  , uriTemplate-  ) where+  ( expandTH,+    uriTemplate,+  )+where  import qualified Burrito.Internal.Expand as Expand import qualified Burrito.Internal.Parse as Parse@@ -27,14 +28,13 @@ -- "l-bar-r" expandTH :: [(String, Value.Value)] -> Template.Template -> TH.Q TH.Exp expandTH xs t = do-  let-    m = Map.fromList $ fmap (Bifunctor.first Text.pack) xs-    f k =-      maybe (Left $ "missing variable: " <> show k) (Right . Just)-        $ Map.lookup k m+  let m = Map.fromList $ fmap (Bifunctor.first Text.pack) xs+      f k =+        maybe (Left $ "missing variable: " <> show k) (Right . Just) $+          Map.lookup k m   x <--    either fail (pure . LazyText.unpack . Builder.toLazyText)-      $ Expand.expandWith f t+    either fail (pure . LazyText.unpack . Builder.toLazyText) $+      Expand.expandWith f t   TH.lift x  -- | This can be used together with the @QuasiQuotes@ language extension to@@ -53,9 +53,10 @@ -- this is invalid: @[uriTemplate|\\xa0|]@. You can however use percent encoded -- triples as normal. So this is valid: @[uriTemplate|%c2%a0|]@. uriTemplate :: TH.QuasiQuoter-uriTemplate = TH.QuasiQuoter-  { TH.quoteDec = const $ fail "cannot be used as a declaration"-  , TH.quoteExp = maybe (fail "invalid URI template") TH.liftData . Parse.parse-  , TH.quotePat = const $ fail "cannot be used as a pattern"-  , TH.quoteType = const $ fail "cannot be used as a type"-  }+uriTemplate =+  TH.QuasiQuoter+    { TH.quoteDec = const $ fail "cannot be used as a declaration",+      TH.quoteExp = maybe (fail "invalid URI template") TH.liftData . Parse.parse,+      TH.quotePat = const $ fail "cannot be used as a pattern",+      TH.quoteType = const $ fail "cannot be used as a type"+    }
source/library/Burrito/Internal/Type/Case.hs view
@@ -1,8 +1,9 @@ {-# LANGUAGE DeriveDataTypeable #-}  module Burrito.Internal.Type.Case-  ( Case(..)-  ) where+  ( Case (..),+  )+where  import qualified Data.Data as Data 
source/library/Burrito/Internal/Type/Character.hs view
@@ -1,8 +1,9 @@ {-# LANGUAGE DeriveDataTypeable #-}  module Burrito.Internal.Type.Character-  ( Character(..)-  ) where+  ( Character (..),+  )+where  import qualified Burrito.Internal.Type.Digit as Digit import qualified Data.Data as Data
source/library/Burrito/Internal/Type/Digit.hs view
@@ -1,11 +1,12 @@ {-# LANGUAGE DeriveDataTypeable #-}  module Burrito.Internal.Type.Digit-  ( Digit(..)-  , fromChar-  , fromWord8-  , toWord8-  ) where+  ( Digit (..),+    fromChar,+    fromWord8,+    toWord8,+  )+where  import qualified Burrito.Internal.Type.Case as Case import qualified Data.Bits as Bits@@ -59,47 +60,45 @@  fromWord8 :: Word.Word8 -> (Digit, Digit) fromWord8 x =-  let-    f :: Word.Word8 -> Digit-    f y = case y of-      0x0 -> Ox0-      0x1 -> Ox1-      0x2 -> Ox2-      0x3 -> Ox3-      0x4 -> Ox4-      0x5 -> Ox5-      0x6 -> Ox6-      0x7 -> Ox7-      0x8 -> Ox8-      0x9 -> Ox9-      0xA -> OxA Case.Upper-      0xB -> OxB Case.Upper-      0xC -> OxC Case.Upper-      0xD -> OxD Case.Upper-      0xE -> OxE Case.Upper-      0xF -> OxF Case.Upper-      _ -> error $ "invalid nibble: " <> show y-  in (f $ Bits.shiftR x 4, f $ x Bits..&. 0x0F)+  let f :: Word.Word8 -> Digit+      f y = case y of+        0x0 -> Ox0+        0x1 -> Ox1+        0x2 -> Ox2+        0x3 -> Ox3+        0x4 -> Ox4+        0x5 -> Ox5+        0x6 -> Ox6+        0x7 -> Ox7+        0x8 -> Ox8+        0x9 -> Ox9+        0xA -> OxA Case.Upper+        0xB -> OxB Case.Upper+        0xC -> OxC Case.Upper+        0xD -> OxD Case.Upper+        0xE -> OxE Case.Upper+        0xF -> OxF Case.Upper+        _ -> error $ "invalid nibble: " <> show y+   in (f $ Bits.shiftR x 4, f $ x Bits..&. 0x0F)  toWord8 :: Digit -> Digit -> Word.Word8 toWord8 x y =-  let-    f :: Digit -> Word.Word8-    f z = case z of-      Ox0 -> 0x0-      Ox1 -> 0x1-      Ox2 -> 0x2-      Ox3 -> 0x3-      Ox4 -> 0x4-      Ox5 -> 0x5-      Ox6 -> 0x6-      Ox7 -> 0x7-      Ox8 -> 0x8-      Ox9 -> 0x9-      OxA _ -> 0xA-      OxB _ -> 0xB-      OxC _ -> 0xC-      OxD _ -> 0xD-      OxE _ -> 0xE-      OxF _ -> 0xF-  in Bits.shiftL (f x) 4 Bits..|. f y+  let f :: Digit -> Word.Word8+      f z = case z of+        Ox0 -> 0x0+        Ox1 -> 0x1+        Ox2 -> 0x2+        Ox3 -> 0x3+        Ox4 -> 0x4+        Ox5 -> 0x5+        Ox6 -> 0x6+        Ox7 -> 0x7+        Ox8 -> 0x8+        Ox9 -> 0x9+        OxA _ -> 0xA+        OxB _ -> 0xB+        OxC _ -> 0xC+        OxD _ -> 0xD+        OxE _ -> 0xE+        OxF _ -> 0xF+   in Bits.shiftL (f x) 4 Bits..|. f y
source/library/Burrito/Internal/Type/Expression.hs view
@@ -1,8 +1,9 @@ {-# LANGUAGE DeriveDataTypeable #-}  module Burrito.Internal.Type.Expression-  ( Expression(..)-  ) where+  ( Expression (..),+  )+where  import qualified Burrito.Internal.Type.Operator as Operator import qualified Burrito.Internal.Type.Variable as Variable@@ -10,7 +11,7 @@ import qualified Data.List.NonEmpty as NonEmpty  data Expression = Expression-  { operator :: Operator.Operator-  , variables :: NonEmpty.NonEmpty Variable.Variable+  { operator :: Operator.Operator,+    variables :: NonEmpty.NonEmpty Variable.Variable   }   deriving (Data.Data, Eq, Ord, Show)
source/library/Burrito/Internal/Type/Field.hs view
@@ -1,8 +1,9 @@ {-# LANGUAGE DeriveDataTypeable #-}  module Burrito.Internal.Type.Field-  ( Field(..)-  ) where+  ( Field (..),+  )+where  import qualified Burrito.Internal.Type.Character as Character import qualified Data.Data as Data@@ -10,4 +11,5 @@  newtype Field = Field   { characters :: NonEmpty.NonEmpty (Character.Character Field)-  } deriving (Data.Data, Eq, Ord, Show)+  }+  deriving (Data.Data, Eq, Ord, Show)
source/library/Burrito/Internal/Type/Literal.hs view
@@ -1,8 +1,9 @@ {-# LANGUAGE DeriveDataTypeable #-}  module Burrito.Internal.Type.Literal-  ( Literal(..)-  ) where+  ( Literal (..),+  )+where  import qualified Burrito.Internal.Type.Character as Character import qualified Data.Data as Data@@ -10,4 +11,5 @@  newtype Literal = Literal   { characters :: NonEmpty.NonEmpty (Character.Character Literal)-  } deriving (Data.Data, Eq, Ord, Show)+  }+  deriving (Data.Data, Eq, Ord, Show)
source/library/Burrito/Internal/Type/Match.hs view
@@ -1,8 +1,9 @@ {-# LANGUAGE DeriveDataTypeable #-}  module Burrito.Internal.Type.Match-  ( Match(..)-  ) where+  ( Match (..),+  )+where  import qualified Burrito.Internal.Type.MaxLength as MaxLength import qualified Data.Data as Data
source/library/Burrito/Internal/Type/MaxLength.hs view
@@ -1,11 +1,13 @@ {-# LANGUAGE DeriveDataTypeable #-}  module Burrito.Internal.Type.MaxLength-  ( MaxLength(..)-  ) where+  ( MaxLength (..),+  )+where  import qualified Data.Data as Data  newtype MaxLength = MaxLength   { count :: Int-  } deriving (Data.Data, Eq, Ord, Show)+  }+  deriving (Data.Data, Eq, Ord, Show)
source/library/Burrito/Internal/Type/Modifier.hs view
@@ -1,8 +1,9 @@ {-# LANGUAGE DeriveDataTypeable #-}  module Burrito.Internal.Type.Modifier-  ( Modifier(..)-  ) where+  ( Modifier (..),+  )+where  import qualified Burrito.Internal.Type.MaxLength as MaxLength import qualified Data.Data as Data
source/library/Burrito/Internal/Type/Name.hs view
@@ -1,8 +1,9 @@ {-# LANGUAGE DeriveDataTypeable #-}  module Burrito.Internal.Type.Name-  ( Name(..)-  ) where+  ( Name (..),+  )+where  import qualified Burrito.Internal.Type.Field as Field import qualified Data.Data as Data@@ -10,4 +11,5 @@  newtype Name = Name   { fields :: NonEmpty.NonEmpty Field.Field-  } deriving (Data.Data, Eq, Ord, Show)+  }+  deriving (Data.Data, Eq, Ord, Show)
source/library/Burrito/Internal/Type/Operator.hs view
@@ -1,8 +1,9 @@ {-# LANGUAGE DeriveDataTypeable #-}  module Burrito.Internal.Type.Operator-  ( Operator(..)-  ) where+  ( Operator (..),+  )+where  import qualified Data.Data as Data 
source/library/Burrito/Internal/Type/Template.hs view
@@ -1,9 +1,10 @@ {-# LANGUAGE DeriveDataTypeable #-}  module Burrito.Internal.Type.Template-  ( Template(..)-  , render-  ) where+  ( Template (..),+    render,+  )+where  import qualified Burrito.Internal.Render as Render import qualified Burrito.Internal.Type.Token as Token@@ -13,7 +14,8 @@ -- | Represents a URI template. newtype Template = Template   { tokens :: [Token.Token]-  } deriving (Data.Data, Eq, Ord)+  }+  deriving (Data.Data, Eq, Ord)  instance Show Template where   show = render
source/library/Burrito/Internal/Type/Token.hs view
@@ -1,8 +1,9 @@ {-# LANGUAGE DeriveDataTypeable #-}  module Burrito.Internal.Type.Token-  ( Token(..)-  ) where+  ( Token (..),+  )+where  import qualified Burrito.Internal.Type.Expression as Expression import qualified Burrito.Internal.Type.Literal as Literal
source/library/Burrito/Internal/Type/Value.hs view
@@ -1,8 +1,9 @@ {-# LANGUAGE DeriveDataTypeable #-}  module Burrito.Internal.Type.Value-  ( Value(..)-  ) where+  ( Value (..),+  )+where  import qualified Data.Data as Data import qualified Data.Map as Map
source/library/Burrito/Internal/Type/Variable.hs view
@@ -1,15 +1,16 @@ {-# LANGUAGE DeriveDataTypeable #-}  module Burrito.Internal.Type.Variable-  ( Variable(..)-  ) where+  ( Variable (..),+  )+where  import qualified Burrito.Internal.Type.Modifier as Modifier import qualified Burrito.Internal.Type.Name as Name import qualified Data.Data as Data  data Variable = Variable-  { name :: Name.Name-  , modifier :: Modifier.Modifier+  { name :: Name.Name,+    modifier :: Modifier.Modifier   }   deriving (Data.Data, Eq, Ord, Show)
source/test-suite/Main.hs view
@@ -1,1466 +1,1459 @@-{-# OPTIONS_GHC -Wno-monomorphism-restriction #-}--{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE QuasiQuotes #-}--module Main-  ( main-  ) where--import qualified Burrito-import qualified Burrito.Internal.Parse as Parse-import qualified Burrito.Internal.Render as Render-import qualified Burrito.Internal.Type.Case as Case-import qualified Burrito.Internal.Type.Character as Character-import qualified Burrito.Internal.Type.Digit as Digit-import qualified Burrito.Internal.Type.Expression as Expression-import qualified Burrito.Internal.Type.Field as Field-import qualified Burrito.Internal.Type.Literal as Literal-import qualified Burrito.Internal.Type.MaxLength as MaxLength-import qualified Burrito.Internal.Type.Modifier as Modifier-import qualified Burrito.Internal.Type.Name as Name-import qualified Burrito.Internal.Type.Operator as Operator-import qualified Burrito.Internal.Type.Template as Template-import qualified Burrito.Internal.Type.Token as Token-import qualified Burrito.Internal.Type.Value as Value-import qualified Burrito.Internal.Type.Variable as Variable-import qualified Control.Monad as Monad-import qualified Data.List as List-import qualified Data.List.NonEmpty as NonEmpty-import qualified Data.Map as Map-import qualified Data.Maybe as Maybe-import qualified Data.Set as Set-import qualified Data.String as String-import qualified Data.Text as Text-import qualified GHC.Stack as Stack-import qualified Test.Hspec as Hspec-import qualified Test.Hspec.QuickCheck as Hspec-import qualified Test.QuickCheck as QC--main :: IO ()-main = Hspec.hspec . Hspec.describe "Burrito" $ do--  Monad.forM_ tests $ \test ->-    Hspec.it (show (testInput test, unwrapOutput $ testOutput test))-      $ runTest test--  Hspec.describe "match" $ do-    let-      matchTest-        :: Stack.HasCallStack-        => String-        -> [(String, Burrito.Value)]-        -> String-        -> Hspec.Spec-      matchTest input values output = Hspec.it (show (input, output)) $ do-        template <- maybe (fail "invalid Template") pure $ Burrito.parse input-        let matches = Burrito.match output template-        matches `Hspec.shouldSatisfy` elem values-        Monad.forM_ matches $ \match -> do-          let it = Burrito.expand match template-          Monad.when (it /= output) . fail $ show-            (input, values, output, matches, match, it)--    matchTest "" [] ""-    matchTest "a" [] "a"-    matchTest "!" [] "!"-    matchTest "\xa0" [] "%C2%A0"--    matchTest "{a}" ["a" =: s ""] ""-    matchTest "{a}" ["a" =: s "A"] "A"-    matchTest "{a}" ["a" =: s "AB"] "AB"--    matchTest "a{b}" ["b" =: s ""] "a"-    matchTest "a{b}" ["b" =: s "B"] "aB"-    matchTest "a{b}" ["b" =: s "BC"] "aBC"--    matchTest "{a}b" ["a" =: s ""] "b"-    matchTest "{a}b" ["a" =: s "A"] "Ab"-    matchTest "{a}b" ["a" =: s "AB"] "ABb"--    matchTest "{a}{a}" ["a" =: s "A"] "AA"-    matchTest "{a}{a}" ["a" =: s "AB"] "ABAB"--    matchTest "{a}" ["a" =: s "%"] "%25"-    matchTest "{a}" ["a" =: s "/"] "%2F"-    matchTest "{a}" ["a" =: s "\xa0"] "%C2%A0"-    matchTest "{a}" ["a" =: s "\xd7ff"] "%ED%9F%BF"-    matchTest "{a}" ["a" =: s "\x10000"] "%F0%90%80%80"-    matchTest "{a}" ["a" =: s "A/B"] "A%2FB"-    matchTest "{a}" ["a" =: s "WX\xa0\xa1YZ"] "WX%C2%A0%C2%A1YZ"--    matchTest "{+a}" ["a" =: s "%"] "%25"-    matchTest "{+a}" ["a" =: s "/"] "/"--    matchTest "{#a}" [] ""-    matchTest "{#a}" ["a" =: s ""] "#"-    matchTest "{#a}" ["a" =: s "A"] "#A"-    matchTest "{#a}" ["a" =: s "%"] "#%25"-    matchTest "{#a}" ["a" =: s "/"] "#/"--    matchTest "{.a}" [] ""-    matchTest "{.a}" ["a" =: s ""] "."-    matchTest "{.a}" ["a" =: s "A"] ".A"-    matchTest "{.a}" ["a" =: s "%"] ".%25"-    matchTest "{.a}" ["a" =: s "/"] ".%2F"--    matchTest "{/a}" [] ""-    matchTest "{/a}" ["a" =: s ""] "/"-    matchTest "{/a}" ["a" =: s "A"] "/A"-    matchTest "{/a}" ["a" =: s "%"] "/%25"-    matchTest "{/a}" ["a" =: s "/"] "/%2F"--    matchTest "{;a}" [] ""-    matchTest "{;a}" ["a" =: s ""] ";a"-    matchTest "{;a}" ["a" =: s "A"] ";a=A"-    matchTest "{;a}" ["a" =: s "%"] ";a=%25"-    matchTest "{;a}" ["a" =: s "/"] ";a=%2F"--    matchTest "{?a}" [] ""-    matchTest "{?a}" ["a" =: s ""] "?a="-    matchTest "{?a}" ["a" =: s "A"] "?a=A"-    matchTest "{?a}" ["a" =: s "%"] "?a=%25"-    matchTest "{?a}" ["a" =: s "/"] "?a=%2F"--    matchTest "{&a}" [] ""-    matchTest "{&a}" ["a" =: s ""] "&a="-    matchTest "{&a}" ["a" =: s "A"] "&a=A"-    matchTest "{&a}" ["a" =: s "%"] "&a=%25"-    matchTest "{&a}" ["a" =: s "/"] "&a=%2F"--    matchTest "{a,b}" ["a" =: s "A", "b" =: s "B"] "A,B"-    matchTest "{+a,b}" ["a" =: s "A", "b" =: s "B"] "A,B"-    matchTest "{#a,b}" ["a" =: s "A", "b" =: s "B"] "#A,B"-    matchTest "{.a,b}" ["a" =: s "A", "b" =: s "B"] ".A.B"-    matchTest "{/a,b}" ["a" =: s "A", "b" =: s "B"] "/A/B"-    matchTest "{;a,b}" ["a" =: s "A", "b" =: s "B"] ";a=A;b=B"-    matchTest "{?a,b}" ["a" =: s "A", "b" =: s "B"] "?a=A&b=B"-    matchTest "{&a,b}" ["a" =: s "A", "b" =: s "B"] "&a=A&b=B"--    matchTest "{a,b}" ["a" =: s "A"] "A"-    matchTest "{a,b,c}" ["a" =: s "A"] "A"-    matchTest "{a,b,c}" ["a" =: s "A", "b" =: s "B"] "A,B"-    matchTest "{a}{a,b}" ["b" =: s "B"] "B"-    matchTest "{a}{a,b,c}" ["b" =: s "B"] "B"-    matchTest "{a,b}{a,b,c}" ["c" =: s "C"] "C"-    matchTest "{b}{a,b,c}" ["a" =: s "A", "c" =: s "C"] "A,C"-    matchTest "{a}{a,b,c}" ["b" =: s "B", "c" =: s "C"] "B,C"--    matchTest "{a:1}/{a}" ["a" =: s "AB"] "A/AB"--    -- TODO: Test matching on explode modifier.-    -- matchTest "{a*}" ["a" =: s "A"] "A"--    -- TODO: Test matching on lists.-    -- matchTest "{a}" ["a" =: l ["A", "B"]] "A,B"--    -- TODO: Test matching on dictionaries.-    -- matchTest "{a}" ["a" =: d ["k" =: "v"]] "k,v"--  Hspec.describe "uriTemplate"-    . Hspec.it "works as an expression"-    $ Just [Burrito.uriTemplate|a{b}c|]-    `Hspec.shouldBe` Burrito.parse "a{b}c"--  Hspec.modifyMaxSize (const 10)-    . Hspec.it "round trips"-    . QC.property-    $ \(Template template) -> Burrito.parse (show template) == Just template---- brittany-next-binding --columns 160-tests :: [Test]-tests = mconcat-  [ [ Test "" [] ""-    , Test "" ["a" =: s ""] ""-    , Test "" ["a" =: l []] ""-    , Test "" ["a" =: d []] ""-    , Test "!" [] "!"-    , Test "#" [] "#"-    , Test "$" [] "$"-    , Test "&" [] "&"-    , Test "(" [] "("-    , Test ")" [] ")"-    , Test "*" [] "*"-    , Test "+" [] "+"-    , Test "," [] ","-    , Test "-" [] "-"-    , Test "." [] "."-    , Test "/" [] "/"-    , Test "0" [] "0"-    , Test "9" [] "9"-    , Test ":" [] ":"-    , Test ";" [] ";"-    , Test "=" [] "="-    , Test "?" [] "?"-    , Test "@" [] "@"-    , Test "A" [] "A"-    , Test "Z" [] "Z"-    , Test "[" [] "["-    , Test "]" [] "]"-    , Test "_" [] "_"-    , Test "a" [] "a"-    , Test "z" [] "z"-    , Test "~" [] "~"-    , Test "\xa0" [] "%C2%A0"-    , Test "\xd7ff" [] "%ED%9F%BF"-    , Test "\xf900" [] "%EF%A4%80"-    , Test "\xfdcf" [] "%EF%B7%8F"-    , Test "\xfdf0" [] "%EF%B7%B0"-    , Test "\xffef" [] "%EF%BF%AF"-    , Test "\x10000" [] "%F0%90%80%80"-    , Test "\x1fffd" [] "%F0%9F%BF%BD"-    , Test "\x20000" [] "%F0%A0%80%80"-    , Test "\x2fffd" [] "%F0%AF%BF%BD"-    , Test "\x30000" [] "%F0%B0%80%80"-    , Test "\x3fffd" [] "%F0%BF%BF%BD"-    , Test "\x40000" [] "%F1%80%80%80"-    , Test "\x4fffd" [] "%F1%8F%BF%BD"-    , Test "\x50000" [] "%F1%90%80%80"-    , Test "\x5fffd" [] "%F1%9F%BF%BD"-    , Test "\x60000" [] "%F1%A0%80%80"-    , Test "\x6fffd" [] "%F1%AF%BF%BD"-    , Test "\x70000" [] "%F1%B0%80%80"-    , Test "\x7fffd" [] "%F1%BF%BF%BD"-    , Test "\x80000" [] "%F2%80%80%80"-    , Test "\x8fffd" [] "%F2%8F%BF%BD"-    , Test "\x90000" [] "%F2%90%80%80"-    , Test "\x9fffd" [] "%F2%9F%BF%BD"-    , Test "\xa0000" [] "%F2%A0%80%80"-    , Test "\xafffd" [] "%F2%AF%BF%BD"-    , Test "\xb0000" [] "%F2%B0%80%80"-    , Test "\xbfffd" [] "%F2%BF%BF%BD"-    , Test "\xc0000" [] "%F3%80%80%80"-    , Test "\xcfffd" [] "%F3%8F%BF%BD"-    , Test "\xd0000" [] "%F3%90%80%80"-    , Test "\xdfffd" [] "%F3%9F%BF%BD"-    , Test "\xe1000" [] "%F3%A1%80%80"-    , Test "\xefffd" [] "%F3%AF%BF%BD"-    , Test "\xe000" [] "%EE%80%80"-    , Test "\xf8ff" [] "%EF%A3%BF"-    , Test "\xf0000" [] "%F3%B0%80%80"-    , Test "\xffffd" [] "%F3%BF%BF%BD"-    , Test "\x100000" [] "%F4%80%80%80"-    , Test "\x10fffd" [] "%F4%8F%BF%BD"-    , Test "%00" [] "%00"-    , Test "%AA" [] "%AA"-    , Test "%Aa" [] "%Aa"-    , Test "%aA" [] "%aA"-    , Test "%aa" [] "%aa"-    , Test "%" [] noParse-    , Test "%0" [] noParse-    , Test "%0z" [] noParse-    , Test "%z" [] noParse-    , Test "%30" [] "%30"-    , Test " " [] noParse-    , Test "\"" [] noParse-    , Test "'" [] noParse-    , Test "%" [] noParse-    , Test "<" [] noParse-    , Test ">" [] noParse-    , Test "\\" [] noParse-    , Test "^" [] noParse-    , Test "`" [] noParse-    , Test "{" [] noParse-    , Test "|" [] noParse-    , Test "}" [] noParse-    , Test "{}" [] noParse-    , Test "{,}" [] noParse-    , Test "{a,,b}" [] noParse-    , Test "{+}" [] noParse-    , Test "{:1}" [] noParse-    , Test "{*}" [] noParse-    , Test "{AZ}" [] ""-    , Test "{az}" [] ""-    , Test "{09}" [] ""-    , Test "{_a}" [] ""-    , Test "{a_}" [] ""-    , Test "{_}" [] ""-    , Test "{A.A}" [] ""-    , Test "{a.a}" [] ""-    , Test "{0.0}" [] ""-    , Test "{_._}" [] ""-    , Test "{%aa.%aa}" [] ""-    , Test "{.}" [] noParse-    , Test "{a.}" [] noParse-    , Test "{+.a}" [] noParse-    , Test "{a..b}" [] noParse-    , Test "{%00}" [] ""-    , Test "{%}" [] noParse-    , Test "{%0}" [] noParse-    , Test "{%0z}" [] noParse-    , Test "{%z}" [] noParse-    , Test "{!}" [] noParse-    , Test "{" [] noParse-    , Test "{{}" [] noParse-    , Test "}" [] noParse-    , Test "{}}" [] noParse-    , Test "{a,b}" [] ""-    , Test "{a,b,c,d}" [] ""-    , Test "{a,a}" [] ""-    , Test "{a:5}" [] ""-    , Test "{a:67}" [] ""-    , Test "{a:801}" [] ""-    , Test "{a:234}" [] ""-    , Test "{a:9999}" [] ""-    , Test "{a:123}" ["a" =: s (replicate 200 'a')] . Output . Just $ replicate 123 'a'-    , Test "{a:}" [] noParse-    , Test "{a:0}" [] noParse-    , Test "{a:10000}" [] noParse-    , Test "{a:-1}" [] noParse-    , Test "{a*}" [] ""-    , Test "{a:1*}" [] noParse-    , Test "{a*:1}" [] noParse-    , Test "{a,b:1,c*}" [] ""-    , Test "{+a}" [] ""-    , Test "{#a}" [] ""-    , Test "{.a}" [] ""-    , Test "{/a}" [] ""-    , Test "{;a}" [] ""-    , Test "{?a}" [] ""-    , Test "{&a}" [] ""-    , Test "{=a}" [] noParse-    , Test "{,a}" [] noParse-    , Test "{!a}" [] noParse-    , Test "{@a}" [] noParse-    , Test "{|a}" [] noParse-    , Test "{+#a}" [] noParse-    , Test "{+a,#b}" [] noParse-    , Test "{+a:1}" [] ""-    , Test "{#a*}" [] ""-    , Test "{+a,b}" [] ""-    , Test "{#a,b}" [] ""-    , Test "{.a,b}" [] ""-    , Test "{/a,b}" [] ""-    , Test "{;a,b}" [] ""-    , Test "{?a,b}" [] ""-    , Test "{&a,b}" [] ""-    , Test "{a}{b}" [] ""-    , Test "{a}{b}{c}{d}" [] ""-    , Test "{a}{a}" [] ""-    , Test "{{}}" [] noParse-    , Test "{a{b}}" [] noParse-    , Test "{{a}b}" [] noParse-    , Test "{a{b}c}" [] noParse-    , Test "a{b}" [] "a"-    , Test "{a}b" [] "b"-    , Test "a{b}c" [] "ac"-    , Test "{a}b{c}" [] "b"-    , Test "{a}" [] ""-    , Test "{+a}" [] ""-    , Test "{#a}" [] ""-    , Test "{.a}" [] ""-    , Test "{/a}" [] ""-    , Test "{;a}" [] ""-    , Test "{?a}" [] ""-    , Test "{&a}" [] ""-    , Test "http://example.com/~{username}/" ["username" =: s "fred"] "http://example.com/~fred/"-    , Test "http://example.com/~{username}/" ["username" =: s "mark"] "http://example.com/~mark/"-    , Test "http://example.com/dictionary/{term:1}/{term}" ["term" =: s "cat"] "http://example.com/dictionary/c/cat"-    , Test "http://example.com/dictionary/{term:1}/{term}" ["term" =: s "dog"] "http://example.com/dictionary/d/dog"-    , Test "http://example.com/search{?q,lang}" ["q" =: s "cat", "lang" =: s "en"] "http://example.com/search?q=cat&lang=en"-    , Test "http://example.com/search{?q,lang}" ["q" =: s "chien", "lang" =: s "fr"] "http://example.com/search?q=chien&lang=fr"-    , Test "http://www.example.com/foo{?query,number}" ["query" =: s "mycelium", "number" =: s "100"] "http://www.example.com/foo?query=mycelium&number=100"-    , Test "http://www.example.com/foo{?query,number}" ["number" =: s "100"] "http://www.example.com/foo?number=100"-    , Test "http://www.example.com/foo{?query,number}" [] "http://www.example.com/foo"-    , Test "{a}" [] ""-    , Test "{a}" ["a" =: l []] ""-    , Test "{a}" ["a" =: d []] ""-    , Test "{a}" ["a" =: s ""] ""-    , Test "{a}" ["a" =: s "A"] "A"-    , Test "{a}" ["a" =: s "~"] "~"-    , Test "{a}" ["a" =: s "%"] "%25"-    , Test "{a}" ["a" =: s "?"] "%3F"-    , Test "{a}" ["a" =: s "&"] "%26"-    , Test "{a}" ["a" =: s "\xa0"] "%C2%A0"-    , Test "{a}" ["a" =: s "\xd7ff"] "%ED%9F%BF"-    , Test "{a}" ["a" =: s "\x10000"] "%F0%90%80%80"-    , Test "{a}" ["a" =: l ["A"]] "A"-    , Test "{a}" ["a" =: l ["A", "B"]] "A,B"-    , Test "{a}" ["a" =: l ["%"]] "%25"-    , Test "{a}" ["a" =: l ["\xa0"]] "%C2%A0"-    , Test "{a}" ["a" =: d ["A" =: "1"]] "A,1"-    , Test "{a}" ["a" =: d ["A" =: "1", "B" =: "2"]] "A,1,B,2"-    , Test "{a}" ["a" =: d ["A" =: "%"]] "A,%25"-    , Test "{a}" ["a" =: d ["A" =: "\xa0"]] "A,%C2%A0"-    , Test "{a}" ["a" =: d ["%" =: "1"]] "%25,1"-    , Test "{a*}" [] ""-    , Test "{a*}" ["a" =: s ""] ""-    , Test "{a*}" ["a" =: s "A"] "A"-    , Test "{a*}" ["a" =: l []] ""-    , Test "{a*}" ["a" =: l ["A"]] "A"-    , Test "{a*}" ["a" =: l ["A", "B"]] "A,B"-    , Test "{a*}" ["a" =: d []] ""-    , Test "{a*}" ["a" =: d ["A" =: "1"]] "A=1"-    , Test "{a*}" ["a" =: d ["A" =: "1", "B" =: "2"]] "A=1,B=2"-    , Test "{a:1}" [] ""-    , Test "{a:1}" ["a" =: s ""] ""-    , Test "{a:1}" ["a" =: s "A"] "A"-    , Test "{a:1}" ["a" =: s "AB"] "A"-    , Test "{a:1}" ["a" =: s "%B"] "%25"-    , Test "{a:1}" ["a" =: s "\xa0\&B"] "%C2%A0"-    , Test "{a:1}" ["a" =: s "\xd7ff\&B"] "%ED%9F%BF"-    , Test "{a:1}" ["a" =: s "\x10000\&B"] "%F0%90%80%80"-    , Test "{a:1}" ["a" =: l []] ""-    , Test "{a:1}" ["a" =: l ["AB"]] "AB"-    , Test "{a:1}" ["a" =: l ["AB", "CD"]] "AB,CD"-    , Test "{a:1}" ["a" =: d []] ""-    , Test "{a:1}" ["a" =: d ["AB" =: "12"]] "AB,12"-    , Test "{a:1}" ["a" =: d ["AB" =: "12", "CD" =: "34"]] "AB,12,CD,34"-    , Test "{a,a}" [] ""-    , Test "{a,a}" ["a" =: l []] ""-    , Test "{a,a}" ["a" =: d []] ""-    , Test "{a,a}" ["a" =: s ""] ","-    , Test "{a,b}" ["a" =: s ""] ""-    , Test "{a,b}" ["b" =: s ""] ""-    , Test "{%aa}" ["%aa" =: s "A"] "A"-    , Test "{%aa}" ["%aa" =: l ["A", "B"]] "A,B"-    , Test "{%aa}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] "A,1,B,2"-    , Test "{%aa*}" ["%aa" =: s "A"] "A"-    , Test "{%aa*}" ["%aa" =: l ["A", "B"]] "A,B"-    , Test "{%aa*}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] "A=1,B=2"-    , Test "{+a}" [] ""-    , Test "{+a}" ["a" =: l []] ""-    , Test "{+a}" ["a" =: d []] ""-    , Test "{+a}" ["a" =: s ""] ""-    , Test "{+a}" ["a" =: s "A"] "A"-    , Test "{+a}" ["a" =: s "~"] "~"-    , Test "{+a}" ["a" =: s "%"] "%25"-    , Test "{+a}" ["a" =: s "?"] "?"-    , Test "{+a}" ["a" =: s "&"] "&"-    , Test "{+a}" ["a" =: s "\xa0"] "%C2%A0"-    , Test "{+a}" ["a" =: s "\xd7ff"] "%ED%9F%BF"-    , Test "{+a}" ["a" =: s "\x10000"] "%F0%90%80%80"-    , Test "{+a}" ["a" =: l ["A"]] "A"-    , Test "{+a}" ["a" =: l ["A", "B"]] "A,B"-    , Test "{+a}" ["a" =: l ["%"]] "%25"-    , Test "{+a}" ["a" =: l ["\xa0"]] "%C2%A0"-    , Test "{+a}" ["a" =: d ["A" =: "1"]] "A,1"-    , Test "{+a}" ["a" =: d ["A" =: "1", "B" =: "2"]] "A,1,B,2"-    , Test "{+a}" ["a" =: d ["A" =: "%"]] "A,%25"-    , Test "{+a}" ["a" =: d ["A" =: "\xa0"]] "A,%C2%A0"-    , Test "{+a}" ["a" =: d ["%" =: "1"]] "%25,1"-    , Test "{+a*}" [] ""-    , Test "{+a*}" ["a" =: s ""] ""-    , Test "{+a*}" ["a" =: s "A"] "A"-    , Test "{+a*}" ["a" =: l []] ""-    , Test "{+a*}" ["a" =: l ["A"]] "A"-    , Test "{+a*}" ["a" =: l ["A", "B"]] "A,B"-    , Test "{+a*}" ["a" =: d []] ""-    , Test "{+a*}" ["a" =: d ["A" =: "1"]] "A=1"-    , Test "{+a*}" ["a" =: d ["A" =: "1", "B" =: "2"]] "A=1,B=2"-    , Test "{+a:1}" [] ""-    , Test "{+a:1}" ["a" =: s ""] ""-    , Test "{+a:1}" ["a" =: s "A"] "A"-    , Test "{+a:1}" ["a" =: s "AB"] "A"-    , Test "{+a:1}" ["a" =: s "%B"] "%25"-    , Test "{+a:1}" ["a" =: s "\xa0\&B"] "%C2%A0"-    , Test "{+a:1}" ["a" =: s "\xd7ff\&B"] "%ED%9F%BF"-    , Test "{+a:1}" ["a" =: s "\x10000\&B"] "%F0%90%80%80"-    , Test "{+a:1}" ["a" =: l []] ""-    , Test "{+a:1}" ["a" =: l ["AB"]] "AB"-    , Test "{+a:1}" ["a" =: l ["AB", "CD"]] "AB,CD"-    , Test "{+a:1}" ["a" =: d []] ""-    , Test "{+a:1}" ["a" =: d ["AB" =: "12"]] "AB,12"-    , Test "{+a:1}" ["a" =: d ["AB" =: "12", "CD" =: "34"]] "AB,12,CD,34"-    , Test "{+a,a}" [] ""-    , Test "{+a,a}" ["a" =: l []] ""-    , Test "{+a,a}" ["a" =: d []] ""-    , Test "{+a,a}" ["a" =: s ""] ","-    , Test "{+a,b}" ["a" =: s ""] ""-    , Test "{+a,b}" ["b" =: s ""] ""-    , Test "{+%aa}" ["%aa" =: s "A"] "A"-    , Test "{+%aa}" ["%aa" =: l ["A", "B"]] "A,B"-    , Test "{+%aa}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] "A,1,B,2"-    , Test "{+%aa*}" ["%aa" =: s "A"] "A"-    , Test "{+%aa*}" ["%aa" =: l ["A", "B"]] "A,B"-    , Test "{+%aa*}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] "A=1,B=2"-    , Test "{#a}" [] ""-    , Test "{#a}" ["a" =: l []] ""-    , Test "{#a}" ["a" =: d []] ""-    , Test "{#a}" ["a" =: s ""] "#"-    , Test "{#a}" ["a" =: s "A"] "#A"-    , Test "{#a}" ["a" =: s "~"] "#~"-    , Test "{#a}" ["a" =: s "%"] "#%25"-    , Test "{#a}" ["a" =: s "?"] "#?"-    , Test "{#a}" ["a" =: s "&"] "#&"-    , Test "{#a}" ["a" =: s "\xa0"] "#%C2%A0"-    , Test "{#a}" ["a" =: s "\xd7ff"] "#%ED%9F%BF"-    , Test "{#a}" ["a" =: s "\x10000"] "#%F0%90%80%80"-    , Test "{#a}" ["a" =: l ["A"]] "#A"-    , Test "{#a}" ["a" =: l ["A", "B"]] "#A,B"-    , Test "{#a}" ["a" =: l ["%"]] "#%25"-    , Test "{#a}" ["a" =: l ["\xa0"]] "#%C2%A0"-    , Test "{#a}" ["a" =: d ["A" =: "1"]] "#A,1"-    , Test "{#a}" ["a" =: d ["A" =: "1", "B" =: "2"]] "#A,1,B,2"-    , Test "{#a}" ["a" =: d ["A" =: "%"]] "#A,%25"-    , Test "{#a}" ["a" =: d ["A" =: "\xa0"]] "#A,%C2%A0"-    , Test "{#a}" ["a" =: d ["%" =: "1"]] "#%25,1"-    , Test "{#a*}" [] ""-    , Test "{#a*}" ["a" =: s ""] "#"-    , Test "{#a*}" ["a" =: s "A"] "#A"-    , Test "{#a*}" ["a" =: l []] ""-    , Test "{#a*}" ["a" =: l ["A"]] "#A"-    , Test "{#a*}" ["a" =: l ["A", "B"]] "#A,B"-    , Test "{#a*}" ["a" =: d []] ""-    , Test "{#a*}" ["a" =: d ["A" =: "1"]] "#A=1"-    , Test "{#a*}" ["a" =: d ["A" =: "1", "B" =: "2"]] "#A=1,B=2"-    , Test "{#a:1}" [] ""-    , Test "{#a:1}" ["a" =: s ""] "#"-    , Test "{#a:1}" ["a" =: s "A"] "#A"-    , Test "{#a:1}" ["a" =: s "AB"] "#A"-    , Test "{#a:1}" ["a" =: s "%B"] "#%25"-    , Test "{#a:1}" ["a" =: s "\xa0\&B"] "#%C2%A0"-    , Test "{#a:1}" ["a" =: s "\xd7ff\&B"] "#%ED%9F%BF"-    , Test "{#a:1}" ["a" =: s "\x10000\&B"] "#%F0%90%80%80"-    , Test "{#a:1}" ["a" =: l []] ""-    , Test "{#a:1}" ["a" =: l ["AB"]] "#AB"-    , Test "{#a:1}" ["a" =: l ["AB", "CD"]] "#AB,CD"-    , Test "{#a:1}" ["a" =: d []] ""-    , Test "{#a:1}" ["a" =: d ["AB" =: "12"]] "#AB,12"-    , Test "{#a:1}" ["a" =: d ["AB" =: "12", "CD" =: "34"]] "#AB,12,CD,34"-    , Test "{#a,a}" [] ""-    , Test "{#a,a}" ["a" =: l []] ""-    , Test "{#a,a}" ["a" =: d []] ""-    , Test "{#a,a}" ["a" =: s ""] "#,"-    , Test "{#a,b}" ["a" =: s ""] "#"-    , Test "{#a,b}" ["b" =: s ""] "#"-    , Test "{#%aa}" ["%aa" =: s "A"] "#A"-    , Test "{#%aa}" ["%aa" =: l ["A", "B"]] "#A,B"-    , Test "{#%aa}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] "#A,1,B,2"-    , Test "{#%aa*}" ["%aa" =: s "A"] "#A"-    , Test "{#%aa*}" ["%aa" =: l ["A", "B"]] "#A,B"-    , Test "{#%aa*}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] "#A=1,B=2"-    , Test "{.a}" [] ""-    , Test "{.a}" ["a" =: l []] ""-    , Test "{.a}" ["a" =: d []] ""-    , Test "{.a}" ["a" =: s ""] "."-    , Test "{.a}" ["a" =: s "A"] ".A"-    , Test "{.a}" ["a" =: s "~"] ".~"-    , Test "{.a}" ["a" =: s "%"] ".%25"-    , Test "{.a}" ["a" =: s "?"] ".%3F"-    , Test "{.a}" ["a" =: s "&"] ".%26"-    , Test "{.a}" ["a" =: s "\xa0"] ".%C2%A0"-    , Test "{.a}" ["a" =: s "\xd7ff"] ".%ED%9F%BF"-    , Test "{.a}" ["a" =: s "\x10000"] ".%F0%90%80%80"-    , Test "{.a}" ["a" =: l ["A"]] ".A"-    , Test "{.a}" ["a" =: l ["A", "B"]] ".A,B"-    , Test "{.a}" ["a" =: l ["%"]] ".%25"-    , Test "{.a}" ["a" =: l ["\xa0"]] ".%C2%A0"-    , Test "{.a}" ["a" =: d ["A" =: "1"]] ".A,1"-    , Test "{.a}" ["a" =: d ["A" =: "1", "B" =: "2"]] ".A,1,B,2"-    , Test "{.a}" ["a" =: d ["A" =: "%"]] ".A,%25"-    , Test "{.a}" ["a" =: d ["A" =: "\xa0"]] ".A,%C2%A0"-    , Test "{.a}" ["a" =: d ["%" =: "1"]] ".%25,1"-    , Test "{.a*}" [] ""-    , Test "{.a*}" ["a" =: s ""] "."-    , Test "{.a*}" ["a" =: s "A"] ".A"-    , Test "{.a*}" ["a" =: l []] ""-    , Test "{.a*}" ["a" =: l ["A"]] ".A"-    , Test "{.a*}" ["a" =: l ["A", "B"]] ".A.B"-    , Test "{.a*}" ["a" =: d []] ""-    , Test "{.a*}" ["a" =: d ["A" =: "1"]] ".A=1"-    , Test "{.a*}" ["a" =: d ["A" =: "1", "B" =: "2"]] ".A=1.B=2"-    , Test "{.a:1}" [] ""-    , Test "{.a:1}" ["a" =: s ""] "."-    , Test "{.a:1}" ["a" =: s "A"] ".A"-    , Test "{.a:1}" ["a" =: s "AB"] ".A"-    , Test "{.a:1}" ["a" =: s "%B"] ".%25"-    , Test "{.a:1}" ["a" =: s "\xa0\&B"] ".%C2%A0"-    , Test "{.a:1}" ["a" =: s "\xd7ff\&B"] ".%ED%9F%BF"-    , Test "{.a:1}" ["a" =: s "\x10000\&B"] ".%F0%90%80%80"-    , Test "{.a:1}" ["a" =: l []] ""-    , Test "{.a:1}" ["a" =: l ["AB"]] ".AB"-    , Test "{.a:1}" ["a" =: l ["AB", "CD"]] ".AB,CD"-    , Test "{.a:1}" ["a" =: d []] ""-    , Test "{.a:1}" ["a" =: d ["AB" =: "12"]] ".AB,12"-    , Test "{.a:1}" ["a" =: d ["AB" =: "12", "CD" =: "34"]] ".AB,12,CD,34"-    , Test "{.a,a}" [] ""-    , Test "{.a,a}" ["a" =: l []] ""-    , Test "{.a,a}" ["a" =: d []] ""-    , Test "{.a,a}" ["a" =: s ""] ".."-    , Test "{.a,b}" ["a" =: s ""] "."-    , Test "{.a,b}" ["b" =: s ""] "."-    , Test "{.%aa}" ["%aa" =: s "A"] ".A"-    , Test "{.%aa}" ["%aa" =: l ["A", "B"]] ".A,B"-    , Test "{.%aa}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] ".A,1,B,2"-    , Test "{.%aa*}" ["%aa" =: s "A"] ".A"-    , Test "{.%aa*}" ["%aa" =: l ["A", "B"]] ".A.B"-    , Test "{.%aa*}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] ".A=1.B=2"-    , Test "{/a}" [] ""-    , Test "{/a}" ["a" =: l []] ""-    , Test "{/a}" ["a" =: d []] ""-    , Test "{/a}" ["a" =: s ""] "/"-    , Test "{/a}" ["a" =: s "A"] "/A"-    , Test "{/a}" ["a" =: s "~"] "/~"-    , Test "{/a}" ["a" =: s "%"] "/%25"-    , Test "{/a}" ["a" =: s "?"] "/%3F"-    , Test "{/a}" ["a" =: s "&"] "/%26"-    , Test "{/a}" ["a" =: s "\xa0"] "/%C2%A0"-    , Test "{/a}" ["a" =: s "\xd7ff"] "/%ED%9F%BF"-    , Test "{/a}" ["a" =: s "\x10000"] "/%F0%90%80%80"-    , Test "{/a}" ["a" =: l ["A"]] "/A"-    , Test "{/a}" ["a" =: l ["A", "B"]] "/A,B"-    , Test "{/a}" ["a" =: l ["%"]] "/%25"-    , Test "{/a}" ["a" =: l ["\xa0"]] "/%C2%A0"-    , Test "{/a}" ["a" =: d ["A" =: "1"]] "/A,1"-    , Test "{/a}" ["a" =: d ["A" =: "1", "B" =: "2"]] "/A,1,B,2"-    , Test "{/a}" ["a" =: d ["A" =: "%"]] "/A,%25"-    , Test "{/a}" ["a" =: d ["A" =: "\xa0"]] "/A,%C2%A0"-    , Test "{/a}" ["a" =: d ["%" =: "1"]] "/%25,1"-    , Test "{/a*}" [] ""-    , Test "{/a*}" ["a" =: s ""] "/"-    , Test "{/a*}" ["a" =: s "A"] "/A"-    , Test "{/a*}" ["a" =: l []] ""-    , Test "{/a*}" ["a" =: l ["A"]] "/A"-    , Test "{/a*}" ["a" =: l ["A", "B"]] "/A/B"-    , Test "{/a*}" ["a" =: d []] ""-    , Test "{/a*}" ["a" =: d ["A" =: "1"]] "/A=1"-    , Test "{/a*}" ["a" =: d ["A" =: "1", "B" =: "2"]] "/A=1/B=2"-    , Test "{/a:1}" [] ""-    , Test "{/a:1}" ["a" =: s ""] "/"-    , Test "{/a:1}" ["a" =: s "A"] "/A"-    , Test "{/a:1}" ["a" =: s "AB"] "/A"-    , Test "{/a:1}" ["a" =: s "%B"] "/%25"-    , Test "{/a:1}" ["a" =: s "\xa0\&B"] "/%C2%A0"-    , Test "{/a:1}" ["a" =: s "\xd7ff\&B"] "/%ED%9F%BF"-    , Test "{/a:1}" ["a" =: s "\x10000\&B"] "/%F0%90%80%80"-    , Test "{/a:1}" ["a" =: l []] ""-    , Test "{/a:1}" ["a" =: l ["AB"]] "/AB"-    , Test "{/a:1}" ["a" =: l ["AB", "CD"]] "/AB,CD"-    , Test "{/a:1}" ["a" =: d []] ""-    , Test "{/a:1}" ["a" =: d ["AB" =: "12"]] "/AB,12"-    , Test "{/a:1}" ["a" =: d ["AB" =: "12", "CD" =: "34"]] "/AB,12,CD,34"-    , Test "{/a,a}" [] ""-    , Test "{/a,a}" ["a" =: l []] ""-    , Test "{/a,a}" ["a" =: d []] ""-    , Test "{/a,a}" ["a" =: s ""] "//"-    , Test "{/a,b}" ["a" =: s ""] "/"-    , Test "{/a,b}" ["b" =: s ""] "/"-    , Test "{/%aa}" ["%aa" =: s "A"] "/A"-    , Test "{/%aa}" ["%aa" =: l ["A", "B"]] "/A,B"-    , Test "{/%aa}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] "/A,1,B,2"-    , Test "{/%aa*}" ["%aa" =: s "A"] "/A"-    , Test "{/%aa*}" ["%aa" =: l ["A", "B"]] "/A/B"-    , Test "{/%aa*}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] "/A=1/B=2"-    , Test "{;a}" [] ""-    , Test "{;a}" ["a" =: l []] ""-    , Test "{;a}" ["a" =: d []] ""-    , Test "{;a}" ["a" =: s ""] ";a"-    , Test "{;a}" ["a" =: s "A"] ";a=A"-    , Test "{;a}" ["a" =: s "~"] ";a=~"-    , Test "{;a}" ["a" =: s "%"] ";a=%25"-    , Test "{;a}" ["a" =: s "?"] ";a=%3F"-    , Test "{;a}" ["a" =: s "&"] ";a=%26"-    , Test "{;a}" ["a" =: s "\xa0"] ";a=%C2%A0"-    , Test "{;a}" ["a" =: s "\xd7ff"] ";a=%ED%9F%BF"-    , Test "{;a}" ["a" =: s "\x10000"] ";a=%F0%90%80%80"-    , Test "{;a}" ["a" =: l ["A"]] ";a=A"-    , Test "{;a}" ["a" =: l ["A", "B"]] ";a=A,B"-    , Test "{;a}" ["a" =: l ["%"]] ";a=%25"-    , Test "{;a}" ["a" =: l ["\xa0"]] ";a=%C2%A0"-    , Test "{;a}" ["a" =: d ["A" =: "1"]] ";a=A,1"-    , Test "{;a}" ["a" =: d ["A" =: "1", "B" =: "2"]] ";a=A,1,B,2"-    , Test "{;a}" ["a" =: d ["A" =: "%"]] ";a=A,%25"-    , Test "{;a}" ["a" =: d ["A" =: "\xa0"]] ";a=A,%C2%A0"-    , Test "{;a}" ["a" =: d ["%" =: "1"]] ";a=%25,1"-    , Test "{;a*}" [] ""-    , Test "{;a*}" ["a" =: s ""] ";a"-    , Test "{;a*}" ["a" =: s "A"] ";a=A"-    , Test "{;a*}" ["a" =: l []] ""-    , Test "{;a*}" ["a" =: l ["A"]] ";a=A"-    , Test "{;a*}" ["a" =: l ["A", "B"]] ";a=A;a=B"-    , Test "{;a*}" ["a" =: d []] ""-    , Test "{;a*}" ["a" =: d ["A" =: "1"]] ";A=1"-    , Test "{;a*}" ["a" =: d ["A" =: "1", "B" =: "2"]] ";A=1;B=2"-    , Test "{;a:1}" [] ""-    , Test "{;a:1}" ["a" =: s ""] ";a"-    , Test "{;a:1}" ["a" =: s "A"] ";a=A"-    , Test "{;a:1}" ["a" =: s "AB"] ";a=A"-    , Test "{;a:1}" ["a" =: s "%B"] ";a=%25"-    , Test "{;a:1}" ["a" =: s "\xa0\&B"] ";a=%C2%A0"-    , Test "{;a:1}" ["a" =: s "\xd7ff\&B"] ";a=%ED%9F%BF"-    , Test "{;a:1}" ["a" =: s "\x10000\&B"] ";a=%F0%90%80%80"-    , Test "{;a:1}" ["a" =: l []] ""-    , Test "{;a:1}" ["a" =: l ["AB"]] ";a=AB"-    , Test "{;a:1}" ["a" =: l ["AB", "CD"]] ";a=AB,CD"-    , Test "{;a:1}" ["a" =: d []] ""-    , Test "{;a:1}" ["a" =: d ["AB" =: "12"]] ";a=AB,12"-    , Test "{;a:1}" ["a" =: d ["AB" =: "12", "CD" =: "34"]] ";a=AB,12,CD,34"-    , Test "{;a,a}" [] ""-    , Test "{;a,a}" ["a" =: l []] ""-    , Test "{;a,a}" ["a" =: d []] ""-    , Test "{;a,a}" ["a" =: s ""] ";a;a"-    , Test "{;a,b}" ["a" =: s ""] ";a"-    , Test "{;a,b}" ["b" =: s ""] ";b"-    , Test "{;%aa}" ["%aa" =: s "A"] ";%aa=A"-    , Test "{;%aa}" ["%aa" =: l ["A", "B"]] ";%aa=A,B"-    , Test "{;%aa}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] ";%aa=A,1,B,2"-    , Test "{;%aa*}" ["%aa" =: s "A"] ";%aa=A"-    , Test "{;%aa*}" ["%aa" =: l ["A", "B"]] ";%aa=A;%aa=B"-    , Test "{;%aa*}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] ";A=1;B=2"-    , Test "{?a}" [] ""-    , Test "{?a}" ["a" =: l []] ""-    , Test "{?a}" ["a" =: d []] ""-    , Test "{?a}" ["a" =: s ""] "?a="-    , Test "{?a}" ["a" =: s "A"] "?a=A"-    , Test "{?a}" ["a" =: s "~"] "?a=~"-    , Test "{?a}" ["a" =: s "%"] "?a=%25"-    , Test "{?a}" ["a" =: s "?"] "?a=%3F"-    , Test "{?a}" ["a" =: s "&"] "?a=%26"-    , Test "{?a}" ["a" =: s "\xa0"] "?a=%C2%A0"-    , Test "{?a}" ["a" =: s "\xd7ff"] "?a=%ED%9F%BF"-    , Test "{?a}" ["a" =: s "\x10000"] "?a=%F0%90%80%80"-    , Test "{?a}" ["a" =: l ["A"]] "?a=A"-    , Test "{?a}" ["a" =: l ["A", "B"]] "?a=A,B"-    , Test "{?a}" ["a" =: l ["%"]] "?a=%25"-    , Test "{?a}" ["a" =: l ["\xa0"]] "?a=%C2%A0"-    , Test "{?a}" ["a" =: d ["A" =: "1"]] "?a=A,1"-    , Test "{?a}" ["a" =: d ["A" =: "1", "B" =: "2"]] "?a=A,1,B,2"-    , Test "{?a}" ["a" =: d ["A" =: "%"]] "?a=A,%25"-    , Test "{?a}" ["a" =: d ["A" =: "\xa0"]] "?a=A,%C2%A0"-    , Test "{?a}" ["a" =: d ["%" =: "1"]] "?a=%25,1"-    , Test "{?a*}" [] ""-    , Test "{?a*}" ["a" =: s ""] "?a="-    , Test "{?a*}" ["a" =: s "A"] "?a=A"-    , Test "{?a*}" ["a" =: l []] ""-    , Test "{?a*}" ["a" =: l ["A"]] "?a=A"-    , Test "{?a*}" ["a" =: l ["A", "B"]] "?a=A&a=B"-    , Test "{?a*}" ["a" =: d []] ""-    , Test "{?a*}" ["a" =: d ["A" =: "1"]] "?A=1"-    , Test "{?a*}" ["a" =: d ["A" =: "1", "B" =: "2"]] "?A=1&B=2"-    , Test "{?a:1}" [] ""-    , Test "{?a:1}" ["a" =: s ""] "?a="-    , Test "{?a:1}" ["a" =: s "A"] "?a=A"-    , Test "{?a:1}" ["a" =: s "AB"] "?a=A"-    , Test "{?a:1}" ["a" =: s "%B"] "?a=%25"-    , Test "{?a:1}" ["a" =: s "\xa0\&B"] "?a=%C2%A0"-    , Test "{?a:1}" ["a" =: s "\xd7ff\&B"] "?a=%ED%9F%BF"-    , Test "{?a:1}" ["a" =: s "\x10000\&B"] "?a=%F0%90%80%80"-    , Test "{?a:1}" ["a" =: l []] ""-    , Test "{?a:1}" ["a" =: l ["AB"]] "?a=AB"-    , Test "{?a:1}" ["a" =: l ["AB", "CD"]] "?a=AB,CD"-    , Test "{?a:1}" ["a" =: d []] ""-    , Test "{?a:1}" ["a" =: d ["AB" =: "12"]] "?a=AB,12"-    , Test "{?a:1}" ["a" =: d ["AB" =: "12", "CD" =: "34"]] "?a=AB,12,CD,34"-    , Test "{?a,a}" [] ""-    , Test "{?a,a}" ["a" =: l []] ""-    , Test "{?a,a}" ["a" =: d []] ""-    , Test "{?a,a}" ["a" =: s ""] "?a=&a="-    , Test "{?a,b}" ["a" =: s ""] "?a="-    , Test "{?a,b}" ["b" =: s ""] "?b="-    , Test "{?%aa}" ["%aa" =: s "A"] "?%aa=A"-    , Test "{?%aa}" ["%aa" =: l ["A", "B"]] "?%aa=A,B"-    , Test "{?%aa}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] "?%aa=A,1,B,2"-    , Test "{?%aa*}" ["%aa" =: s "A"] "?%aa=A"-    , Test "{?%aa*}" ["%aa" =: l ["A", "B"]] "?%aa=A&%aa=B"-    , Test "{?%aa*}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] "?A=1&B=2"-    , Test "{&a}" [] ""-    , Test "{&a}" ["a" =: l []] ""-    , Test "{&a}" ["a" =: d []] ""-    , Test "{&a}" ["a" =: s ""] "&a="-    , Test "{&a}" ["a" =: s "A"] "&a=A"-    , Test "{&a}" ["a" =: s "~"] "&a=~"-    , Test "{&a}" ["a" =: s "%"] "&a=%25"-    , Test "{&a}" ["a" =: s "?"] "&a=%3F"-    , Test "{&a}" ["a" =: s "&"] "&a=%26"-    , Test "{&a}" ["a" =: s "\xa0"] "&a=%C2%A0"-    , Test "{&a}" ["a" =: s "\xd7ff"] "&a=%ED%9F%BF"-    , Test "{&a}" ["a" =: s "\x10000"] "&a=%F0%90%80%80"-    , Test "{&a}" ["a" =: l ["A"]] "&a=A"-    , Test "{&a}" ["a" =: l ["A", "B"]] "&a=A,B"-    , Test "{&a}" ["a" =: l ["%"]] "&a=%25"-    , Test "{&a}" ["a" =: l ["\xa0"]] "&a=%C2%A0"-    , Test "{&a}" ["a" =: d ["A" =: "1"]] "&a=A,1"-    , Test "{&a}" ["a" =: d ["A" =: "1", "B" =: "2"]] "&a=A,1,B,2"-    , Test "{&a}" ["a" =: d ["A" =: "%"]] "&a=A,%25"-    , Test "{&a}" ["a" =: d ["A" =: "\xa0"]] "&a=A,%C2%A0"-    , Test "{&a}" ["a" =: d ["%" =: "1"]] "&a=%25,1"-    , Test "{&a*}" [] ""-    , Test "{&a*}" ["a" =: s ""] "&a="-    , Test "{&a*}" ["a" =: s "A"] "&a=A"-    , Test "{&a*}" ["a" =: l []] ""-    , Test "{&a*}" ["a" =: l ["A"]] "&a=A"-    , Test "{&a*}" ["a" =: l ["A", "B"]] "&a=A&a=B"-    , Test "{&a*}" ["a" =: d []] ""-    , Test "{&a*}" ["a" =: d ["A" =: "1"]] "&A=1"-    , Test "{&a*}" ["a" =: d ["A" =: "1", "B" =: "2"]] "&A=1&B=2"-    , Test "{&a:1}" [] ""-    , Test "{&a:1}" ["a" =: s ""] "&a="-    , Test "{&a:1}" ["a" =: s "A"] "&a=A"-    , Test "{&a:1}" ["a" =: s "AB"] "&a=A"-    , Test "{&a:1}" ["a" =: s "%B"] "&a=%25"-    , Test "{&a:1}" ["a" =: s "\xa0\&B"] "&a=%C2%A0"-    , Test "{&a:1}" ["a" =: s "\xd7ff\&B"] "&a=%ED%9F%BF"-    , Test "{&a:1}" ["a" =: s "\x10000\&B"] "&a=%F0%90%80%80"-    , Test "{&a:1}" ["a" =: l []] ""-    , Test "{&a:1}" ["a" =: l ["AB"]] "&a=AB"-    , Test "{&a:1}" ["a" =: l ["AB", "CD"]] "&a=AB,CD"-    , Test "{&a:1}" ["a" =: d []] ""-    , Test "{&a:1}" ["a" =: d ["AB" =: "12"]] "&a=AB,12"-    , Test "{&a:1}" ["a" =: d ["AB" =: "12", "CD" =: "34"]] "&a=AB,12,CD,34"-    , Test "{&a,a}" [] ""-    , Test "{&a,a}" ["a" =: l []] ""-    , Test "{&a,a}" ["a" =: d []] ""-    , Test "{&a,a}" ["a" =: s ""] "&a=&a="-    , Test "{&a,b}" ["a" =: s ""] "&a="-    , Test "{&a,b}" ["b" =: s ""] "&b="-    , Test "{&%aa}" ["%aa" =: s "A"] "&%aa=A"-    , Test "{&%aa}" ["%aa" =: l ["A", "B"]] "&%aa=A,B"-    , Test "{&%aa}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] "&%aa=A,1,B,2"-    , Test "{&%aa*}" ["%aa" =: s "A"] "&%aa=A"-    , Test "{&%aa*}" ["%aa" =: l ["A", "B"]] "&%aa=A&%aa=B"-    , Test "{&%aa*}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] "&A=1&B=2"-    ]-  , let values = ["%AA" =: s "1", "%Aa" =: s "2", "%aA" =: s "3", "%aa" =: s "4"]-    in-      [ Test "{%AA}" values "1"-      , Test "{%Aa}" values "2"-      , Test "{%aA}" values "3"-      , Test "{%aa}" values "4"-          -- This comment forces Brittany to use a multi-line layout.-      ]-  , let values = ["a" =: s "abcdefghijklmnopqrstuvwxyz"]-    in-      [ Test "{a:1}" values "a"-      , Test "{a:5}" values "abcde"-      , Test "{a:10}" values "abcdefghij"-      , Test "{a:15}" values "abcdefghijklmno"-      , Test "{a:20}" values "abcdefghijklmnopqrst"-      , Test "{a:25}" values "abcdefghijklmnopqrstuvwxy"-      , Test "{a:26}" values "abcdefghijklmnopqrstuvwxyz"-      , Test "{a:30}" values "abcdefghijklmnopqrstuvwxyz"-      ]-  , let values = ["a" =: l []]-    in-      [ Test "{a}" values ""-      , Test "{+a}" values ""-      , Test "{#a}" values ""-      , Test "{.a}" values ""-      , Test "{/a}" values ""-      , Test "{;a}" values ""-      , Test "{?a}" values ""-      , Test "{&a}" values ""-      ]-  , let values = ["a" =: d []]-    in-      [ Test "{a}" values ""-      , Test "{+a}" values ""-      , Test "{#a}" values ""-      , Test "{.a}" values ""-      , Test "{/a}" values ""-      , Test "{;a}" values ""-      , Test "{?a}" values ""-      , Test "{&a}" values ""-      ]-  , let values = ["a" =: s ""]-    in-      [ Test "{a}" values ""-      , Test "{+a}" values ""-      , Test "{#a}" values "#"-      , Test "{.a}" values "."-      , Test "{/a}" values "/"-      , Test "{;a}" values ";a"-      , Test "{?a}" values "?a="-      , Test "{&a}" values "&a="-      ]-  , let values = ["a" =: s "A"]-    in-      [ Test "{a}" values "A"-      , Test "{+a}" values "A"-      , Test "{#a}" values "#A"-      , Test "{.a}" values ".A"-      , Test "{/a}" values "/A"-      , Test "{;a}" values ";a=A"-      , Test "{?a}" values "?a=A"-      , Test "{&a}" values "&a=A"-      ]-  , let values = ["b" =: s "B"]-    in-      [ Test "{a,b}" values "B"-      , Test "{+a,b}" values "B"-      , Test "{#a,b}" values "#B"-      , Test "{.a,b}" values ".B"-      , Test "{/a,b}" values "/B"-      , Test "{;a,b}" values ";b=B"-      , Test "{?a,b}" values "?b=B"-      , Test "{&a,b}" values "&b=B"-      ]-  , let values = ["a" =: s ""]-    in-      [ Test "{a,a}" values ","-      , Test "{+a,a}" values ","-      , Test "{#a,a}" values "#,"-      , Test "{.a,a}" values ".."-      , Test "{/a,a}" values "//"-      , Test "{;a,a}" values ";a;a"-      , Test "{?a,a}" values "?a=&a="-      , Test "{&a,a}" values "&a=&a="-      ]-  , let values = ["a" =: s "A", "b" =: s "B"]-    in-      [ Test "{a,b}" values "A,B"-      , Test "{+a,b}" values "A,B"-      , Test "{#a,b}" values "#A,B"-      , Test "{.a,b}" values ".A.B"-      , Test "{/a,b}" values "/A/B"-      , Test "{;a,b}" values ";a=A;b=B"-      , Test "{?a,b}" values "?a=A&b=B"-      , Test "{&a,b}" values "&a=A&b=B"-      ]-  , let values = ["a" =: d ["K! \xa0\xd7ff\x10000" =: "V! \xa0\xd7ff\x10000"]]-    in-      [ Test "{a*}" values "K%21%20%C2%A0%ED%9F%BF%F0%90%80%80=V%21%20%C2%A0%ED%9F%BF%F0%90%80%80"-      , Test "{+a*}" values "K!%20%C2%A0%ED%9F%BF%F0%90%80%80=V!%20%C2%A0%ED%9F%BF%F0%90%80%80"-      , Test "{#a*}" values "#K!%20%C2%A0%ED%9F%BF%F0%90%80%80=V!%20%C2%A0%ED%9F%BF%F0%90%80%80"-      , Test "{.a*}" values ".K%21%20%C2%A0%ED%9F%BF%F0%90%80%80=V%21%20%C2%A0%ED%9F%BF%F0%90%80%80"-      , Test "{/a*}" values "/K%21%20%C2%A0%ED%9F%BF%F0%90%80%80=V%21%20%C2%A0%ED%9F%BF%F0%90%80%80"-      , Test "{;a*}" values ";K%21%20%C2%A0%ED%9F%BF%F0%90%80%80=V%21%20%C2%A0%ED%9F%BF%F0%90%80%80"-      , Test "{?a*}" values "?K%21%20%C2%A0%ED%9F%BF%F0%90%80%80=V%21%20%C2%A0%ED%9F%BF%F0%90%80%80"-      , Test "{&a*}" values "&K%21%20%C2%A0%ED%9F%BF%F0%90%80%80=V%21%20%C2%A0%ED%9F%BF%F0%90%80%80"-      ]-  , let-      values =-        [ "empty" =: s ""-        , "hello" =: s "Hello World!"-        , "keys" =: d ["semi" =: ";", "dot" =: ".", "comma" =: ","]-        , "list" =: l ["red", "green", "blue"]-        , "path" =: s "/foo/bar"-        , "var" =: s "value"-        , "x" =: s "1024"-        , "y" =: s "768"-        ]-    in-      [ Test "{var}" values "value"-      , Test "{hello}" values "Hello%20World%21"-      , Test "{+var}" values "value"-      , Test "{+hello}" values "Hello%20World!"-      , Test "{+path}/here" values "/foo/bar/here"-      , Test "here?ref={+path}" values "here?ref=/foo/bar"-      , Test "X{#var}" values "X#value"-      , Test "X{#hello}" values "X#Hello%20World!"-      , Test "map?{x,y}" values "map?1024,768"-      , Test "{x,hello,y}" values "1024,Hello%20World%21,768"-      , Test "{+x,hello,y}" values "1024,Hello%20World!,768"-      , Test "{+path,x}/here" values "/foo/bar,1024/here"-      , Test "{#x,hello,y}" values "#1024,Hello%20World!,768"-      , Test "{#path,x}/here" values "#/foo/bar,1024/here"-      , Test "X{.var}" values "X.value"-      , Test "X{.x,y}" values "X.1024.768"-      , Test "{/var}" values "/value"-      , Test "{/var,x}/here" values "/value/1024/here"-      , Test "{;x,y}" values ";x=1024;y=768"-      , Test "{;x,y,empty}" values ";x=1024;y=768;empty"-      , Test "{?x,y}" values "?x=1024&y=768"-      , Test "{?x,y,empty}" values "?x=1024&y=768&empty="-      , Test "?fixed=yes{&x}" values "?fixed=yes&x=1024"-      , Test "{&x,y,empty}" values "&x=1024&y=768&empty="-      , Test "{var:3}" values "val"-      , Test "{var:30}" values "value"-      , Test "{list}" values "red,green,blue"-      , Test "{list*}" values "red,green,blue"-      , Test "{keys}" values "comma,%2C,dot,.,semi,%3B"-      , Test "{keys*}" values "comma=%2C,dot=.,semi=%3B"-      , Test "{+path:6}/here" values "/foo/b/here"-      , Test "{+list}" values "red,green,blue"-      , Test "{+list*}" values "red,green,blue"-      , Test "{+keys}" values "comma,,,dot,.,semi,;"-      , Test "{+keys*}" values "comma=,,dot=.,semi=;"-      , Test "{#path:6}/here" values "#/foo/b/here"-      , Test "{#list}" values "#red,green,blue"-      , Test "{#list*}" values "#red,green,blue"-      , Test "{#keys}" values "#comma,,,dot,.,semi,;"-      , Test "{#keys*}" values "#comma=,,dot=.,semi=;"-      , Test "X{.var:3}" values "X.val"-      , Test "X{.list}" values "X.red,green,blue"-      , Test "X{.list*}" values "X.red.green.blue"-      , Test "X{.keys}" values "X.comma,%2C,dot,.,semi,%3B"-      , Test "X{.keys*}" values "X.comma=%2C.dot=..semi=%3B"-      , Test "{/var:1,var}" values "/v/value"-      , Test "{/list}" values "/red,green,blue"-      , Test "{/list*}" values "/red/green/blue"-      , Test "{/list*,path:4}" values "/red/green/blue/%2Ffoo"-      , Test "{/keys}" values "/comma,%2C,dot,.,semi,%3B"-      , Test "{/keys*}" values "/comma=%2C/dot=./semi=%3B"-      , Test "{;hello:5}" values ";hello=Hello"-      , Test "{;list}" values ";list=red,green,blue"-      , Test "{;list*}" values ";list=red;list=green;list=blue"-      , Test "{;keys}" values ";keys=comma,%2C,dot,.,semi,%3B"-      , Test "{;keys*}" values ";comma=%2C;dot=.;semi=%3B"-      , Test "{?var:3}" values "?var=val"-      , Test "{?list}" values "?list=red,green,blue"-      , Test "{?list*}" values "?list=red&list=green&list=blue"-      , Test "{?keys}" values "?keys=comma,%2C,dot,.,semi,%3B"-      , Test "{?keys*}" values "?comma=%2C&dot=.&semi=%3B"-      , Test "{&var:3}" values "&var=val"-      , Test "{&list}" values "&list=red,green,blue"-      , Test "{&list*}" values "&list=red&list=green&list=blue"-      , Test "{&keys}" values "&keys=comma,%2C,dot,.,semi,%3B"-      , Test "{&keys*}" values "&comma=%2C&dot=.&semi=%3B"-      ]-  , let values = ["var" =: s "value", "semi" =: s ";"]-    in-      [ Test "{var}" values "value"-      , Test "{var:20}" values "value"-      , Test "{var:3}" values "val"-      , Test "{semi}" values "%3B"-      , Test "{semi:2}" values "%3B"-          -- This comment forces Brittany to use a multi-line layout.-      ]-  , let values = ["year" =: l ["1965", "2000", "2012"], "dom" =: l ["example", "com"]]-    in-      [ Test "find{?year*}" values "find?year=1965&year=2000&year=2012"-      , Test "www{.dom*}" values "www.example.com"-          -- This comment forces Brittany to use a multi-line layout.-      ]-  , let-      values =-        [ "base" =: s "http://example.com/home/"-        , "count" =: l ["one", "two", "three"]-        , "dom" =: l ["example", "com"]-        , "dub" =: s "me/too"-        , "empty_keys" =: d []-        , "empty" =: s ""-        , "half" =: s "50%"-        , "hello" =: s "Hello World!"-        , "keys" =: d ["semi" =: ";", "dot" =: ".", "comma" =: ","]-        , "list" =: l ["red", "green", "blue"]-        , "path" =: s "/foo/bar"-        , "v" =: s "6"-        , "var" =: s "value"-        , "who" =: s "fred"-        , "x" =: s "1024"-        , "y" =: s "768"-        ]-    in-      [ Test "{count}" values "one,two,three"-      , Test "{count*}" values "one,two,three"-      , Test "{/count}" values "/one,two,three"-      , Test "{/count*}" values "/one/two/three"-      , Test "{;count}" values ";count=one,two,three"-      , Test "{;count*}" values ";count=one;count=two;count=three"-      , Test "{?count}" values "?count=one,two,three"-      , Test "{?count*}" values "?count=one&count=two&count=three"-      , Test "{&count*}" values "&count=one&count=two&count=three"-      , Test "{var}" values "value"-      , Test "{hello}" values "Hello%20World%21"-      , Test "{half}" values "50%25"-      , Test "O{empty}X" values "OX"-      , Test "O{undef}X" values "OX"-      , Test "{x,y}" values "1024,768"-      , Test "{x,hello,y}" values "1024,Hello%20World%21,768"-      , Test "?{x,empty}" values "?1024,"-      , Test "?{x,undef}" values "?1024"-      , Test "?{undef,y}" values "?768"-      , Test "{var:3}" values "val"-      , Test "{var:30}" values "value"-      , Test "{list}" values "red,green,blue"-      , Test "{list*}" values "red,green,blue"-      , Test "{keys}" values "comma,%2C,dot,.,semi,%3B"-      , Test "{keys*}" values "comma=%2C,dot=.,semi=%3B"-      , Test "{+var}" values "value"-      , Test "{+hello}" values "Hello%20World!"-      , Test "{+half}" values "50%25"-      , Test "{base}index" values "http%3A%2F%2Fexample.com%2Fhome%2Findex"-      , Test "{+base}index" values "http://example.com/home/index"-      , Test "O{+empty}X" values "OX"-      , Test "O{+undef}X" values "OX"-      , Test "{+path}/here" values "/foo/bar/here"-      , Test "here?ref={+path}" values "here?ref=/foo/bar"-      , Test "up{+path}{var}/here" values "up/foo/barvalue/here"-      , Test "{+x,hello,y}" values "1024,Hello%20World!,768"-      , Test "{+path,x}/here" values "/foo/bar,1024/here"-      , Test "{+path:6}/here" values "/foo/b/here"-      , Test "{+list}" values "red,green,blue"-      , Test "{+list*}" values "red,green,blue"-      , Test "{+keys}" values "comma,,,dot,.,semi,;"-      , Test "{+keys*}" values "comma=,,dot=.,semi=;"-      , Test "{#var}" values "#value"-      , Test "{#hello}" values "#Hello%20World!"-      , Test "{#half}" values "#50%25"-      , Test "foo{#empty}" values "foo#"-      , Test "foo{#undef}" values "foo"-      , Test "{#x,hello,y}" values "#1024,Hello%20World!,768"-      , Test "{#path,x}/here" values "#/foo/bar,1024/here"-      , Test "{#path:6}/here" values "#/foo/b/here"-      , Test "{#list}" values "#red,green,blue"-      , Test "{#list*}" values "#red,green,blue"-      , Test "{#keys}" values "#comma,,,dot,.,semi,;"-      , Test "{#keys*}" values "#comma=,,dot=.,semi=;"-      , Test "{.who}" values ".fred"-      , Test "{.who,who}" values ".fred.fred"-      , Test "{.half,who}" values ".50%25.fred"-      , Test "www{.dom*}" values "www.example.com"-      , Test "X{.var}" values "X.value"-      , Test "X{.empty}" values "X."-      , Test "X{.undef}" values "X"-      , Test "X{.var:3}" values "X.val"-      , Test "X{.list}" values "X.red,green,blue"-      , Test "X{.list*}" values "X.red.green.blue"-      , Test "X{.keys}" values "X.comma,%2C,dot,.,semi,%3B"-      , Test "X{.keys*}" values "X.comma=%2C.dot=..semi=%3B"-      , Test "X{.empty_keys}" values "X"-      , Test "X{.empty_keys*}" values "X"-      , Test "{/who}" values "/fred"-      , Test "{/who,who}" values "/fred/fred"-      , Test "{/half,who}" values "/50%25/fred"-      , Test "{/who,dub}" values "/fred/me%2Ftoo"-      , Test "{/var}" values "/value"-      , Test "{/var,empty}" values "/value/"-      , Test "{/var,undef}" values "/value"-      , Test "{/var,x}/here" values "/value/1024/here"-      , Test "{/var:1,var}" values "/v/value"-      , Test "{/list}" values "/red,green,blue"-      , Test "{/list*}" values "/red/green/blue"-      , Test "{/list*,path:4}" values "/red/green/blue/%2Ffoo"-      , Test "{/keys}" values "/comma,%2C,dot,.,semi,%3B"-      , Test "{/keys*}" values "/comma=%2C/dot=./semi=%3B"-      , Test "{;who}" values ";who=fred"-      , Test "{;half}" values ";half=50%25"-      , Test "{;empty}" values ";empty"-      , Test "{;v,empty,who}" values ";v=6;empty;who=fred"-      , Test "{;v,bar,who}" values ";v=6;who=fred"-      , Test "{;x,y}" values ";x=1024;y=768"-      , Test "{;x,y,empty}" values ";x=1024;y=768;empty"-      , Test "{;x,y,undef}" values ";x=1024;y=768"-      , Test "{;hello:5}" values ";hello=Hello"-      , Test "{;list}" values ";list=red,green,blue"-      , Test "{;list*}" values ";list=red;list=green;list=blue"-      , Test "{;keys}" values ";keys=comma,%2C,dot,.,semi,%3B"-      , Test "{;keys*}" values ";comma=%2C;dot=.;semi=%3B"-      , Test "{?who}" values "?who=fred"-      , Test "{?half}" values "?half=50%25"-      , Test "{?x,y}" values "?x=1024&y=768"-      , Test "{?x,y,empty}" values "?x=1024&y=768&empty="-      , Test "{?x,y,undef}" values "?x=1024&y=768"-      , Test "{?var:3}" values "?var=val"-      , Test "{?list}" values "?list=red,green,blue"-      , Test "{?list*}" values "?list=red&list=green&list=blue"-      , Test "{?keys}" values "?keys=comma,%2C,dot,.,semi,%3B"-      , Test "{?keys*}" values "?comma=%2C&dot=.&semi=%3B"-      , Test "{&who}" values "&who=fred"-      , Test "{&half}" values "&half=50%25"-      , Test "?fixed=yes{&x}" values "?fixed=yes&x=1024"-      , Test "{&x,y,empty}" values "&x=1024&y=768&empty="-      , Test "{&x,y,undef}" values "&x=1024&y=768"-      , Test "{&var:3}" values "&var=val"-      , Test "{&list}" values "&list=red,green,blue"-      , Test "{&list*}" values "&list=red&list=green&list=blue"-      , Test "{&keys}" values "&keys=comma,%2C,dot,.,semi,%3B"-      , Test "{&keys*}" values "&comma=%2C&dot=.&semi=%3B"-      ]-  ]--data Test = Test-  { testInput :: String-  , testValues :: [(String, Burrito.Value)]-  , testOutput :: Output-  }-  deriving (Eq, Show)--runTest :: Test -> Hspec.Expectation-runTest test =-  case (Burrito.parse $ testInput test, unwrapOutput $ testOutput test) of-    (Nothing, Nothing) -> pure ()-    (Nothing, Just _) -> Hspec.expectationFailure "should have parsed"-    (Just _, Nothing) -> Hspec.expectationFailure "should not have parsed"-    (Just template, Just expected) -> do-      let-        values = testValues test-        actual = Burrito.expand values template-      actual `Hspec.shouldBe` expected-      Burrito.parse (show template) `Hspec.shouldBe` Just template-      let-        relevant =-          List.sort $ keepRelevant (templateVariables template) values-      Monad.when (isMatchable template relevant) $ do-        let matches = List.sort <$> Burrito.match expected template-        matches `Hspec.shouldSatisfy` elem relevant--isMatchable :: Template.Template -> [(String, Burrito.Value)] -> Bool-isMatchable template values =-  (not . any (isAsterisk . Variable.modifier) $ templateVariables template)-    && all (isString . snd) values--isString :: Burrito.Value -> Bool-isString value = case value of-  Value.String _ -> True-  _ -> False--isAsterisk :: Modifier.Modifier -> Bool-isAsterisk modifier = case modifier of-  Modifier.Asterisk -> True-  _ -> False--keepRelevant-  :: Set.Set Variable.Variable-  -> [(String, Burrito.Value)]-  -> [(String, Burrito.Value)]-keepRelevant variables =-  let-    vs =-      Map.fromListWith-          (\mx my -> case (mx, my) of-            (Just x, Just y) -> Just $ max x y-            _ -> Nothing-          )-        . fmap-            (\v ->-              ( Render.builderToString . Render.name $ Variable.name v-              , case Variable.modifier v of-                Modifier.Colon n -> Just $ MaxLength.count n-                _ -> Nothing-              )-            )-        $ Set.toList variables-  in-    Maybe.mapMaybe $ \(k, v) -> do-      m <- Map.lookup k vs-      pure . (,) k $ case m of-        Nothing -> v-        Just n -> case v of-          Value.String t -> Value.String $ Text.take n t-          _ -> v--templateVariables :: Template.Template -> Set.Set Variable.Variable-templateVariables =-  Set.fromList-    . concatMap-        (\token -> case token of-          Token.Expression expression ->-            NonEmpty.toList $ Expression.variables expression-          Token.Literal _ -> []-        )-    . Template.tokens--newtype Output = Output-  { unwrapOutput :: Maybe String-  } deriving (Eq, Show)--instance String.IsString Output where-  fromString = Output . Just--noParse :: Output-noParse = Output Nothing--(=:) :: a -> b -> (a, b)-(=:) = (,)--s :: String -> Burrito.Value-s = Burrito.stringValue--l :: [String] -> Burrito.Value-l = Burrito.listValue--d :: [(String, String)] -> Burrito.Value-d = Burrito.dictionaryValue--newtype Template = Template-  { unwrapTemplate :: Template.Template-  } deriving (Eq)--instance Show Template where-  show (Template template) =-    unwords [show $ show template, "{-", show (Template.tokens template), "-}"]--instance QC.Arbitrary Template where-  arbitrary = Template <$> arbitraryTemplate-  shrink = fmap Template . shrinkTemplate . unwrapTemplate--type Shrink a = a -> [a]--arbitraryTemplate :: QC.Gen Template.Template-arbitraryTemplate = Template.Template . simplify <$> QC.listOf arbitraryToken--shrinkTemplate :: Shrink Template.Template-shrinkTemplate =-  fmap (Template.Template . simplify)-    . QC.shrinkList shrinkToken-    . Template.tokens--simplify :: [Token.Token] -> [Token.Token]-simplify tokens = case tokens of-  t1 : t2 : ts -> case (t1, t2) of-    (Token.Literal l1, Token.Literal l2) ->-      simplify $ Token.Literal (appendLiteral l1 l2) : ts-    _ -> t1 : simplify (t2 : ts)-  _ -> tokens--appendLiteral :: Literal.Literal -> Literal.Literal -> Literal.Literal-appendLiteral x y =-  Literal.Literal $ Literal.characters x <> Literal.characters y--arbitraryToken :: QC.Gen Token.Token-arbitraryToken = QC.oneof-  [ Token.Expression <$> arbitraryExpression-  , Token.Literal <$> arbitraryLiteral-  ]--shrinkToken :: Shrink Token.Token-shrinkToken x = case x of-  Token.Expression y -> Token.Expression <$> shrinkExpression y-  Token.Literal y -> Token.Literal <$> shrinkLiteral y--arbitraryExpression :: QC.Gen Expression.Expression-arbitraryExpression =-  Expression.Expression-    <$> arbitraryOperator-    <*> arbitraryNonEmpty arbitraryVariable--shrinkExpression :: Shrink Expression.Expression-shrinkExpression x = uncurry Expression.Expression <$> shrinkTuple-  shrinkOperator-  (shrinkNonEmpty shrinkVariable)-  (Expression.operator x, Expression.variables x)--arbitraryOperator :: QC.Gen Operator.Operator-arbitraryOperator = QC.elements-  [ Operator.Ampersand-  , Operator.FullStop-  , Operator.None-  , Operator.NumberSign-  , Operator.PlusSign-  , Operator.QuestionMark-  , Operator.Semicolon-  , Operator.Solidus-  ]--shrinkOperator :: Shrink Operator.Operator-shrinkOperator x = case x of-  Operator.None -> []-  _ -> [Operator.None]--arbitraryNonEmpty :: QC.Gen a -> QC.Gen (NonEmpty.NonEmpty a)-arbitraryNonEmpty g = (NonEmpty.:|) <$> g <*> QC.listOf g--shrinkNonEmpty :: Shrink a -> Shrink (NonEmpty.NonEmpty a)-shrinkNonEmpty f x = uncurry (NonEmpty.:|)-  <$> shrinkTuple f (QC.shrinkList f) (NonEmpty.head x, NonEmpty.tail x)--arbitraryVariable :: QC.Gen Variable.Variable-arbitraryVariable = Variable.Variable <$> arbitraryName <*> arbitraryModifier--shrinkVariable :: Shrink Variable.Variable-shrinkVariable variable = uncurry Variable.Variable <$> shrinkTuple-  shrinkName-  shrinkModifier-  (Variable.name variable, Variable.modifier variable)--shrinkTuple :: Shrink a -> Shrink b -> Shrink (a, b)-shrinkTuple f g (x, y) =-  fmap (\a -> (a, y)) (f x) <> fmap (\b -> (x, b)) (g y)--arbitraryName :: QC.Gen Name.Name-arbitraryName = Name.Name <$> arbitraryNonEmpty arbitraryField--shrinkName :: Shrink Name.Name-shrinkName = fmap Name.Name . shrinkNonEmpty shrinkField . Name.fields--arbitraryField :: QC.Gen Field.Field-arbitraryField = Field.Field <$> arbitraryNonEmpty arbitraryFieldCharacter--shrinkField :: Shrink Field.Field-shrinkField =-  fmap Field.Field . shrinkNonEmpty shrinkFieldCharacter . Field.characters--arbitraryFieldCharacter :: QC.Gen (Character.Character Field.Field)-arbitraryFieldCharacter = QC.oneof-  [ Character.Encoded <$> arbitraryDigit <*> arbitraryDigit-  , Character.Unencoded <$> QC.suchThat QC.arbitrary Parse.isFieldCharacter-  ]--shrinkFieldCharacter :: Shrink (Character.Character Field.Field)-shrinkFieldCharacter x = case x of-  Character.Encoded y z ->-    uncurry Character.Encoded <$> shrinkTuple shrinkDigit shrinkDigit (y, z)-  Character.Unencoded y ->-    fmap Character.Unencoded . filter Parse.isFieldCharacter $ QC.shrink y--arbitraryDigit :: QC.Gen Digit.Digit-arbitraryDigit = QC.oneof-  [ pure Digit.Ox0-  , pure Digit.Ox1-  , pure Digit.Ox2-  , pure Digit.Ox3-  , pure Digit.Ox4-  , pure Digit.Ox5-  , pure Digit.Ox6-  , pure Digit.Ox7-  , pure Digit.Ox8-  , pure Digit.Ox9-  , Digit.OxA <$> arbitraryCase-  , Digit.OxB <$> arbitraryCase-  , Digit.OxC <$> arbitraryCase-  , Digit.OxD <$> arbitraryCase-  , Digit.OxE <$> arbitraryCase-  , Digit.OxF <$> arbitraryCase-  ]--shrinkDigit :: Shrink Digit.Digit-shrinkDigit x = case x of-  Digit.Ox0 -> []-  Digit.Ox1 -> [Digit.Ox0]-  Digit.Ox2 -> [Digit.Ox0]-  Digit.Ox3 -> [Digit.Ox0]-  Digit.Ox4 -> [Digit.Ox0]-  Digit.Ox5 -> [Digit.Ox0]-  Digit.Ox6 -> [Digit.Ox0]-  Digit.Ox7 -> [Digit.Ox0]-  Digit.Ox8 -> [Digit.Ox0]-  Digit.Ox9 -> [Digit.Ox0]-  Digit.OxA y -> Digit.Ox0 : fmap Digit.OxA (shrinkCase y)-  Digit.OxB y -> Digit.Ox0 : fmap Digit.OxA (shrinkCase y)-  Digit.OxC y -> Digit.Ox0 : fmap Digit.OxA (shrinkCase y)-  Digit.OxD y -> Digit.Ox0 : fmap Digit.OxA (shrinkCase y)-  Digit.OxE y -> Digit.Ox0 : fmap Digit.OxA (shrinkCase y)-  Digit.OxF y -> Digit.Ox0 : fmap Digit.OxA (shrinkCase y)--arbitraryCase :: QC.Gen Case.Case-arbitraryCase = QC.elements [Case.Lower, Case.Upper]--shrinkCase :: Shrink Case.Case-shrinkCase x = case x of-  Case.Lower -> []-  Case.Upper -> [Case.Lower]--arbitraryModifier :: QC.Gen Modifier.Modifier-arbitraryModifier = QC.oneof-  [ pure Modifier.Asterisk-  , Modifier.Colon <$> arbitraryMaxLength-  , pure Modifier.None-  ]--shrinkModifier :: Shrink Modifier.Modifier-shrinkModifier x = case x of-  Modifier.Asterisk -> [Modifier.None]-  Modifier.Colon y -> Modifier.None : fmap Modifier.Colon (shrinkMaxLength y)-  Modifier.None -> []--arbitraryMaxLength :: QC.Gen MaxLength.MaxLength-arbitraryMaxLength =-  MaxLength.MaxLength <$> QC.suchThat QC.arbitrary Parse.isMaxLength--shrinkMaxLength :: Shrink MaxLength.MaxLength-shrinkMaxLength =-  fmap MaxLength.MaxLength-    . filter Parse.isMaxLength-    . QC.shrink-    . MaxLength.count--arbitraryLiteral :: QC.Gen Literal.Literal-arbitraryLiteral =-  Literal.Literal <$> arbitraryNonEmpty arbitraryLiteralCharacter--shrinkLiteral :: Shrink Literal.Literal-shrinkLiteral =-  fmap Literal.Literal-    . shrinkNonEmpty shrinkLiteralCharacter-    . Literal.characters--arbitraryLiteralCharacter :: QC.Gen (Character.Character Literal.Literal)-arbitraryLiteralCharacter = QC.oneof-  [ Character.Encoded <$> arbitraryDigit <*> arbitraryDigit-  , Character.Unencoded <$> QC.suchThat QC.arbitrary Parse.isLiteralCharacter-  ]+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}+{-# OPTIONS_GHC -Wno-monomorphism-restriction #-}++module Main+  ( main,+  )+where++import qualified Burrito+import qualified Burrito.Internal.Parse as Parse+import qualified Burrito.Internal.Render as Render+import qualified Burrito.Internal.Type.Case as Case+import qualified Burrito.Internal.Type.Character as Character+import qualified Burrito.Internal.Type.Digit as Digit+import qualified Burrito.Internal.Type.Expression as Expression+import qualified Burrito.Internal.Type.Field as Field+import qualified Burrito.Internal.Type.Literal as Literal+import qualified Burrito.Internal.Type.MaxLength as MaxLength+import qualified Burrito.Internal.Type.Modifier as Modifier+import qualified Burrito.Internal.Type.Name as Name+import qualified Burrito.Internal.Type.Operator as Operator+import qualified Burrito.Internal.Type.Template as Template+import qualified Burrito.Internal.Type.Token as Token+import qualified Burrito.Internal.Type.Value as Value+import qualified Burrito.Internal.Type.Variable as Variable+import qualified Control.Monad as Monad+import qualified Data.List as List+import qualified Data.List.NonEmpty as NonEmpty+import qualified Data.Map as Map+import qualified Data.Maybe as Maybe+import qualified Data.Set as Set+import qualified Data.String as String+import qualified Data.Text as Text+import qualified GHC.Stack as Stack+import qualified Test.Hspec as Hspec+import qualified Test.Hspec.QuickCheck as Hspec+import qualified Test.QuickCheck as QC++main :: IO ()+main = Hspec.hspec . Hspec.describe "Burrito" $ do+  Monad.forM_ tests $ \test ->+    Hspec.it (show (testInput test, unwrapOutput $ testOutput test)) $+      runTest test++  Hspec.describe "match" $ do+    let matchTest ::+          (Stack.HasCallStack) =>+          String ->+          [(String, Burrito.Value)] ->+          String ->+          Hspec.Spec+        matchTest input values output = Hspec.it (show (input, output)) $ do+          template <- maybe (fail "invalid Template") pure $ Burrito.parse input+          let matches = Burrito.match output template+          matches `Hspec.shouldSatisfy` elem values+          Monad.forM_ matches $ \match -> do+            let it = Burrito.expand match template+            Monad.when (it /= output) . fail $+              show+                (input, values, output, matches, match, it)++    matchTest "" [] ""+    matchTest "a" [] "a"+    matchTest "!" [] "!"+    matchTest "\xa0" [] "%C2%A0"++    matchTest "{a}" ["a" =: s ""] ""+    matchTest "{a}" ["a" =: s "A"] "A"+    matchTest "{a}" ["a" =: s "AB"] "AB"++    matchTest "a{b}" ["b" =: s ""] "a"+    matchTest "a{b}" ["b" =: s "B"] "aB"+    matchTest "a{b}" ["b" =: s "BC"] "aBC"++    matchTest "{a}b" ["a" =: s ""] "b"+    matchTest "{a}b" ["a" =: s "A"] "Ab"+    matchTest "{a}b" ["a" =: s "AB"] "ABb"++    matchTest "{a}{a}" ["a" =: s "A"] "AA"+    matchTest "{a}{a}" ["a" =: s "AB"] "ABAB"++    matchTest "{a}" ["a" =: s "%"] "%25"+    matchTest "{a}" ["a" =: s "/"] "%2F"+    matchTest "{a}" ["a" =: s "\xa0"] "%C2%A0"+    matchTest "{a}" ["a" =: s "\xd7ff"] "%ED%9F%BF"+    matchTest "{a}" ["a" =: s "\x10000"] "%F0%90%80%80"+    matchTest "{a}" ["a" =: s "A/B"] "A%2FB"+    matchTest "{a}" ["a" =: s "WX\xa0\xa1YZ"] "WX%C2%A0%C2%A1YZ"++    matchTest "{+a}" ["a" =: s "%"] "%25"+    matchTest "{+a}" ["a" =: s "/"] "/"++    matchTest "{#a}" [] ""+    matchTest "{#a}" ["a" =: s ""] "#"+    matchTest "{#a}" ["a" =: s "A"] "#A"+    matchTest "{#a}" ["a" =: s "%"] "#%25"+    matchTest "{#a}" ["a" =: s "/"] "#/"++    matchTest "{.a}" [] ""+    matchTest "{.a}" ["a" =: s ""] "."+    matchTest "{.a}" ["a" =: s "A"] ".A"+    matchTest "{.a}" ["a" =: s "%"] ".%25"+    matchTest "{.a}" ["a" =: s "/"] ".%2F"++    matchTest "{/a}" [] ""+    matchTest "{/a}" ["a" =: s ""] "/"+    matchTest "{/a}" ["a" =: s "A"] "/A"+    matchTest "{/a}" ["a" =: s "%"] "/%25"+    matchTest "{/a}" ["a" =: s "/"] "/%2F"++    matchTest "{;a}" [] ""+    matchTest "{;a}" ["a" =: s ""] ";a"+    matchTest "{;a}" ["a" =: s "A"] ";a=A"+    matchTest "{;a}" ["a" =: s "%"] ";a=%25"+    matchTest "{;a}" ["a" =: s "/"] ";a=%2F"++    matchTest "{?a}" [] ""+    matchTest "{?a}" ["a" =: s ""] "?a="+    matchTest "{?a}" ["a" =: s "A"] "?a=A"+    matchTest "{?a}" ["a" =: s "%"] "?a=%25"+    matchTest "{?a}" ["a" =: s "/"] "?a=%2F"++    matchTest "{&a}" [] ""+    matchTest "{&a}" ["a" =: s ""] "&a="+    matchTest "{&a}" ["a" =: s "A"] "&a=A"+    matchTest "{&a}" ["a" =: s "%"] "&a=%25"+    matchTest "{&a}" ["a" =: s "/"] "&a=%2F"++    matchTest "{a,b}" ["a" =: s "A", "b" =: s "B"] "A,B"+    matchTest "{+a,b}" ["a" =: s "A", "b" =: s "B"] "A,B"+    matchTest "{#a,b}" ["a" =: s "A", "b" =: s "B"] "#A,B"+    matchTest "{.a,b}" ["a" =: s "A", "b" =: s "B"] ".A.B"+    matchTest "{/a,b}" ["a" =: s "A", "b" =: s "B"] "/A/B"+    matchTest "{;a,b}" ["a" =: s "A", "b" =: s "B"] ";a=A;b=B"+    matchTest "{?a,b}" ["a" =: s "A", "b" =: s "B"] "?a=A&b=B"+    matchTest "{&a,b}" ["a" =: s "A", "b" =: s "B"] "&a=A&b=B"++    matchTest "{a,b}" ["a" =: s "A"] "A"+    matchTest "{a,b,c}" ["a" =: s "A"] "A"+    matchTest "{a,b,c}" ["a" =: s "A", "b" =: s "B"] "A,B"+    matchTest "{a}{a,b}" ["b" =: s "B"] "B"+    matchTest "{a}{a,b,c}" ["b" =: s "B"] "B"+    matchTest "{a,b}{a,b,c}" ["c" =: s "C"] "C"+    matchTest "{b}{a,b,c}" ["a" =: s "A", "c" =: s "C"] "A,C"+    matchTest "{a}{a,b,c}" ["b" =: s "B", "c" =: s "C"] "B,C"++    matchTest "{a:1}/{a}" ["a" =: s "AB"] "A/AB"++  -- TODO: Test matching on explode modifier.+  -- matchTest "{a*}" ["a" =: s "A"] "A"++  -- TODO: Test matching on lists.+  -- matchTest "{a}" ["a" =: l ["A", "B"]] "A,B"++  -- TODO: Test matching on dictionaries.+  -- matchTest "{a}" ["a" =: d ["k" =: "v"]] "k,v"++  Hspec.describe "uriTemplate"+    . Hspec.it "works as an expression"+    $ Just [Burrito.uriTemplate|a{b}c|]+      `Hspec.shouldBe` Burrito.parse "a{b}c"++  Hspec.modifyMaxSize (const 10)+    . Hspec.it "round trips"+    . QC.property+    $ \(Template template) -> Burrito.parse (show template) == Just template++-- brittany-next-binding --columns 160+tests :: [Test]+tests =+  mconcat+    [ [ Test "" [] "",+        Test "" ["a" =: s ""] "",+        Test "" ["a" =: l []] "",+        Test "" ["a" =: d []] "",+        Test "!" [] "!",+        Test "#" [] "#",+        Test "$" [] "$",+        Test "&" [] "&",+        Test "(" [] "(",+        Test ")" [] ")",+        Test "*" [] "*",+        Test "+" [] "+",+        Test "," [] ",",+        Test "-" [] "-",+        Test "." [] ".",+        Test "/" [] "/",+        Test "0" [] "0",+        Test "9" [] "9",+        Test ":" [] ":",+        Test ";" [] ";",+        Test "=" [] "=",+        Test "?" [] "?",+        Test "@" [] "@",+        Test "A" [] "A",+        Test "Z" [] "Z",+        Test "[" [] "[",+        Test "]" [] "]",+        Test "_" [] "_",+        Test "a" [] "a",+        Test "z" [] "z",+        Test "~" [] "~",+        Test "\xa0" [] "%C2%A0",+        Test "\xd7ff" [] "%ED%9F%BF",+        Test "\xf900" [] "%EF%A4%80",+        Test "\xfdcf" [] "%EF%B7%8F",+        Test "\xfdf0" [] "%EF%B7%B0",+        Test "\xffef" [] "%EF%BF%AF",+        Test "\x10000" [] "%F0%90%80%80",+        Test "\x1fffd" [] "%F0%9F%BF%BD",+        Test "\x20000" [] "%F0%A0%80%80",+        Test "\x2fffd" [] "%F0%AF%BF%BD",+        Test "\x30000" [] "%F0%B0%80%80",+        Test "\x3fffd" [] "%F0%BF%BF%BD",+        Test "\x40000" [] "%F1%80%80%80",+        Test "\x4fffd" [] "%F1%8F%BF%BD",+        Test "\x50000" [] "%F1%90%80%80",+        Test "\x5fffd" [] "%F1%9F%BF%BD",+        Test "\x60000" [] "%F1%A0%80%80",+        Test "\x6fffd" [] "%F1%AF%BF%BD",+        Test "\x70000" [] "%F1%B0%80%80",+        Test "\x7fffd" [] "%F1%BF%BF%BD",+        Test "\x80000" [] "%F2%80%80%80",+        Test "\x8fffd" [] "%F2%8F%BF%BD",+        Test "\x90000" [] "%F2%90%80%80",+        Test "\x9fffd" [] "%F2%9F%BF%BD",+        Test "\xa0000" [] "%F2%A0%80%80",+        Test "\xafffd" [] "%F2%AF%BF%BD",+        Test "\xb0000" [] "%F2%B0%80%80",+        Test "\xbfffd" [] "%F2%BF%BF%BD",+        Test "\xc0000" [] "%F3%80%80%80",+        Test "\xcfffd" [] "%F3%8F%BF%BD",+        Test "\xd0000" [] "%F3%90%80%80",+        Test "\xdfffd" [] "%F3%9F%BF%BD",+        Test "\xe1000" [] "%F3%A1%80%80",+        Test "\xefffd" [] "%F3%AF%BF%BD",+        Test "\xe000" [] "%EE%80%80",+        Test "\xf8ff" [] "%EF%A3%BF",+        Test "\xf0000" [] "%F3%B0%80%80",+        Test "\xffffd" [] "%F3%BF%BF%BD",+        Test "\x100000" [] "%F4%80%80%80",+        Test "\x10fffd" [] "%F4%8F%BF%BD",+        Test "%00" [] "%00",+        Test "%AA" [] "%AA",+        Test "%Aa" [] "%Aa",+        Test "%aA" [] "%aA",+        Test "%aa" [] "%aa",+        Test "%" [] noParse,+        Test "%0" [] noParse,+        Test "%0z" [] noParse,+        Test "%z" [] noParse,+        Test "%30" [] "%30",+        Test " " [] noParse,+        Test "\"" [] noParse,+        Test "'" [] noParse,+        Test "%" [] noParse,+        Test "<" [] noParse,+        Test ">" [] noParse,+        Test "\\" [] noParse,+        Test "^" [] noParse,+        Test "`" [] noParse,+        Test "{" [] noParse,+        Test "|" [] noParse,+        Test "}" [] noParse,+        Test "{}" [] noParse,+        Test "{,}" [] noParse,+        Test "{a,,b}" [] noParse,+        Test "{+}" [] noParse,+        Test "{:1}" [] noParse,+        Test "{*}" [] noParse,+        Test "{AZ}" [] "",+        Test "{az}" [] "",+        Test "{09}" [] "",+        Test "{_a}" [] "",+        Test "{a_}" [] "",+        Test "{_}" [] "",+        Test "{A.A}" [] "",+        Test "{a.a}" [] "",+        Test "{0.0}" [] "",+        Test "{_._}" [] "",+        Test "{%aa.%aa}" [] "",+        Test "{.}" [] noParse,+        Test "{a.}" [] noParse,+        Test "{+.a}" [] noParse,+        Test "{a..b}" [] noParse,+        Test "{%00}" [] "",+        Test "{%}" [] noParse,+        Test "{%0}" [] noParse,+        Test "{%0z}" [] noParse,+        Test "{%z}" [] noParse,+        Test "{!}" [] noParse,+        Test "{" [] noParse,+        Test "{{}" [] noParse,+        Test "}" [] noParse,+        Test "{}}" [] noParse,+        Test "{a,b}" [] "",+        Test "{a,b,c,d}" [] "",+        Test "{a,a}" [] "",+        Test "{a:5}" [] "",+        Test "{a:67}" [] "",+        Test "{a:801}" [] "",+        Test "{a:234}" [] "",+        Test "{a:9999}" [] "",+        Test "{a:123}" ["a" =: s (replicate 200 'a')] . Output . Just $ replicate 123 'a',+        Test "{a:}" [] noParse,+        Test "{a:0}" [] noParse,+        Test "{a:10000}" [] noParse,+        Test "{a:-1}" [] noParse,+        Test "{a*}" [] "",+        Test "{a:1*}" [] noParse,+        Test "{a*:1}" [] noParse,+        Test "{a,b:1,c*}" [] "",+        Test "{+a}" [] "",+        Test "{#a}" [] "",+        Test "{.a}" [] "",+        Test "{/a}" [] "",+        Test "{;a}" [] "",+        Test "{?a}" [] "",+        Test "{&a}" [] "",+        Test "{=a}" [] noParse,+        Test "{,a}" [] noParse,+        Test "{!a}" [] noParse,+        Test "{@a}" [] noParse,+        Test "{|a}" [] noParse,+        Test "{+#a}" [] noParse,+        Test "{+a,#b}" [] noParse,+        Test "{+a:1}" [] "",+        Test "{#a*}" [] "",+        Test "{+a,b}" [] "",+        Test "{#a,b}" [] "",+        Test "{.a,b}" [] "",+        Test "{/a,b}" [] "",+        Test "{;a,b}" [] "",+        Test "{?a,b}" [] "",+        Test "{&a,b}" [] "",+        Test "{a}{b}" [] "",+        Test "{a}{b}{c}{d}" [] "",+        Test "{a}{a}" [] "",+        Test "{{}}" [] noParse,+        Test "{a{b}}" [] noParse,+        Test "{{a}b}" [] noParse,+        Test "{a{b}c}" [] noParse,+        Test "a{b}" [] "a",+        Test "{a}b" [] "b",+        Test "a{b}c" [] "ac",+        Test "{a}b{c}" [] "b",+        Test "{a}" [] "",+        Test "{+a}" [] "",+        Test "{#a}" [] "",+        Test "{.a}" [] "",+        Test "{/a}" [] "",+        Test "{;a}" [] "",+        Test "{?a}" [] "",+        Test "{&a}" [] "",+        Test "http://example.com/~{username}/" ["username" =: s "fred"] "http://example.com/~fred/",+        Test "http://example.com/~{username}/" ["username" =: s "mark"] "http://example.com/~mark/",+        Test "http://example.com/dictionary/{term:1}/{term}" ["term" =: s "cat"] "http://example.com/dictionary/c/cat",+        Test "http://example.com/dictionary/{term:1}/{term}" ["term" =: s "dog"] "http://example.com/dictionary/d/dog",+        Test "http://example.com/search{?q,lang}" ["q" =: s "cat", "lang" =: s "en"] "http://example.com/search?q=cat&lang=en",+        Test "http://example.com/search{?q,lang}" ["q" =: s "chien", "lang" =: s "fr"] "http://example.com/search?q=chien&lang=fr",+        Test "http://www.example.com/foo{?query,number}" ["query" =: s "mycelium", "number" =: s "100"] "http://www.example.com/foo?query=mycelium&number=100",+        Test "http://www.example.com/foo{?query,number}" ["number" =: s "100"] "http://www.example.com/foo?number=100",+        Test "http://www.example.com/foo{?query,number}" [] "http://www.example.com/foo",+        Test "{a}" [] "",+        Test "{a}" ["a" =: l []] "",+        Test "{a}" ["a" =: d []] "",+        Test "{a}" ["a" =: s ""] "",+        Test "{a}" ["a" =: s "A"] "A",+        Test "{a}" ["a" =: s "~"] "~",+        Test "{a}" ["a" =: s "%"] "%25",+        Test "{a}" ["a" =: s "?"] "%3F",+        Test "{a}" ["a" =: s "&"] "%26",+        Test "{a}" ["a" =: s "\xa0"] "%C2%A0",+        Test "{a}" ["a" =: s "\xd7ff"] "%ED%9F%BF",+        Test "{a}" ["a" =: s "\x10000"] "%F0%90%80%80",+        Test "{a}" ["a" =: l ["A"]] "A",+        Test "{a}" ["a" =: l ["A", "B"]] "A,B",+        Test "{a}" ["a" =: l ["%"]] "%25",+        Test "{a}" ["a" =: l ["\xa0"]] "%C2%A0",+        Test "{a}" ["a" =: d ["A" =: "1"]] "A,1",+        Test "{a}" ["a" =: d ["A" =: "1", "B" =: "2"]] "A,1,B,2",+        Test "{a}" ["a" =: d ["A" =: "%"]] "A,%25",+        Test "{a}" ["a" =: d ["A" =: "\xa0"]] "A,%C2%A0",+        Test "{a}" ["a" =: d ["%" =: "1"]] "%25,1",+        Test "{a*}" [] "",+        Test "{a*}" ["a" =: s ""] "",+        Test "{a*}" ["a" =: s "A"] "A",+        Test "{a*}" ["a" =: l []] "",+        Test "{a*}" ["a" =: l ["A"]] "A",+        Test "{a*}" ["a" =: l ["A", "B"]] "A,B",+        Test "{a*}" ["a" =: d []] "",+        Test "{a*}" ["a" =: d ["A" =: "1"]] "A=1",+        Test "{a*}" ["a" =: d ["A" =: "1", "B" =: "2"]] "A=1,B=2",+        Test "{a:1}" [] "",+        Test "{a:1}" ["a" =: s ""] "",+        Test "{a:1}" ["a" =: s "A"] "A",+        Test "{a:1}" ["a" =: s "AB"] "A",+        Test "{a:1}" ["a" =: s "%B"] "%25",+        Test "{a:1}" ["a" =: s "\xa0\&B"] "%C2%A0",+        Test "{a:1}" ["a" =: s "\xd7ff\&B"] "%ED%9F%BF",+        Test "{a:1}" ["a" =: s "\x10000\&B"] "%F0%90%80%80",+        Test "{a:1}" ["a" =: l []] "",+        Test "{a:1}" ["a" =: l ["AB"]] "AB",+        Test "{a:1}" ["a" =: l ["AB", "CD"]] "AB,CD",+        Test "{a:1}" ["a" =: d []] "",+        Test "{a:1}" ["a" =: d ["AB" =: "12"]] "AB,12",+        Test "{a:1}" ["a" =: d ["AB" =: "12", "CD" =: "34"]] "AB,12,CD,34",+        Test "{a,a}" [] "",+        Test "{a,a}" ["a" =: l []] "",+        Test "{a,a}" ["a" =: d []] "",+        Test "{a,a}" ["a" =: s ""] ",",+        Test "{a,b}" ["a" =: s ""] "",+        Test "{a,b}" ["b" =: s ""] "",+        Test "{%aa}" ["%aa" =: s "A"] "A",+        Test "{%aa}" ["%aa" =: l ["A", "B"]] "A,B",+        Test "{%aa}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] "A,1,B,2",+        Test "{%aa*}" ["%aa" =: s "A"] "A",+        Test "{%aa*}" ["%aa" =: l ["A", "B"]] "A,B",+        Test "{%aa*}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] "A=1,B=2",+        Test "{+a}" [] "",+        Test "{+a}" ["a" =: l []] "",+        Test "{+a}" ["a" =: d []] "",+        Test "{+a}" ["a" =: s ""] "",+        Test "{+a}" ["a" =: s "A"] "A",+        Test "{+a}" ["a" =: s "~"] "~",+        Test "{+a}" ["a" =: s "%"] "%25",+        Test "{+a}" ["a" =: s "?"] "?",+        Test "{+a}" ["a" =: s "&"] "&",+        Test "{+a}" ["a" =: s "\xa0"] "%C2%A0",+        Test "{+a}" ["a" =: s "\xd7ff"] "%ED%9F%BF",+        Test "{+a}" ["a" =: s "\x10000"] "%F0%90%80%80",+        Test "{+a}" ["a" =: l ["A"]] "A",+        Test "{+a}" ["a" =: l ["A", "B"]] "A,B",+        Test "{+a}" ["a" =: l ["%"]] "%25",+        Test "{+a}" ["a" =: l ["\xa0"]] "%C2%A0",+        Test "{+a}" ["a" =: d ["A" =: "1"]] "A,1",+        Test "{+a}" ["a" =: d ["A" =: "1", "B" =: "2"]] "A,1,B,2",+        Test "{+a}" ["a" =: d ["A" =: "%"]] "A,%25",+        Test "{+a}" ["a" =: d ["A" =: "\xa0"]] "A,%C2%A0",+        Test "{+a}" ["a" =: d ["%" =: "1"]] "%25,1",+        Test "{+a*}" [] "",+        Test "{+a*}" ["a" =: s ""] "",+        Test "{+a*}" ["a" =: s "A"] "A",+        Test "{+a*}" ["a" =: l []] "",+        Test "{+a*}" ["a" =: l ["A"]] "A",+        Test "{+a*}" ["a" =: l ["A", "B"]] "A,B",+        Test "{+a*}" ["a" =: d []] "",+        Test "{+a*}" ["a" =: d ["A" =: "1"]] "A=1",+        Test "{+a*}" ["a" =: d ["A" =: "1", "B" =: "2"]] "A=1,B=2",+        Test "{+a:1}" [] "",+        Test "{+a:1}" ["a" =: s ""] "",+        Test "{+a:1}" ["a" =: s "A"] "A",+        Test "{+a:1}" ["a" =: s "AB"] "A",+        Test "{+a:1}" ["a" =: s "%B"] "%25",+        Test "{+a:1}" ["a" =: s "\xa0\&B"] "%C2%A0",+        Test "{+a:1}" ["a" =: s "\xd7ff\&B"] "%ED%9F%BF",+        Test "{+a:1}" ["a" =: s "\x10000\&B"] "%F0%90%80%80",+        Test "{+a:1}" ["a" =: l []] "",+        Test "{+a:1}" ["a" =: l ["AB"]] "AB",+        Test "{+a:1}" ["a" =: l ["AB", "CD"]] "AB,CD",+        Test "{+a:1}" ["a" =: d []] "",+        Test "{+a:1}" ["a" =: d ["AB" =: "12"]] "AB,12",+        Test "{+a:1}" ["a" =: d ["AB" =: "12", "CD" =: "34"]] "AB,12,CD,34",+        Test "{+a,a}" [] "",+        Test "{+a,a}" ["a" =: l []] "",+        Test "{+a,a}" ["a" =: d []] "",+        Test "{+a,a}" ["a" =: s ""] ",",+        Test "{+a,b}" ["a" =: s ""] "",+        Test "{+a,b}" ["b" =: s ""] "",+        Test "{+%aa}" ["%aa" =: s "A"] "A",+        Test "{+%aa}" ["%aa" =: l ["A", "B"]] "A,B",+        Test "{+%aa}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] "A,1,B,2",+        Test "{+%aa*}" ["%aa" =: s "A"] "A",+        Test "{+%aa*}" ["%aa" =: l ["A", "B"]] "A,B",+        Test "{+%aa*}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] "A=1,B=2",+        Test "{#a}" [] "",+        Test "{#a}" ["a" =: l []] "",+        Test "{#a}" ["a" =: d []] "",+        Test "{#a}" ["a" =: s ""] "#",+        Test "{#a}" ["a" =: s "A"] "#A",+        Test "{#a}" ["a" =: s "~"] "#~",+        Test "{#a}" ["a" =: s "%"] "#%25",+        Test "{#a}" ["a" =: s "?"] "#?",+        Test "{#a}" ["a" =: s "&"] "#&",+        Test "{#a}" ["a" =: s "\xa0"] "#%C2%A0",+        Test "{#a}" ["a" =: s "\xd7ff"] "#%ED%9F%BF",+        Test "{#a}" ["a" =: s "\x10000"] "#%F0%90%80%80",+        Test "{#a}" ["a" =: l ["A"]] "#A",+        Test "{#a}" ["a" =: l ["A", "B"]] "#A,B",+        Test "{#a}" ["a" =: l ["%"]] "#%25",+        Test "{#a}" ["a" =: l ["\xa0"]] "#%C2%A0",+        Test "{#a}" ["a" =: d ["A" =: "1"]] "#A,1",+        Test "{#a}" ["a" =: d ["A" =: "1", "B" =: "2"]] "#A,1,B,2",+        Test "{#a}" ["a" =: d ["A" =: "%"]] "#A,%25",+        Test "{#a}" ["a" =: d ["A" =: "\xa0"]] "#A,%C2%A0",+        Test "{#a}" ["a" =: d ["%" =: "1"]] "#%25,1",+        Test "{#a*}" [] "",+        Test "{#a*}" ["a" =: s ""] "#",+        Test "{#a*}" ["a" =: s "A"] "#A",+        Test "{#a*}" ["a" =: l []] "",+        Test "{#a*}" ["a" =: l ["A"]] "#A",+        Test "{#a*}" ["a" =: l ["A", "B"]] "#A,B",+        Test "{#a*}" ["a" =: d []] "",+        Test "{#a*}" ["a" =: d ["A" =: "1"]] "#A=1",+        Test "{#a*}" ["a" =: d ["A" =: "1", "B" =: "2"]] "#A=1,B=2",+        Test "{#a:1}" [] "",+        Test "{#a:1}" ["a" =: s ""] "#",+        Test "{#a:1}" ["a" =: s "A"] "#A",+        Test "{#a:1}" ["a" =: s "AB"] "#A",+        Test "{#a:1}" ["a" =: s "%B"] "#%25",+        Test "{#a:1}" ["a" =: s "\xa0\&B"] "#%C2%A0",+        Test "{#a:1}" ["a" =: s "\xd7ff\&B"] "#%ED%9F%BF",+        Test "{#a:1}" ["a" =: s "\x10000\&B"] "#%F0%90%80%80",+        Test "{#a:1}" ["a" =: l []] "",+        Test "{#a:1}" ["a" =: l ["AB"]] "#AB",+        Test "{#a:1}" ["a" =: l ["AB", "CD"]] "#AB,CD",+        Test "{#a:1}" ["a" =: d []] "",+        Test "{#a:1}" ["a" =: d ["AB" =: "12"]] "#AB,12",+        Test "{#a:1}" ["a" =: d ["AB" =: "12", "CD" =: "34"]] "#AB,12,CD,34",+        Test "{#a,a}" [] "",+        Test "{#a,a}" ["a" =: l []] "",+        Test "{#a,a}" ["a" =: d []] "",+        Test "{#a,a}" ["a" =: s ""] "#,",+        Test "{#a,b}" ["a" =: s ""] "#",+        Test "{#a,b}" ["b" =: s ""] "#",+        Test "{#%aa}" ["%aa" =: s "A"] "#A",+        Test "{#%aa}" ["%aa" =: l ["A", "B"]] "#A,B",+        Test "{#%aa}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] "#A,1,B,2",+        Test "{#%aa*}" ["%aa" =: s "A"] "#A",+        Test "{#%aa*}" ["%aa" =: l ["A", "B"]] "#A,B",+        Test "{#%aa*}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] "#A=1,B=2",+        Test "{.a}" [] "",+        Test "{.a}" ["a" =: l []] "",+        Test "{.a}" ["a" =: d []] "",+        Test "{.a}" ["a" =: s ""] ".",+        Test "{.a}" ["a" =: s "A"] ".A",+        Test "{.a}" ["a" =: s "~"] ".~",+        Test "{.a}" ["a" =: s "%"] ".%25",+        Test "{.a}" ["a" =: s "?"] ".%3F",+        Test "{.a}" ["a" =: s "&"] ".%26",+        Test "{.a}" ["a" =: s "\xa0"] ".%C2%A0",+        Test "{.a}" ["a" =: s "\xd7ff"] ".%ED%9F%BF",+        Test "{.a}" ["a" =: s "\x10000"] ".%F0%90%80%80",+        Test "{.a}" ["a" =: l ["A"]] ".A",+        Test "{.a}" ["a" =: l ["A", "B"]] ".A,B",+        Test "{.a}" ["a" =: l ["%"]] ".%25",+        Test "{.a}" ["a" =: l ["\xa0"]] ".%C2%A0",+        Test "{.a}" ["a" =: d ["A" =: "1"]] ".A,1",+        Test "{.a}" ["a" =: d ["A" =: "1", "B" =: "2"]] ".A,1,B,2",+        Test "{.a}" ["a" =: d ["A" =: "%"]] ".A,%25",+        Test "{.a}" ["a" =: d ["A" =: "\xa0"]] ".A,%C2%A0",+        Test "{.a}" ["a" =: d ["%" =: "1"]] ".%25,1",+        Test "{.a*}" [] "",+        Test "{.a*}" ["a" =: s ""] ".",+        Test "{.a*}" ["a" =: s "A"] ".A",+        Test "{.a*}" ["a" =: l []] "",+        Test "{.a*}" ["a" =: l ["A"]] ".A",+        Test "{.a*}" ["a" =: l ["A", "B"]] ".A.B",+        Test "{.a*}" ["a" =: d []] "",+        Test "{.a*}" ["a" =: d ["A" =: "1"]] ".A=1",+        Test "{.a*}" ["a" =: d ["A" =: "1", "B" =: "2"]] ".A=1.B=2",+        Test "{.a:1}" [] "",+        Test "{.a:1}" ["a" =: s ""] ".",+        Test "{.a:1}" ["a" =: s "A"] ".A",+        Test "{.a:1}" ["a" =: s "AB"] ".A",+        Test "{.a:1}" ["a" =: s "%B"] ".%25",+        Test "{.a:1}" ["a" =: s "\xa0\&B"] ".%C2%A0",+        Test "{.a:1}" ["a" =: s "\xd7ff\&B"] ".%ED%9F%BF",+        Test "{.a:1}" ["a" =: s "\x10000\&B"] ".%F0%90%80%80",+        Test "{.a:1}" ["a" =: l []] "",+        Test "{.a:1}" ["a" =: l ["AB"]] ".AB",+        Test "{.a:1}" ["a" =: l ["AB", "CD"]] ".AB,CD",+        Test "{.a:1}" ["a" =: d []] "",+        Test "{.a:1}" ["a" =: d ["AB" =: "12"]] ".AB,12",+        Test "{.a:1}" ["a" =: d ["AB" =: "12", "CD" =: "34"]] ".AB,12,CD,34",+        Test "{.a,a}" [] "",+        Test "{.a,a}" ["a" =: l []] "",+        Test "{.a,a}" ["a" =: d []] "",+        Test "{.a,a}" ["a" =: s ""] "..",+        Test "{.a,b}" ["a" =: s ""] ".",+        Test "{.a,b}" ["b" =: s ""] ".",+        Test "{.%aa}" ["%aa" =: s "A"] ".A",+        Test "{.%aa}" ["%aa" =: l ["A", "B"]] ".A,B",+        Test "{.%aa}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] ".A,1,B,2",+        Test "{.%aa*}" ["%aa" =: s "A"] ".A",+        Test "{.%aa*}" ["%aa" =: l ["A", "B"]] ".A.B",+        Test "{.%aa*}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] ".A=1.B=2",+        Test "{/a}" [] "",+        Test "{/a}" ["a" =: l []] "",+        Test "{/a}" ["a" =: d []] "",+        Test "{/a}" ["a" =: s ""] "/",+        Test "{/a}" ["a" =: s "A"] "/A",+        Test "{/a}" ["a" =: s "~"] "/~",+        Test "{/a}" ["a" =: s "%"] "/%25",+        Test "{/a}" ["a" =: s "?"] "/%3F",+        Test "{/a}" ["a" =: s "&"] "/%26",+        Test "{/a}" ["a" =: s "\xa0"] "/%C2%A0",+        Test "{/a}" ["a" =: s "\xd7ff"] "/%ED%9F%BF",+        Test "{/a}" ["a" =: s "\x10000"] "/%F0%90%80%80",+        Test "{/a}" ["a" =: l ["A"]] "/A",+        Test "{/a}" ["a" =: l ["A", "B"]] "/A,B",+        Test "{/a}" ["a" =: l ["%"]] "/%25",+        Test "{/a}" ["a" =: l ["\xa0"]] "/%C2%A0",+        Test "{/a}" ["a" =: d ["A" =: "1"]] "/A,1",+        Test "{/a}" ["a" =: d ["A" =: "1", "B" =: "2"]] "/A,1,B,2",+        Test "{/a}" ["a" =: d ["A" =: "%"]] "/A,%25",+        Test "{/a}" ["a" =: d ["A" =: "\xa0"]] "/A,%C2%A0",+        Test "{/a}" ["a" =: d ["%" =: "1"]] "/%25,1",+        Test "{/a*}" [] "",+        Test "{/a*}" ["a" =: s ""] "/",+        Test "{/a*}" ["a" =: s "A"] "/A",+        Test "{/a*}" ["a" =: l []] "",+        Test "{/a*}" ["a" =: l ["A"]] "/A",+        Test "{/a*}" ["a" =: l ["A", "B"]] "/A/B",+        Test "{/a*}" ["a" =: d []] "",+        Test "{/a*}" ["a" =: d ["A" =: "1"]] "/A=1",+        Test "{/a*}" ["a" =: d ["A" =: "1", "B" =: "2"]] "/A=1/B=2",+        Test "{/a:1}" [] "",+        Test "{/a:1}" ["a" =: s ""] "/",+        Test "{/a:1}" ["a" =: s "A"] "/A",+        Test "{/a:1}" ["a" =: s "AB"] "/A",+        Test "{/a:1}" ["a" =: s "%B"] "/%25",+        Test "{/a:1}" ["a" =: s "\xa0\&B"] "/%C2%A0",+        Test "{/a:1}" ["a" =: s "\xd7ff\&B"] "/%ED%9F%BF",+        Test "{/a:1}" ["a" =: s "\x10000\&B"] "/%F0%90%80%80",+        Test "{/a:1}" ["a" =: l []] "",+        Test "{/a:1}" ["a" =: l ["AB"]] "/AB",+        Test "{/a:1}" ["a" =: l ["AB", "CD"]] "/AB,CD",+        Test "{/a:1}" ["a" =: d []] "",+        Test "{/a:1}" ["a" =: d ["AB" =: "12"]] "/AB,12",+        Test "{/a:1}" ["a" =: d ["AB" =: "12", "CD" =: "34"]] "/AB,12,CD,34",+        Test "{/a,a}" [] "",+        Test "{/a,a}" ["a" =: l []] "",+        Test "{/a,a}" ["a" =: d []] "",+        Test "{/a,a}" ["a" =: s ""] "//",+        Test "{/a,b}" ["a" =: s ""] "/",+        Test "{/a,b}" ["b" =: s ""] "/",+        Test "{/%aa}" ["%aa" =: s "A"] "/A",+        Test "{/%aa}" ["%aa" =: l ["A", "B"]] "/A,B",+        Test "{/%aa}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] "/A,1,B,2",+        Test "{/%aa*}" ["%aa" =: s "A"] "/A",+        Test "{/%aa*}" ["%aa" =: l ["A", "B"]] "/A/B",+        Test "{/%aa*}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] "/A=1/B=2",+        Test "{;a}" [] "",+        Test "{;a}" ["a" =: l []] "",+        Test "{;a}" ["a" =: d []] "",+        Test "{;a}" ["a" =: s ""] ";a",+        Test "{;a}" ["a" =: s "A"] ";a=A",+        Test "{;a}" ["a" =: s "~"] ";a=~",+        Test "{;a}" ["a" =: s "%"] ";a=%25",+        Test "{;a}" ["a" =: s "?"] ";a=%3F",+        Test "{;a}" ["a" =: s "&"] ";a=%26",+        Test "{;a}" ["a" =: s "\xa0"] ";a=%C2%A0",+        Test "{;a}" ["a" =: s "\xd7ff"] ";a=%ED%9F%BF",+        Test "{;a}" ["a" =: s "\x10000"] ";a=%F0%90%80%80",+        Test "{;a}" ["a" =: l ["A"]] ";a=A",+        Test "{;a}" ["a" =: l ["A", "B"]] ";a=A,B",+        Test "{;a}" ["a" =: l ["%"]] ";a=%25",+        Test "{;a}" ["a" =: l ["\xa0"]] ";a=%C2%A0",+        Test "{;a}" ["a" =: d ["A" =: "1"]] ";a=A,1",+        Test "{;a}" ["a" =: d ["A" =: "1", "B" =: "2"]] ";a=A,1,B,2",+        Test "{;a}" ["a" =: d ["A" =: "%"]] ";a=A,%25",+        Test "{;a}" ["a" =: d ["A" =: "\xa0"]] ";a=A,%C2%A0",+        Test "{;a}" ["a" =: d ["%" =: "1"]] ";a=%25,1",+        Test "{;a*}" [] "",+        Test "{;a*}" ["a" =: s ""] ";a",+        Test "{;a*}" ["a" =: s "A"] ";a=A",+        Test "{;a*}" ["a" =: l []] "",+        Test "{;a*}" ["a" =: l ["A"]] ";a=A",+        Test "{;a*}" ["a" =: l ["A", "B"]] ";a=A;a=B",+        Test "{;a*}" ["a" =: d []] "",+        Test "{;a*}" ["a" =: d ["A" =: "1"]] ";A=1",+        Test "{;a*}" ["a" =: d ["A" =: "1", "B" =: "2"]] ";A=1;B=2",+        Test "{;a:1}" [] "",+        Test "{;a:1}" ["a" =: s ""] ";a",+        Test "{;a:1}" ["a" =: s "A"] ";a=A",+        Test "{;a:1}" ["a" =: s "AB"] ";a=A",+        Test "{;a:1}" ["a" =: s "%B"] ";a=%25",+        Test "{;a:1}" ["a" =: s "\xa0\&B"] ";a=%C2%A0",+        Test "{;a:1}" ["a" =: s "\xd7ff\&B"] ";a=%ED%9F%BF",+        Test "{;a:1}" ["a" =: s "\x10000\&B"] ";a=%F0%90%80%80",+        Test "{;a:1}" ["a" =: l []] "",+        Test "{;a:1}" ["a" =: l ["AB"]] ";a=AB",+        Test "{;a:1}" ["a" =: l ["AB", "CD"]] ";a=AB,CD",+        Test "{;a:1}" ["a" =: d []] "",+        Test "{;a:1}" ["a" =: d ["AB" =: "12"]] ";a=AB,12",+        Test "{;a:1}" ["a" =: d ["AB" =: "12", "CD" =: "34"]] ";a=AB,12,CD,34",+        Test "{;a,a}" [] "",+        Test "{;a,a}" ["a" =: l []] "",+        Test "{;a,a}" ["a" =: d []] "",+        Test "{;a,a}" ["a" =: s ""] ";a;a",+        Test "{;a,b}" ["a" =: s ""] ";a",+        Test "{;a,b}" ["b" =: s ""] ";b",+        Test "{;%aa}" ["%aa" =: s "A"] ";%aa=A",+        Test "{;%aa}" ["%aa" =: l ["A", "B"]] ";%aa=A,B",+        Test "{;%aa}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] ";%aa=A,1,B,2",+        Test "{;%aa*}" ["%aa" =: s "A"] ";%aa=A",+        Test "{;%aa*}" ["%aa" =: l ["A", "B"]] ";%aa=A;%aa=B",+        Test "{;%aa*}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] ";A=1;B=2",+        Test "{?a}" [] "",+        Test "{?a}" ["a" =: l []] "",+        Test "{?a}" ["a" =: d []] "",+        Test "{?a}" ["a" =: s ""] "?a=",+        Test "{?a}" ["a" =: s "A"] "?a=A",+        Test "{?a}" ["a" =: s "~"] "?a=~",+        Test "{?a}" ["a" =: s "%"] "?a=%25",+        Test "{?a}" ["a" =: s "?"] "?a=%3F",+        Test "{?a}" ["a" =: s "&"] "?a=%26",+        Test "{?a}" ["a" =: s "\xa0"] "?a=%C2%A0",+        Test "{?a}" ["a" =: s "\xd7ff"] "?a=%ED%9F%BF",+        Test "{?a}" ["a" =: s "\x10000"] "?a=%F0%90%80%80",+        Test "{?a}" ["a" =: l ["A"]] "?a=A",+        Test "{?a}" ["a" =: l ["A", "B"]] "?a=A,B",+        Test "{?a}" ["a" =: l ["%"]] "?a=%25",+        Test "{?a}" ["a" =: l ["\xa0"]] "?a=%C2%A0",+        Test "{?a}" ["a" =: d ["A" =: "1"]] "?a=A,1",+        Test "{?a}" ["a" =: d ["A" =: "1", "B" =: "2"]] "?a=A,1,B,2",+        Test "{?a}" ["a" =: d ["A" =: "%"]] "?a=A,%25",+        Test "{?a}" ["a" =: d ["A" =: "\xa0"]] "?a=A,%C2%A0",+        Test "{?a}" ["a" =: d ["%" =: "1"]] "?a=%25,1",+        Test "{?a*}" [] "",+        Test "{?a*}" ["a" =: s ""] "?a=",+        Test "{?a*}" ["a" =: s "A"] "?a=A",+        Test "{?a*}" ["a" =: l []] "",+        Test "{?a*}" ["a" =: l ["A"]] "?a=A",+        Test "{?a*}" ["a" =: l ["A", "B"]] "?a=A&a=B",+        Test "{?a*}" ["a" =: d []] "",+        Test "{?a*}" ["a" =: d ["A" =: "1"]] "?A=1",+        Test "{?a*}" ["a" =: d ["A" =: "1", "B" =: "2"]] "?A=1&B=2",+        Test "{?a:1}" [] "",+        Test "{?a:1}" ["a" =: s ""] "?a=",+        Test "{?a:1}" ["a" =: s "A"] "?a=A",+        Test "{?a:1}" ["a" =: s "AB"] "?a=A",+        Test "{?a:1}" ["a" =: s "%B"] "?a=%25",+        Test "{?a:1}" ["a" =: s "\xa0\&B"] "?a=%C2%A0",+        Test "{?a:1}" ["a" =: s "\xd7ff\&B"] "?a=%ED%9F%BF",+        Test "{?a:1}" ["a" =: s "\x10000\&B"] "?a=%F0%90%80%80",+        Test "{?a:1}" ["a" =: l []] "",+        Test "{?a:1}" ["a" =: l ["AB"]] "?a=AB",+        Test "{?a:1}" ["a" =: l ["AB", "CD"]] "?a=AB,CD",+        Test "{?a:1}" ["a" =: d []] "",+        Test "{?a:1}" ["a" =: d ["AB" =: "12"]] "?a=AB,12",+        Test "{?a:1}" ["a" =: d ["AB" =: "12", "CD" =: "34"]] "?a=AB,12,CD,34",+        Test "{?a,a}" [] "",+        Test "{?a,a}" ["a" =: l []] "",+        Test "{?a,a}" ["a" =: d []] "",+        Test "{?a,a}" ["a" =: s ""] "?a=&a=",+        Test "{?a,b}" ["a" =: s ""] "?a=",+        Test "{?a,b}" ["b" =: s ""] "?b=",+        Test "{?%aa}" ["%aa" =: s "A"] "?%aa=A",+        Test "{?%aa}" ["%aa" =: l ["A", "B"]] "?%aa=A,B",+        Test "{?%aa}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] "?%aa=A,1,B,2",+        Test "{?%aa*}" ["%aa" =: s "A"] "?%aa=A",+        Test "{?%aa*}" ["%aa" =: l ["A", "B"]] "?%aa=A&%aa=B",+        Test "{?%aa*}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] "?A=1&B=2",+        Test "{&a}" [] "",+        Test "{&a}" ["a" =: l []] "",+        Test "{&a}" ["a" =: d []] "",+        Test "{&a}" ["a" =: s ""] "&a=",+        Test "{&a}" ["a" =: s "A"] "&a=A",+        Test "{&a}" ["a" =: s "~"] "&a=~",+        Test "{&a}" ["a" =: s "%"] "&a=%25",+        Test "{&a}" ["a" =: s "?"] "&a=%3F",+        Test "{&a}" ["a" =: s "&"] "&a=%26",+        Test "{&a}" ["a" =: s "\xa0"] "&a=%C2%A0",+        Test "{&a}" ["a" =: s "\xd7ff"] "&a=%ED%9F%BF",+        Test "{&a}" ["a" =: s "\x10000"] "&a=%F0%90%80%80",+        Test "{&a}" ["a" =: l ["A"]] "&a=A",+        Test "{&a}" ["a" =: l ["A", "B"]] "&a=A,B",+        Test "{&a}" ["a" =: l ["%"]] "&a=%25",+        Test "{&a}" ["a" =: l ["\xa0"]] "&a=%C2%A0",+        Test "{&a}" ["a" =: d ["A" =: "1"]] "&a=A,1",+        Test "{&a}" ["a" =: d ["A" =: "1", "B" =: "2"]] "&a=A,1,B,2",+        Test "{&a}" ["a" =: d ["A" =: "%"]] "&a=A,%25",+        Test "{&a}" ["a" =: d ["A" =: "\xa0"]] "&a=A,%C2%A0",+        Test "{&a}" ["a" =: d ["%" =: "1"]] "&a=%25,1",+        Test "{&a*}" [] "",+        Test "{&a*}" ["a" =: s ""] "&a=",+        Test "{&a*}" ["a" =: s "A"] "&a=A",+        Test "{&a*}" ["a" =: l []] "",+        Test "{&a*}" ["a" =: l ["A"]] "&a=A",+        Test "{&a*}" ["a" =: l ["A", "B"]] "&a=A&a=B",+        Test "{&a*}" ["a" =: d []] "",+        Test "{&a*}" ["a" =: d ["A" =: "1"]] "&A=1",+        Test "{&a*}" ["a" =: d ["A" =: "1", "B" =: "2"]] "&A=1&B=2",+        Test "{&a:1}" [] "",+        Test "{&a:1}" ["a" =: s ""] "&a=",+        Test "{&a:1}" ["a" =: s "A"] "&a=A",+        Test "{&a:1}" ["a" =: s "AB"] "&a=A",+        Test "{&a:1}" ["a" =: s "%B"] "&a=%25",+        Test "{&a:1}" ["a" =: s "\xa0\&B"] "&a=%C2%A0",+        Test "{&a:1}" ["a" =: s "\xd7ff\&B"] "&a=%ED%9F%BF",+        Test "{&a:1}" ["a" =: s "\x10000\&B"] "&a=%F0%90%80%80",+        Test "{&a:1}" ["a" =: l []] "",+        Test "{&a:1}" ["a" =: l ["AB"]] "&a=AB",+        Test "{&a:1}" ["a" =: l ["AB", "CD"]] "&a=AB,CD",+        Test "{&a:1}" ["a" =: d []] "",+        Test "{&a:1}" ["a" =: d ["AB" =: "12"]] "&a=AB,12",+        Test "{&a:1}" ["a" =: d ["AB" =: "12", "CD" =: "34"]] "&a=AB,12,CD,34",+        Test "{&a,a}" [] "",+        Test "{&a,a}" ["a" =: l []] "",+        Test "{&a,a}" ["a" =: d []] "",+        Test "{&a,a}" ["a" =: s ""] "&a=&a=",+        Test "{&a,b}" ["a" =: s ""] "&a=",+        Test "{&a,b}" ["b" =: s ""] "&b=",+        Test "{&%aa}" ["%aa" =: s "A"] "&%aa=A",+        Test "{&%aa}" ["%aa" =: l ["A", "B"]] "&%aa=A,B",+        Test "{&%aa}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] "&%aa=A,1,B,2",+        Test "{&%aa*}" ["%aa" =: s "A"] "&%aa=A",+        Test "{&%aa*}" ["%aa" =: l ["A", "B"]] "&%aa=A&%aa=B",+        Test "{&%aa*}" ["%aa" =: d ["A" =: "1", "B" =: "2"]] "&A=1&B=2"+      ],+      let values = ["%AA" =: s "1", "%Aa" =: s "2", "%aA" =: s "3", "%aa" =: s "4"]+       in [ Test "{%AA}" values "1",+            Test "{%Aa}" values "2",+            Test "{%aA}" values "3",+            Test "{%aa}" values "4"+            -- This comment forces Brittany to use a multi-line layout.+          ],+      let values = ["a" =: s "abcdefghijklmnopqrstuvwxyz"]+       in [ Test "{a:1}" values "a",+            Test "{a:5}" values "abcde",+            Test "{a:10}" values "abcdefghij",+            Test "{a:15}" values "abcdefghijklmno",+            Test "{a:20}" values "abcdefghijklmnopqrst",+            Test "{a:25}" values "abcdefghijklmnopqrstuvwxy",+            Test "{a:26}" values "abcdefghijklmnopqrstuvwxyz",+            Test "{a:30}" values "abcdefghijklmnopqrstuvwxyz"+          ],+      let values = ["a" =: l []]+       in [ Test "{a}" values "",+            Test "{+a}" values "",+            Test "{#a}" values "",+            Test "{.a}" values "",+            Test "{/a}" values "",+            Test "{;a}" values "",+            Test "{?a}" values "",+            Test "{&a}" values ""+          ],+      let values = ["a" =: d []]+       in [ Test "{a}" values "",+            Test "{+a}" values "",+            Test "{#a}" values "",+            Test "{.a}" values "",+            Test "{/a}" values "",+            Test "{;a}" values "",+            Test "{?a}" values "",+            Test "{&a}" values ""+          ],+      let values = ["a" =: s ""]+       in [ Test "{a}" values "",+            Test "{+a}" values "",+            Test "{#a}" values "#",+            Test "{.a}" values ".",+            Test "{/a}" values "/",+            Test "{;a}" values ";a",+            Test "{?a}" values "?a=",+            Test "{&a}" values "&a="+          ],+      let values = ["a" =: s "A"]+       in [ Test "{a}" values "A",+            Test "{+a}" values "A",+            Test "{#a}" values "#A",+            Test "{.a}" values ".A",+            Test "{/a}" values "/A",+            Test "{;a}" values ";a=A",+            Test "{?a}" values "?a=A",+            Test "{&a}" values "&a=A"+          ],+      let values = ["b" =: s "B"]+       in [ Test "{a,b}" values "B",+            Test "{+a,b}" values "B",+            Test "{#a,b}" values "#B",+            Test "{.a,b}" values ".B",+            Test "{/a,b}" values "/B",+            Test "{;a,b}" values ";b=B",+            Test "{?a,b}" values "?b=B",+            Test "{&a,b}" values "&b=B"+          ],+      let values = ["a" =: s ""]+       in [ Test "{a,a}" values ",",+            Test "{+a,a}" values ",",+            Test "{#a,a}" values "#,",+            Test "{.a,a}" values "..",+            Test "{/a,a}" values "//",+            Test "{;a,a}" values ";a;a",+            Test "{?a,a}" values "?a=&a=",+            Test "{&a,a}" values "&a=&a="+          ],+      let values = ["a" =: s "A", "b" =: s "B"]+       in [ Test "{a,b}" values "A,B",+            Test "{+a,b}" values "A,B",+            Test "{#a,b}" values "#A,B",+            Test "{.a,b}" values ".A.B",+            Test "{/a,b}" values "/A/B",+            Test "{;a,b}" values ";a=A;b=B",+            Test "{?a,b}" values "?a=A&b=B",+            Test "{&a,b}" values "&a=A&b=B"+          ],+      let values = ["a" =: d ["K! \xa0\xd7ff\x10000" =: "V! \xa0\xd7ff\x10000"]]+       in [ Test "{a*}" values "K%21%20%C2%A0%ED%9F%BF%F0%90%80%80=V%21%20%C2%A0%ED%9F%BF%F0%90%80%80",+            Test "{+a*}" values "K!%20%C2%A0%ED%9F%BF%F0%90%80%80=V!%20%C2%A0%ED%9F%BF%F0%90%80%80",+            Test "{#a*}" values "#K!%20%C2%A0%ED%9F%BF%F0%90%80%80=V!%20%C2%A0%ED%9F%BF%F0%90%80%80",+            Test "{.a*}" values ".K%21%20%C2%A0%ED%9F%BF%F0%90%80%80=V%21%20%C2%A0%ED%9F%BF%F0%90%80%80",+            Test "{/a*}" values "/K%21%20%C2%A0%ED%9F%BF%F0%90%80%80=V%21%20%C2%A0%ED%9F%BF%F0%90%80%80",+            Test "{;a*}" values ";K%21%20%C2%A0%ED%9F%BF%F0%90%80%80=V%21%20%C2%A0%ED%9F%BF%F0%90%80%80",+            Test "{?a*}" values "?K%21%20%C2%A0%ED%9F%BF%F0%90%80%80=V%21%20%C2%A0%ED%9F%BF%F0%90%80%80",+            Test "{&a*}" values "&K%21%20%C2%A0%ED%9F%BF%F0%90%80%80=V%21%20%C2%A0%ED%9F%BF%F0%90%80%80"+          ],+      let values =+            [ "empty" =: s "",+              "hello" =: s "Hello World!",+              "keys" =: d ["semi" =: ";", "dot" =: ".", "comma" =: ","],+              "list" =: l ["red", "green", "blue"],+              "path" =: s "/foo/bar",+              "var" =: s "value",+              "x" =: s "1024",+              "y" =: s "768"+            ]+       in [ Test "{var}" values "value",+            Test "{hello}" values "Hello%20World%21",+            Test "{+var}" values "value",+            Test "{+hello}" values "Hello%20World!",+            Test "{+path}/here" values "/foo/bar/here",+            Test "here?ref={+path}" values "here?ref=/foo/bar",+            Test "X{#var}" values "X#value",+            Test "X{#hello}" values "X#Hello%20World!",+            Test "map?{x,y}" values "map?1024,768",+            Test "{x,hello,y}" values "1024,Hello%20World%21,768",+            Test "{+x,hello,y}" values "1024,Hello%20World!,768",+            Test "{+path,x}/here" values "/foo/bar,1024/here",+            Test "{#x,hello,y}" values "#1024,Hello%20World!,768",+            Test "{#path,x}/here" values "#/foo/bar,1024/here",+            Test "X{.var}" values "X.value",+            Test "X{.x,y}" values "X.1024.768",+            Test "{/var}" values "/value",+            Test "{/var,x}/here" values "/value/1024/here",+            Test "{;x,y}" values ";x=1024;y=768",+            Test "{;x,y,empty}" values ";x=1024;y=768;empty",+            Test "{?x,y}" values "?x=1024&y=768",+            Test "{?x,y,empty}" values "?x=1024&y=768&empty=",+            Test "?fixed=yes{&x}" values "?fixed=yes&x=1024",+            Test "{&x,y,empty}" values "&x=1024&y=768&empty=",+            Test "{var:3}" values "val",+            Test "{var:30}" values "value",+            Test "{list}" values "red,green,blue",+            Test "{list*}" values "red,green,blue",+            Test "{keys}" values "comma,%2C,dot,.,semi,%3B",+            Test "{keys*}" values "comma=%2C,dot=.,semi=%3B",+            Test "{+path:6}/here" values "/foo/b/here",+            Test "{+list}" values "red,green,blue",+            Test "{+list*}" values "red,green,blue",+            Test "{+keys}" values "comma,,,dot,.,semi,;",+            Test "{+keys*}" values "comma=,,dot=.,semi=;",+            Test "{#path:6}/here" values "#/foo/b/here",+            Test "{#list}" values "#red,green,blue",+            Test "{#list*}" values "#red,green,blue",+            Test "{#keys}" values "#comma,,,dot,.,semi,;",+            Test "{#keys*}" values "#comma=,,dot=.,semi=;",+            Test "X{.var:3}" values "X.val",+            Test "X{.list}" values "X.red,green,blue",+            Test "X{.list*}" values "X.red.green.blue",+            Test "X{.keys}" values "X.comma,%2C,dot,.,semi,%3B",+            Test "X{.keys*}" values "X.comma=%2C.dot=..semi=%3B",+            Test "{/var:1,var}" values "/v/value",+            Test "{/list}" values "/red,green,blue",+            Test "{/list*}" values "/red/green/blue",+            Test "{/list*,path:4}" values "/red/green/blue/%2Ffoo",+            Test "{/keys}" values "/comma,%2C,dot,.,semi,%3B",+            Test "{/keys*}" values "/comma=%2C/dot=./semi=%3B",+            Test "{;hello:5}" values ";hello=Hello",+            Test "{;list}" values ";list=red,green,blue",+            Test "{;list*}" values ";list=red;list=green;list=blue",+            Test "{;keys}" values ";keys=comma,%2C,dot,.,semi,%3B",+            Test "{;keys*}" values ";comma=%2C;dot=.;semi=%3B",+            Test "{?var:3}" values "?var=val",+            Test "{?list}" values "?list=red,green,blue",+            Test "{?list*}" values "?list=red&list=green&list=blue",+            Test "{?keys}" values "?keys=comma,%2C,dot,.,semi,%3B",+            Test "{?keys*}" values "?comma=%2C&dot=.&semi=%3B",+            Test "{&var:3}" values "&var=val",+            Test "{&list}" values "&list=red,green,blue",+            Test "{&list*}" values "&list=red&list=green&list=blue",+            Test "{&keys}" values "&keys=comma,%2C,dot,.,semi,%3B",+            Test "{&keys*}" values "&comma=%2C&dot=.&semi=%3B"+          ],+      let values = ["var" =: s "value", "semi" =: s ";"]+       in [ Test "{var}" values "value",+            Test "{var:20}" values "value",+            Test "{var:3}" values "val",+            Test "{semi}" values "%3B",+            Test "{semi:2}" values "%3B"+            -- This comment forces Brittany to use a multi-line layout.+          ],+      let values = ["year" =: l ["1965", "2000", "2012"], "dom" =: l ["example", "com"]]+       in [ Test "find{?year*}" values "find?year=1965&year=2000&year=2012",+            Test "www{.dom*}" values "www.example.com"+            -- This comment forces Brittany to use a multi-line layout.+          ],+      let values =+            [ "base" =: s "http://example.com/home/",+              "count" =: l ["one", "two", "three"],+              "dom" =: l ["example", "com"],+              "dub" =: s "me/too",+              "empty_keys" =: d [],+              "empty" =: s "",+              "half" =: s "50%",+              "hello" =: s "Hello World!",+              "keys" =: d ["semi" =: ";", "dot" =: ".", "comma" =: ","],+              "list" =: l ["red", "green", "blue"],+              "path" =: s "/foo/bar",+              "v" =: s "6",+              "var" =: s "value",+              "who" =: s "fred",+              "x" =: s "1024",+              "y" =: s "768"+            ]+       in [ Test "{count}" values "one,two,three",+            Test "{count*}" values "one,two,three",+            Test "{/count}" values "/one,two,three",+            Test "{/count*}" values "/one/two/three",+            Test "{;count}" values ";count=one,two,three",+            Test "{;count*}" values ";count=one;count=two;count=three",+            Test "{?count}" values "?count=one,two,three",+            Test "{?count*}" values "?count=one&count=two&count=three",+            Test "{&count*}" values "&count=one&count=two&count=three",+            Test "{var}" values "value",+            Test "{hello}" values "Hello%20World%21",+            Test "{half}" values "50%25",+            Test "O{empty}X" values "OX",+            Test "O{undef}X" values "OX",+            Test "{x,y}" values "1024,768",+            Test "{x,hello,y}" values "1024,Hello%20World%21,768",+            Test "?{x,empty}" values "?1024,",+            Test "?{x,undef}" values "?1024",+            Test "?{undef,y}" values "?768",+            Test "{var:3}" values "val",+            Test "{var:30}" values "value",+            Test "{list}" values "red,green,blue",+            Test "{list*}" values "red,green,blue",+            Test "{keys}" values "comma,%2C,dot,.,semi,%3B",+            Test "{keys*}" values "comma=%2C,dot=.,semi=%3B",+            Test "{+var}" values "value",+            Test "{+hello}" values "Hello%20World!",+            Test "{+half}" values "50%25",+            Test "{base}index" values "http%3A%2F%2Fexample.com%2Fhome%2Findex",+            Test "{+base}index" values "http://example.com/home/index",+            Test "O{+empty}X" values "OX",+            Test "O{+undef}X" values "OX",+            Test "{+path}/here" values "/foo/bar/here",+            Test "here?ref={+path}" values "here?ref=/foo/bar",+            Test "up{+path}{var}/here" values "up/foo/barvalue/here",+            Test "{+x,hello,y}" values "1024,Hello%20World!,768",+            Test "{+path,x}/here" values "/foo/bar,1024/here",+            Test "{+path:6}/here" values "/foo/b/here",+            Test "{+list}" values "red,green,blue",+            Test "{+list*}" values "red,green,blue",+            Test "{+keys}" values "comma,,,dot,.,semi,;",+            Test "{+keys*}" values "comma=,,dot=.,semi=;",+            Test "{#var}" values "#value",+            Test "{#hello}" values "#Hello%20World!",+            Test "{#half}" values "#50%25",+            Test "foo{#empty}" values "foo#",+            Test "foo{#undef}" values "foo",+            Test "{#x,hello,y}" values "#1024,Hello%20World!,768",+            Test "{#path,x}/here" values "#/foo/bar,1024/here",+            Test "{#path:6}/here" values "#/foo/b/here",+            Test "{#list}" values "#red,green,blue",+            Test "{#list*}" values "#red,green,blue",+            Test "{#keys}" values "#comma,,,dot,.,semi,;",+            Test "{#keys*}" values "#comma=,,dot=.,semi=;",+            Test "{.who}" values ".fred",+            Test "{.who,who}" values ".fred.fred",+            Test "{.half,who}" values ".50%25.fred",+            Test "www{.dom*}" values "www.example.com",+            Test "X{.var}" values "X.value",+            Test "X{.empty}" values "X.",+            Test "X{.undef}" values "X",+            Test "X{.var:3}" values "X.val",+            Test "X{.list}" values "X.red,green,blue",+            Test "X{.list*}" values "X.red.green.blue",+            Test "X{.keys}" values "X.comma,%2C,dot,.,semi,%3B",+            Test "X{.keys*}" values "X.comma=%2C.dot=..semi=%3B",+            Test "X{.empty_keys}" values "X",+            Test "X{.empty_keys*}" values "X",+            Test "{/who}" values "/fred",+            Test "{/who,who}" values "/fred/fred",+            Test "{/half,who}" values "/50%25/fred",+            Test "{/who,dub}" values "/fred/me%2Ftoo",+            Test "{/var}" values "/value",+            Test "{/var,empty}" values "/value/",+            Test "{/var,undef}" values "/value",+            Test "{/var,x}/here" values "/value/1024/here",+            Test "{/var:1,var}" values "/v/value",+            Test "{/list}" values "/red,green,blue",+            Test "{/list*}" values "/red/green/blue",+            Test "{/list*,path:4}" values "/red/green/blue/%2Ffoo",+            Test "{/keys}" values "/comma,%2C,dot,.,semi,%3B",+            Test "{/keys*}" values "/comma=%2C/dot=./semi=%3B",+            Test "{;who}" values ";who=fred",+            Test "{;half}" values ";half=50%25",+            Test "{;empty}" values ";empty",+            Test "{;v,empty,who}" values ";v=6;empty;who=fred",+            Test "{;v,bar,who}" values ";v=6;who=fred",+            Test "{;x,y}" values ";x=1024;y=768",+            Test "{;x,y,empty}" values ";x=1024;y=768;empty",+            Test "{;x,y,undef}" values ";x=1024;y=768",+            Test "{;hello:5}" values ";hello=Hello",+            Test "{;list}" values ";list=red,green,blue",+            Test "{;list*}" values ";list=red;list=green;list=blue",+            Test "{;keys}" values ";keys=comma,%2C,dot,.,semi,%3B",+            Test "{;keys*}" values ";comma=%2C;dot=.;semi=%3B",+            Test "{?who}" values "?who=fred",+            Test "{?half}" values "?half=50%25",+            Test "{?x,y}" values "?x=1024&y=768",+            Test "{?x,y,empty}" values "?x=1024&y=768&empty=",+            Test "{?x,y,undef}" values "?x=1024&y=768",+            Test "{?var:3}" values "?var=val",+            Test "{?list}" values "?list=red,green,blue",+            Test "{?list*}" values "?list=red&list=green&list=blue",+            Test "{?keys}" values "?keys=comma,%2C,dot,.,semi,%3B",+            Test "{?keys*}" values "?comma=%2C&dot=.&semi=%3B",+            Test "{&who}" values "&who=fred",+            Test "{&half}" values "&half=50%25",+            Test "?fixed=yes{&x}" values "?fixed=yes&x=1024",+            Test "{&x,y,empty}" values "&x=1024&y=768&empty=",+            Test "{&x,y,undef}" values "&x=1024&y=768",+            Test "{&var:3}" values "&var=val",+            Test "{&list}" values "&list=red,green,blue",+            Test "{&list*}" values "&list=red&list=green&list=blue",+            Test "{&keys}" values "&keys=comma,%2C,dot,.,semi,%3B",+            Test "{&keys*}" values "&comma=%2C&dot=.&semi=%3B"+          ]+    ]++data Test = Test+  { testInput :: String,+    testValues :: [(String, Burrito.Value)],+    testOutput :: Output+  }+  deriving (Eq, Show)++runTest :: Test -> Hspec.Expectation+runTest test =+  case (Burrito.parse $ testInput test, unwrapOutput $ testOutput test) of+    (Nothing, Nothing) -> pure ()+    (Nothing, Just _) -> Hspec.expectationFailure "should have parsed"+    (Just _, Nothing) -> Hspec.expectationFailure "should not have parsed"+    (Just template, Just expected) -> do+      let values = testValues test+          actual = Burrito.expand values template+      actual `Hspec.shouldBe` expected+      Burrito.parse (show template) `Hspec.shouldBe` Just template+      let relevant =+            List.sort $ keepRelevant (templateVariables template) values+      Monad.when (isMatchable template relevant) $ do+        let matches = List.sort <$> Burrito.match expected template+        matches `Hspec.shouldSatisfy` elem relevant++isMatchable :: Template.Template -> [(String, Burrito.Value)] -> Bool+isMatchable template values =+  (not . any (isAsterisk . Variable.modifier) $ templateVariables template)+    && all (isString . snd) values++isString :: Burrito.Value -> Bool+isString value = case value of+  Value.String _ -> True+  _ -> False++isAsterisk :: Modifier.Modifier -> Bool+isAsterisk modifier = case modifier of+  Modifier.Asterisk -> True+  _ -> False++keepRelevant ::+  Set.Set Variable.Variable ->+  [(String, Burrito.Value)] ->+  [(String, Burrito.Value)]+keepRelevant variables =+  let vs =+        Map.fromListWith+          ( \mx my -> case (mx, my) of+              (Just x, Just y) -> Just $ max x y+              _ -> Nothing+          )+          . fmap+            ( \v ->+                ( Render.builderToString . Render.name $ Variable.name v,+                  case Variable.modifier v of+                    Modifier.Colon n -> Just $ MaxLength.count n+                    _ -> Nothing+                )+            )+          $ Set.toList variables+   in Maybe.mapMaybe $ \(k, v) -> do+        m <- Map.lookup k vs+        pure . (,) k $ case m of+          Nothing -> v+          Just n -> case v of+            Value.String t -> Value.String $ Text.take n t+            _ -> v++templateVariables :: Template.Template -> Set.Set Variable.Variable+templateVariables =+  Set.fromList+    . concatMap+      ( \token -> case token of+          Token.Expression expression ->+            NonEmpty.toList $ Expression.variables expression+          Token.Literal _ -> []+      )+    . Template.tokens++newtype Output = Output+  { unwrapOutput :: Maybe String+  }+  deriving (Eq, Show)++instance String.IsString Output where+  fromString = Output . Just++noParse :: Output+noParse = Output Nothing++(=:) :: a -> b -> (a, b)+(=:) = (,)++s :: String -> Burrito.Value+s = Burrito.stringValue++l :: [String] -> Burrito.Value+l = Burrito.listValue++d :: [(String, String)] -> Burrito.Value+d = Burrito.dictionaryValue++newtype Template = Template+  { unwrapTemplate :: Template.Template+  }+  deriving (Eq)++instance Show Template where+  show (Template template) =+    unwords [show $ show template, "{-", show (Template.tokens template), "-}"]++instance QC.Arbitrary Template where+  arbitrary = Template <$> arbitraryTemplate+  shrink = fmap Template . shrinkTemplate . unwrapTemplate++type Shrink a = a -> [a]++arbitraryTemplate :: QC.Gen Template.Template+arbitraryTemplate = Template.Template . simplify <$> QC.listOf arbitraryToken++shrinkTemplate :: Shrink Template.Template+shrinkTemplate =+  fmap (Template.Template . simplify)+    . QC.shrinkList shrinkToken+    . Template.tokens++simplify :: [Token.Token] -> [Token.Token]+simplify tokens = case tokens of+  t1 : t2 : ts -> case (t1, t2) of+    (Token.Literal l1, Token.Literal l2) ->+      simplify $ Token.Literal (appendLiteral l1 l2) : ts+    _ -> t1 : simplify (t2 : ts)+  _ -> tokens++appendLiteral :: Literal.Literal -> Literal.Literal -> Literal.Literal+appendLiteral x y =+  Literal.Literal $ Literal.characters x <> Literal.characters y++arbitraryToken :: QC.Gen Token.Token+arbitraryToken =+  QC.oneof+    [ Token.Expression <$> arbitraryExpression,+      Token.Literal <$> arbitraryLiteral+    ]++shrinkToken :: Shrink Token.Token+shrinkToken x = case x of+  Token.Expression y -> Token.Expression <$> shrinkExpression y+  Token.Literal y -> Token.Literal <$> shrinkLiteral y++arbitraryExpression :: QC.Gen Expression.Expression+arbitraryExpression =+  Expression.Expression+    <$> arbitraryOperator+    <*> arbitraryNonEmpty arbitraryVariable++shrinkExpression :: Shrink Expression.Expression+shrinkExpression x =+  uncurry Expression.Expression+    <$> shrinkTuple+      shrinkOperator+      (shrinkNonEmpty shrinkVariable)+      (Expression.operator x, Expression.variables x)++arbitraryOperator :: QC.Gen Operator.Operator+arbitraryOperator =+  QC.elements+    [ Operator.Ampersand,+      Operator.FullStop,+      Operator.None,+      Operator.NumberSign,+      Operator.PlusSign,+      Operator.QuestionMark,+      Operator.Semicolon,+      Operator.Solidus+    ]++shrinkOperator :: Shrink Operator.Operator+shrinkOperator x = case x of+  Operator.None -> []+  _ -> [Operator.None]++arbitraryNonEmpty :: QC.Gen a -> QC.Gen (NonEmpty.NonEmpty a)+arbitraryNonEmpty g = (NonEmpty.:|) <$> g <*> QC.listOf g++shrinkNonEmpty :: Shrink a -> Shrink (NonEmpty.NonEmpty a)+shrinkNonEmpty f x =+  uncurry (NonEmpty.:|)+    <$> shrinkTuple f (QC.shrinkList f) (NonEmpty.head x, NonEmpty.tail x)++arbitraryVariable :: QC.Gen Variable.Variable+arbitraryVariable = Variable.Variable <$> arbitraryName <*> arbitraryModifier++shrinkVariable :: Shrink Variable.Variable+shrinkVariable variable =+  uncurry Variable.Variable+    <$> shrinkTuple+      shrinkName+      shrinkModifier+      (Variable.name variable, Variable.modifier variable)++shrinkTuple :: Shrink a -> Shrink b -> Shrink (a, b)+shrinkTuple f g (x, y) =+  fmap (\a -> (a, y)) (f x) <> fmap (\b -> (x, b)) (g y)++arbitraryName :: QC.Gen Name.Name+arbitraryName = Name.Name <$> arbitraryNonEmpty arbitraryField++shrinkName :: Shrink Name.Name+shrinkName = fmap Name.Name . shrinkNonEmpty shrinkField . Name.fields++arbitraryField :: QC.Gen Field.Field+arbitraryField = Field.Field <$> arbitraryNonEmpty arbitraryFieldCharacter++shrinkField :: Shrink Field.Field+shrinkField =+  fmap Field.Field . shrinkNonEmpty shrinkFieldCharacter . Field.characters++arbitraryFieldCharacter :: QC.Gen (Character.Character Field.Field)+arbitraryFieldCharacter =+  QC.oneof+    [ Character.Encoded <$> arbitraryDigit <*> arbitraryDigit,+      Character.Unencoded <$> QC.suchThat QC.arbitrary Parse.isFieldCharacter+    ]++shrinkFieldCharacter :: Shrink (Character.Character Field.Field)+shrinkFieldCharacter x = case x of+  Character.Encoded y z ->+    uncurry Character.Encoded <$> shrinkTuple shrinkDigit shrinkDigit (y, z)+  Character.Unencoded y ->+    fmap Character.Unencoded . filter Parse.isFieldCharacter $ QC.shrink y++arbitraryDigit :: QC.Gen Digit.Digit+arbitraryDigit =+  QC.oneof+    [ pure Digit.Ox0,+      pure Digit.Ox1,+      pure Digit.Ox2,+      pure Digit.Ox3,+      pure Digit.Ox4,+      pure Digit.Ox5,+      pure Digit.Ox6,+      pure Digit.Ox7,+      pure Digit.Ox8,+      pure Digit.Ox9,+      Digit.OxA <$> arbitraryCase,+      Digit.OxB <$> arbitraryCase,+      Digit.OxC <$> arbitraryCase,+      Digit.OxD <$> arbitraryCase,+      Digit.OxE <$> arbitraryCase,+      Digit.OxF <$> arbitraryCase+    ]++shrinkDigit :: Shrink Digit.Digit+shrinkDigit x = case x of+  Digit.Ox0 -> []+  Digit.Ox1 -> [Digit.Ox0]+  Digit.Ox2 -> [Digit.Ox0]+  Digit.Ox3 -> [Digit.Ox0]+  Digit.Ox4 -> [Digit.Ox0]+  Digit.Ox5 -> [Digit.Ox0]+  Digit.Ox6 -> [Digit.Ox0]+  Digit.Ox7 -> [Digit.Ox0]+  Digit.Ox8 -> [Digit.Ox0]+  Digit.Ox9 -> [Digit.Ox0]+  Digit.OxA y -> Digit.Ox0 : fmap Digit.OxA (shrinkCase y)+  Digit.OxB y -> Digit.Ox0 : fmap Digit.OxA (shrinkCase y)+  Digit.OxC y -> Digit.Ox0 : fmap Digit.OxA (shrinkCase y)+  Digit.OxD y -> Digit.Ox0 : fmap Digit.OxA (shrinkCase y)+  Digit.OxE y -> Digit.Ox0 : fmap Digit.OxA (shrinkCase y)+  Digit.OxF y -> Digit.Ox0 : fmap Digit.OxA (shrinkCase y)++arbitraryCase :: QC.Gen Case.Case+arbitraryCase = QC.elements [Case.Lower, Case.Upper]++shrinkCase :: Shrink Case.Case+shrinkCase x = case x of+  Case.Lower -> []+  Case.Upper -> [Case.Lower]++arbitraryModifier :: QC.Gen Modifier.Modifier+arbitraryModifier =+  QC.oneof+    [ pure Modifier.Asterisk,+      Modifier.Colon <$> arbitraryMaxLength,+      pure Modifier.None+    ]++shrinkModifier :: Shrink Modifier.Modifier+shrinkModifier x = case x of+  Modifier.Asterisk -> [Modifier.None]+  Modifier.Colon y -> Modifier.None : fmap Modifier.Colon (shrinkMaxLength y)+  Modifier.None -> []++arbitraryMaxLength :: QC.Gen MaxLength.MaxLength+arbitraryMaxLength =+  MaxLength.MaxLength <$> QC.suchThat QC.arbitrary Parse.isMaxLength++shrinkMaxLength :: Shrink MaxLength.MaxLength+shrinkMaxLength =+  fmap MaxLength.MaxLength+    . filter Parse.isMaxLength+    . QC.shrink+    . MaxLength.count++arbitraryLiteral :: QC.Gen Literal.Literal+arbitraryLiteral =+  Literal.Literal <$> arbitraryNonEmpty arbitraryLiteralCharacter++shrinkLiteral :: Shrink Literal.Literal+shrinkLiteral =+  fmap Literal.Literal+    . shrinkNonEmpty shrinkLiteralCharacter+    . Literal.characters++arbitraryLiteralCharacter :: QC.Gen (Character.Character Literal.Literal)+arbitraryLiteralCharacter =+  QC.oneof+    [ Character.Encoded <$> arbitraryDigit <*> arbitraryDigit,+      Character.Unencoded <$> QC.suchThat QC.arbitrary Parse.isLiteralCharacter+    ]  shrinkLiteralCharacter :: Shrink (Character.Character Literal.Literal) shrinkLiteralCharacter x = case x of