53 lines
1.3 KiB
Haskell
53 lines
1.3 KiB
Haskell
{-# LANGUAGE OverloadedStrings #-}
|
|
|
|
module RangeQuery where
|
|
|
|
import Control.Applicative
|
|
import Network.HTTP.Types.Header
|
|
|
|
import Data.Ranged.Boundaries
|
|
import Data.Ranged.Ranges
|
|
|
|
import qualified Data.ByteString.Char8 as BS
|
|
import Text.Regex.TDFA ((=~))
|
|
import Text.Read (readMaybe)
|
|
|
|
import Data.Maybe (fromMaybe, listToMaybe)
|
|
|
|
type NonnegRange = Range Int
|
|
|
|
rangeGeq :: Int -> NonnegRange
|
|
rangeGeq n =
|
|
Range (BoundaryBelow n) BoundaryAboveAll
|
|
|
|
rangeLeq :: Int -> NonnegRange
|
|
rangeLeq n =
|
|
Range BoundaryBelowAll (BoundaryAbove n)
|
|
|
|
parseRange :: String -> Maybe NonnegRange
|
|
parseRange range = do
|
|
let rangeRegex = "^([0-9]+)-([0-9]*)$" :: String
|
|
|
|
parsedRange <- listToMaybe (range =~ rangeRegex :: [[String]])
|
|
|
|
let [_, from, to] = readMaybe <$> parsedRange
|
|
let lower = fromMaybe emptyRange (rangeGeq <$> from)
|
|
let upper = fromMaybe (rangeGeq 0) (rangeLeq <$> to)
|
|
|
|
return $ rangeIntersection lower upper
|
|
|
|
requestedRange :: RequestHeaders -> Maybe NonnegRange
|
|
requestedRange hdrs = parseRange =<< BS.unpack <$> lookup hRange hdrs
|
|
|
|
limit :: NonnegRange -> Maybe Int
|
|
limit range =
|
|
case [rangeLower range, rangeUpper range]
|
|
of [BoundaryBelow from, BoundaryAbove to] -> Just (1 + to - from)
|
|
_ -> Nothing
|
|
|
|
offset :: NonnegRange -> Int
|
|
offset range =
|
|
case rangeLower range
|
|
of BoundaryBelow from -> from
|
|
_ -> 0 -- should never happen
|