module Network.PublicSuffixList.Serialize (getDataStructure, putDataStructure) where import Blaze.ByteString.Builder (Builder, fromWord8, toByteString) import Blaze.ByteString.Builder.Char.Utf8 (fromText) import qualified Data.ByteString as BS import Data.Foldable (foldMap) import Data.Map (Map) import qualified Data.Map as Map import Data.Monoid (mappend) import qualified Data.Text as T import qualified Data.Text.Encoding as TE import Network.PublicSuffixList.Types getTree :: BS.ByteString -> (Tree T.Text, BS.ByteString) getTree :: ByteString -> (Tree Text, ByteString) getTree = Map Text (Tree Text) -> ByteString -> (Tree Text, ByteString) loop forall k a. Map k a Map.empty where loop :: Map Text (Tree Text) -> ByteString -> (Tree Text, ByteString) loop Map Text (Tree Text) m ByteString bs | ByteString -> Bool BS.null ByteString bs = (forall e. Map e (Tree e) -> Tree e Node Map Text (Tree Text) m, ByteString bs) | HasCallStack => ByteString -> Word8 BS.head ByteString bs forall a. Eq a => a -> a -> Bool == Word8 0 = (forall e. Map e (Tree e) -> Tree e Node Map Text (Tree Text) m, Int -> ByteString -> ByteString BS.drop Int 1 ByteString bs) | Bool otherwise = let (Text k, Tree Text v, ByteString bs') = ByteString -> (Text, Tree Text, ByteString) getPair ByteString bs in Map Text (Tree Text) -> ByteString -> (Tree Text, ByteString) loop (forall k a. Ord k => k -> a -> Map k a -> Map k a Map.insert Text k Tree Text v Map Text (Tree Text) m) ByteString bs' getPair :: BS.ByteString -> (T.Text, Tree T.Text, BS.ByteString) getPair :: ByteString -> (Text, Tree Text, ByteString) getPair ByteString bs0 = (Text k, Tree Text v, ByteString bs2) where (Text k, ByteString bs1) = ByteString -> (Text, ByteString) getText ByteString bs0 (Tree Text v, ByteString bs2) = ByteString -> (Tree Text, ByteString) getTree ByteString bs1 getText :: BS.ByteString -> (T.Text, BS.ByteString) getText :: ByteString -> (Text, ByteString) getText ByteString bs0 = (ByteString -> Text TE.decodeUtf8 ByteString v, Int -> ByteString -> ByteString BS.drop Int 1 ByteString bs1) where (ByteString v, ByteString bs1) = (Word8 -> Bool) -> ByteString -> (ByteString, ByteString) BS.break (forall a. Eq a => a -> a -> Bool == Word8 0) ByteString bs0 getDataStructure :: BS.ByteString -> DataStructure getDataStructure :: ByteString -> DataStructure getDataStructure ByteString bs0 = (Tree Text x, Tree Text y) where (Tree Text x, ByteString bs1) = ByteString -> (Tree Text, ByteString) getTree ByteString bs0 (Tree Text y, ByteString _) = ByteString -> (Tree Text, ByteString) getTree ByteString bs1 putTree :: Tree T.Text -> Builder putTree :: Tree Text -> Builder putTree = Map Text (Tree Text) -> Builder putMap forall b c a. (b -> c) -> (a -> b) -> a -> c . forall e. Tree e -> Map e (Tree e) children putMap :: Map T.Text (Tree T.Text) -> Builder putMap :: Map Text (Tree Text) -> Builder putMap Map Text (Tree Text) m = forall (t :: * -> *) m a. (Foldable t, Monoid m) => (a -> m) -> t a -> m Data.Foldable.foldMap (Text, Tree Text) -> Builder putPair (forall k a. Map k a -> [(k, a)] Map.toList Map Text (Tree Text) m) forall a. Monoid a => a -> a -> a `mappend` Word8 -> Builder fromWord8 Word8 0 putPair :: (T.Text, Tree T.Text) -> Builder putPair :: (Text, Tree Text) -> Builder putPair (Text x, Tree Text y) = Text -> Builder putText Text x forall a. Monoid a => a -> a -> a `mappend` Tree Text -> Builder putTree Tree Text y putText :: T.Text -> Builder putText :: Text -> Builder putText Text t = Text -> Builder fromText Text t forall a. Monoid a => a -> a -> a `Data.Monoid.mappend` Word8 -> Builder fromWord8 Word8 0 putDataStructure :: DataStructure -> BS.ByteString putDataStructure :: DataStructure -> ByteString putDataStructure (Tree Text x, Tree Text y) = Builder -> ByteString toByteString forall a b. (a -> b) -> a -> b $ Tree Text -> Builder putTree Tree Text x forall a. Monoid a => a -> a -> a `mappend` Tree Text -> Builder putTree Tree Text y