module Network.Web.Server.Range (skipAndSize) where
import Control.Applicative hiding (many,optional,(<|>))
import Text.Parsec
import Text.Parsec.String
skipAndSize :: String -> Integer -> Maybe (Integer,Integer)
skipAndSize str size = case parseRange str of
Just [(mbeg,mend)] -> adjust mbeg mend size
_ -> Nothing
adjust :: Maybe Integer -> Maybe Integer -> Integer -> Maybe (Integer,Integer)
adjust (Just beg) (Just end) siz
| beg <= end && end <= siz = Just (beg, end beg + 1)
| otherwise = Nothing
adjust (Just beg) Nothing siz
| beg <= siz = Just (beg, siz beg)
| otherwise = Nothing
adjust Nothing (Just end) siz
| end <= siz = Just (siz end, end)
| otherwise = Nothing
adjust Nothing Nothing _ = Nothing
type Range = (Maybe Integer, Maybe Integer)
parseRange :: String -> Maybe [Range]
parseRange xs = case parse byteRange "" xs of
Left _ -> Nothing
Right x -> Just x
byteRange :: Parser [Range]
byteRange = string "bytes=" *> (ranges <* eof)
ranges :: Parser [Range]
ranges = sepBy1 (range <|> suffixRange) (spaces >> char ',' >> spaces)
range :: Parser Range
range = (,) <$> ((Just <$> num) <* char '-')
<*> option Nothing (Just <$> num)
suffixRange :: Parser Range
suffixRange = (,) Nothing <$> (char '-' *> (Just <$> num))
num :: Parser Integer
num = read <$> many1 digit