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