implemented decodeGemURL

This commit is contained in:
Jonathan Lamothe 2021-10-24 22:04:56 -04:00
parent a5d0c25fc3
commit 00142e91d6
2 changed files with 90 additions and 1 deletions

View File

@ -24,10 +24,11 @@ License along with this program. If not, see
-} -}
{-# LANGUAGE LambdaCase #-} {-# LANGUAGE LambdaCase, OverloadedStrings, RecordWildCards #-}
module Network.GemServ ( module Network.GemServ (
encodeGemURL, encodeGemURL,
decodeGemURL,
escapeString, escapeString,
unescapeString unescapeString
) where ) where
@ -56,6 +57,49 @@ encodeGemURL url =
Nothing -> "" Nothing -> ""
Just q -> '?' : escapeString q Just q -> '?' : escapeString q
-- | Decodes a 'GemURL' from a 'String' (if possible)
decodeGemURL :: String -> Maybe GemURL
decodeGemURL str = do
let txt = T.pack str
noProt <- case T.splitOn "://" txt of
[prot, rest] -> if T.toLower prot == "gemini"
then Just rest
else Nothing
_ -> Nothing
noFrag <- case T.splitOn "#" noProt of
[x, _] -> Just x
[x] -> Just x
_ -> Nothing
(noQuery, query) <- case T.splitOn "?" noFrag of
[nq, q] -> Just (nq, Just q)
[nq] -> Just (nq, Nothing)
_ -> Nothing
gemQuery <- case query of
Just q -> Just <$> unescapeString (T.unpack q)
Nothing -> Just Nothing
(auth, path) <- case T.splitOn "/" noQuery of
[a] -> Just (a, [])
[a, ""] -> Just (a, [])
a:ps -> Just (a, ps)
_ -> Nothing
gemPath <- mapM (unescapeString . T.unpack) path
(host, gemPort) <- case T.splitOn ":" auth of
[h, p] -> case reads $ T.unpack p of
[(n, "")] -> Just (h, Just n)
_ -> Nothing
[h] -> Just (h, Nothing)
_ -> Nothing
let gemHost = T.unpack host
Just GemURL {..}
-- | add required escape sequences to a string -- | add required escape sequences to a string
escapeString :: String -> String escapeString :: String -> String
escapeString = concatMap escapeString = concatMap

View File

@ -30,6 +30,7 @@ import Network.GemServ.Types
spec :: Spec spec :: Spec
spec = describe "Network.GemServ" $ do spec = describe "Network.GemServ" $ do
encodeGemURLSpec encodeGemURLSpec
decodeGemURLSpec
escapeStringSpec escapeStringSpec
unescapeStringSpec unescapeStringSpec
@ -68,6 +69,50 @@ encodeGemURLSpec = describe "encodeGemURL" $ mapM_
withEscapeExp = "gemini://example.com/foo%20bar?baz%20quux" withEscapeExp = "gemini://example.com/foo%20bar?baz%20quux"
decodeGemURLSpec :: Spec
decodeGemURLSpec = describe "decodeGemURL" $ mapM_
( \(str, expected) -> context (show str) $
it ("should be " ++ show expected) $
decodeGemURL str `shouldBe` expected
)
-- URL string, expected
[ ( simpleStr, Just simpleURL )
, ( withSlashStr, Just simpleURL )
, ( withPathStr, Just withPathURL )
, ( withQueryStr, Just withQueryURL )
, ( pathQueryStr, Just pathQueryURL )
, ( blankQueryStr, Just blankQueryURL )
, ( withFragmentStr, Just simpleURL )
, ( escapedStr, Just escapedURL )
, ( httpStr, Nothing )
, ( malformed, Nothing )
, ( "", Nothing )
]
where
simpleStr = "gemini://example.com"
simpleURL = newGemURL "example.com"
withSlashStr = simpleStr ++ "/"
withPathStr = simpleStr ++ "/foo/bar"
withPathURL = simpleURL { gemPath = ["foo", "bar"] }
withQueryStr = simpleStr ++ "?foo"
withQueryURL = simpleURL { gemQuery = Just "foo" }
pathQueryStr = withPathStr ++ "?baz"
pathQueryURL = withPathURL { gemQuery = Just "baz" }
blankQueryStr = simpleStr ++"?"
blankQueryURL = simpleURL { gemQuery = Just "" }
withFragmentStr = simpleStr ++ "#foo"
escapedStr = simpleStr ++ "/foo%20bar/baz?quux%20stuff"
escapedURL = simpleURL
{ gemPath = ["foo bar", "baz"]
, gemQuery = Just "quux stuff"
}
httpStr = "http://example.com"
malformed = "foo"
escapeStringSpec :: Spec escapeStringSpec :: Spec
escapeStringSpec = describe "escapeString" $ mapM_ escapeStringSpec = describe "escapeString" $ mapM_
( \(input, expected) -> context (show input) $ ( \(input, expected) -> context (show input) $