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 Map Text (Tree Text) 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 = (Map Text (Tree Text) -> Tree Text forall e. Map e (Tree e) -> Tree e Node Map Text (Tree Text) m, ByteString bs) | ByteString -> Word8 BS.head ByteString bs Word8 -> Word8 -> Bool forall a. Eq a => a -> a -> Bool == Word8 0 = (Map Text (Tree Text) -> Tree Text 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 (Text -> Tree Text -> Map Text (Tree Text) -> Map Text (Tree Text) 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 (Word8 -> Word8 -> Bool 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 (Map Text (Tree Text) -> Builder) -> (Tree Text -> Map Text (Tree Text)) -> Tree Text -> Builder forall b c a. (b -> c) -> (a -> b) -> a -> c . Tree Text -> Map Text (Tree Text) 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 = ((Text, Tree Text) -> Builder) -> [(Text, Tree Text)] -> Builder forall (t :: * -> *) m a. (Foldable t, Monoid m) => (a -> m) -> t a -> m Data.Foldable.foldMap (Text, Tree Text) -> Builder putPair (Map Text (Tree Text) -> [(Text, Tree Text)] forall k a. Map k a -> [(k, a)] Map.toList Map Text (Tree Text) m) Builder -> Builder -> Builder 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 Builder -> Builder -> Builder 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 Builder -> Builder -> Builder 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 (Builder -> ByteString) -> Builder -> ByteString forall a b. (a -> b) -> a -> b $ Tree Text -> Builder putTree Tree Text x Builder -> Builder -> Builder forall a. Monoid a => a -> a -> a `mappend` Tree Text -> Builder putTree Tree Text y