Skip to content

Instantly share code, notes, and snippets.

@abc-mikey
Created November 1, 2020 11:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save abc-mikey/b9c73c5cc5d2065d7a68b28939ac27b4 to your computer and use it in GitHub Desktop.
Save abc-mikey/b9c73c5cc5d2065d7a68b28939ac27b4 to your computer and use it in GitHub Desktop.
{-# LANGUAGE FlexibleContexts #-}
module NetStrings where
import Data.Char (ord)
import Control.Monad (forever)
import Control.Monad.Except
import Data.Either.Utils
netstring :: String -> Either String (String, String)
netstring xs = netstring' 0 xs -- size body
where
netstring' _ [] = Left "unexpected end of stream"
netstring' c _
| c > 4096 = Left "message size too large"
netstring' c (x:xs)
| x >= '0' && x <= '9' = netstring' (c * 10 + (ord x - ord '0')) xs
| x /= ':' = Left "missing colon"
| x == ':' = consume c (take c xs) (drop c xs)
consume c _ [] = Left "unexpected end of stream"
consume c msg (x:xs)
| length msg /= c = Left "unexpected end of stream"
| x /= ',' = Left "missing comma"
| x == ',' = Right (msg, xs)
netstrings :: (MonadError String m) => String -> m [String]
netstrings xs = do
(msg, xs) <- eitherToMonadError $ netstring xs
if null xs
then return [msg]
else do
rest <- netstrings xs
return (msg:rest)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment