2020-12-30 23:29:56 +02:00
|
|
|
{-# LANGUAGE DataKinds #-}
|
|
|
|
{-# LANGUAGE TypeFamilies #-}
|
|
|
|
module Data.Buuka
|
|
|
|
( BuukaQ(..)
|
|
|
|
, BuukaU(..)
|
|
|
|
, BuukaEntry(..)
|
|
|
|
, URL(..)
|
2020-12-31 08:51:37 +02:00
|
|
|
, Buuka
|
2020-12-30 23:29:56 +02:00
|
|
|
|
|
|
|
, insert
|
2021-01-01 08:29:24 +02:00
|
|
|
, elements
|
2021-01-01 09:04:48 +02:00
|
|
|
, fingerprint
|
2020-12-30 23:29:56 +02:00
|
|
|
)
|
|
|
|
where
|
|
|
|
|
|
|
|
import Database.Migrations
|
|
|
|
|
|
|
|
import Data.Aeson
|
2021-01-01 09:04:48 +02:00
|
|
|
import Data.Bits
|
|
|
|
(finiteBitSize, shiftR, (.&.))
|
|
|
|
import Data.Hashable
|
|
|
|
(Hashable, hash)
|
2020-12-30 23:29:56 +02:00
|
|
|
import GHC.Generics
|
|
|
|
(Generic)
|
|
|
|
|
2021-01-03 08:33:44 +02:00
|
|
|
import Data.Text
|
|
|
|
|
2020-12-30 23:29:56 +02:00
|
|
|
import Control.Monad.Reader
|
|
|
|
import Control.Monad.State
|
|
|
|
|
2021-01-01 09:04:48 +02:00
|
|
|
import Data.ByteString
|
|
|
|
(ByteString)
|
|
|
|
import qualified Data.ByteString as B
|
|
|
|
|
2021-01-03 08:33:44 +02:00
|
|
|
newtype URL = URL Text
|
2020-12-30 23:29:56 +02:00
|
|
|
deriving stock (Show, Eq, Generic, Ord)
|
2021-01-01 09:04:48 +02:00
|
|
|
deriving newtype (ToJSON, FromJSON, FromJSONKey, ToJSONKey, Hashable)
|
2020-12-30 23:29:56 +02:00
|
|
|
|
|
|
|
data BuukaEntry
|
|
|
|
= BuukaEntry { url :: URL
|
2021-01-03 08:33:44 +02:00
|
|
|
, title :: Maybe Text
|
2020-12-30 23:29:56 +02:00
|
|
|
}
|
|
|
|
deriving stock (Show, Eq, Generic)
|
2021-01-01 09:04:48 +02:00
|
|
|
deriving anyclass (ToJSON, FromJSON, Hashable)
|
2020-12-30 23:29:56 +02:00
|
|
|
|
|
|
|
instance SafeJSON BuukaEntry where
|
|
|
|
type Version BuukaEntry = 0
|
|
|
|
|
2021-01-01 07:55:10 +02:00
|
|
|
newtype Buuka = Buuka [BuukaEntry]
|
2020-12-31 08:51:37 +02:00
|
|
|
deriving stock (Show, Eq)
|
2021-01-01 09:04:48 +02:00
|
|
|
deriving newtype (Semigroup, Monoid, FromJSON, ToJSON, Hashable)
|
2020-12-30 23:29:56 +02:00
|
|
|
|
|
|
|
insert :: BuukaEntry -> Buuka -> Buuka
|
2021-01-01 07:55:10 +02:00
|
|
|
insert e (Buuka b) = Buuka (e : b)
|
2020-12-30 23:29:56 +02:00
|
|
|
|
2021-01-01 08:29:24 +02:00
|
|
|
elements :: Buuka -> [BuukaEntry]
|
|
|
|
elements (Buuka b) = b
|
|
|
|
|
2021-01-01 09:04:48 +02:00
|
|
|
-- | Create a (non-cryptographic) hash out of the 'Buuka'
|
|
|
|
fingerprint :: Buuka -> ByteString
|
|
|
|
fingerprint = toBS . hash
|
|
|
|
where
|
|
|
|
toBS x =
|
|
|
|
let bs = finiteBitSize x
|
|
|
|
in B.pack [fromIntegral ((x `shiftR` s) .&. 255) | s <- [0..bs - 1]]
|
|
|
|
|
2020-12-30 23:29:56 +02:00
|
|
|
instance SafeJSON Buuka where
|
|
|
|
type Version Buuka = 0
|
|
|
|
|
|
|
|
newtype BuukaQ a = BuukaQ { runBuukaQ :: Reader Buuka a }
|
|
|
|
deriving newtype (Functor, Applicative, Monad, MonadReader Buuka)
|
|
|
|
|
|
|
|
-- Last write wins
|
|
|
|
newtype BuukaU a = BuukaU { runBuukaU :: State Buuka a }
|
|
|
|
deriving newtype (Functor, Applicative, Monad, MonadState Buuka)
|