module Codec.Container.Ogg.MessageHeaders (
MessageHeaders(..),
mhEmpty,
mhSingleton,
mhInsert,
mhAppend
) where
import Data.Char
import Data.List as List
import qualified Data.Map as Map
data MessageHeaders =
MessageHeaders {
mhHeaders :: Map.Map String [String]
}
mhEmpty :: MessageHeaders
mhEmpty = MessageHeaders (Map.empty)
mhSingleton :: String -> String -> MessageHeaders
mhSingleton f v = MessageHeaders (Map.singleton f [v])
mhInsert :: String -> String -> MessageHeaders -> MessageHeaders
mhInsert k v (MessageHeaders h) = MessageHeaders (Map.insert k [v] h)
mhAppend :: String -> String -> MessageHeaders -> MessageHeaders
mhAppend k v mhdrs = mhAppends k [v] mhdrs
mhAppends :: String -> [String] -> MessageHeaders -> MessageHeaders
mhAppends k vs (MessageHeaders h) = MessageHeaders (Map.insertWith (++) k vs h)
instance Read MessageHeaders where
readsPrec _ = readMH mhEmpty
readMH :: MessageHeaders -> ReadS MessageHeaders
readMH mhdrs s = readMHlines mhdrs (lines s)
readMHlines :: MessageHeaders -> [String] -> [(MessageHeaders, String)]
readMHlines mhdrs [] = [(mhdrs, "")]
readMHlines mhdrs ("":body) = [(mhdrs, unlines body)]
readMHlines mhdrs (l:rest) = readMHlines mhdrs' rest
where
mhdrs' = mhAppends k vs mhdrs
(k, ':':vs'csv) = break (':' ==) l
vs' = split ',' vs'csv
vs = filter (not . null) $ map (filter isHTTPTokenChar) vs'
split :: Char -> String -> [String]
split = unfoldr . split'
split' :: Char -> String -> Maybe (String, String)
split' c l
| null l = Nothing
| otherwise = Just (h, drop 1 t)
where (h, t) = span (/=c) l
isHTTPCTL :: Char -> Bool
isHTTPCTL c = (ord c <= 31) || (ord c) == 127
isHTTPSeparator :: Char -> Bool
isHTTPSeparator = flip elem ['(' , ')' , '<' , '>' , '@'
, ',' , ';' , ':' , '\\' , '\"'
, '/' , '[' , ']' , '?' , '='
, '{' , '}' , ' ', '\t']
isHTTPTokenChar :: Char -> Bool
isHTTPTokenChar c = not (isHTTPCTL c || isHTTPSeparator c)
instance Show MessageHeaders where
show (MessageHeaders h) =
concat $ List.map serializeMH (Map.assocs h)
where
serializeMH :: (String, [String]) -> String
serializeMH (k, v) = k ++ ": " ++ (concat $ intersperse ", " v) ++ "\r\n"