module Network.PublicSuffixList.Create (PublicSuffixListException, sink) where
import Control.Exception
import qualified Data.ByteString as BS
import qualified Data.Conduit as C
import qualified Data.Conduit.List as CL
import qualified Data.Conduit.Text as CT
import Data.Default
import qualified Data.Map as M
import qualified Data.Text as T
import Data.Typeable
import Text.IDNA
import Network.PublicSuffixList.Internal.Types
data PublicSuffixListException = PublicSuffixListException
deriving (Show, Typeable)
instance Exception PublicSuffixListException
insert :: (Ord e) => Tree e -> [e] -> Tree e
insert _ [] = def
insert t (p : ps) = case M.lookup p $ children t of
Nothing -> t { children = M.insert p (insert def ps) $ children t }
Just l -> t { children = M.insert p (insert l ps) $ children t }
foldingFunction :: DataStructure -> T.Text -> DataStructure
foldingFunction d@(rules, exceptions) s'
| T.null s = d
| T.take 2 s == "//" = d
| T.head s == '!' = (rules, insert exceptions $ labelList $ T.tail s)
| otherwise = (insert rules $ labelList s, exceptions)
where ss = filter (not . T.null) $ T.words s'
s
| null ss = ""
| otherwise = head ss
labelList = reverse . map internationalize . T.split (== '.')
internationalize str
| str == "*" = str
| otherwise = case toASCII False True $ T.toLower str of
Just x -> x
Nothing -> throw PublicSuffixListException
sink :: C.MonadThrow m => C.GSink BS.ByteString m DataStructure
sink = CT.decode CT.utf8 C.>+> CT.lines C.>+> CL.fold foldingFunction def