buuka/src/Data/Buuka.hs

100 lines
2.2 KiB
Haskell
Raw Normal View History

2021-01-03 09:52:38 +02:00
{-# LANGUAGE TemplateHaskell #-}
2020-12-30 23:29:56 +02:00
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeFamilies #-}
module Data.Buuka
( BuukaQ(..)
, BuukaU(..)
, BuukaEntry(..)
2021-01-03 09:52:38 +02:00
, url
, title
2020-12-30 23:29:56 +02:00
, URL(..)
2021-01-03 09:52:38 +02:00
, _URL
2020-12-31 08:51:37 +02:00
, Buuka
2021-01-03 09:52:38 +02:00
, _Buuka
2020-12-30 23:29:56 +02:00
, insert
2021-01-01 08:29:24 +02:00
, elements
, fingerprint
2020-12-30 23:29:56 +02:00
)
where
2021-01-03 09:52:38 +02:00
import Control.Lens (makeLenses, Iso', iso)
2020-12-30 23:29:56 +02:00
import Database.Migrations
import Data.Aeson
import Data.Bits
(finiteBitSize, shiftR, (.&.))
import Data.Hashable
(Hashable, hash)
2020-12-30 23:29:56 +02:00
import GHC.Generics
(Generic)
2021-10-27 20:46:23 +03:00
import Data.Text (Text)
2021-01-03 08:33:44 +02:00
2020-12-30 23:29:56 +02:00
import Control.Monad.Reader
import Control.Monad.State
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)
deriving newtype (ToJSON, FromJSON, FromJSONKey, ToJSONKey, Hashable)
2020-12-30 23:29:56 +02:00
2021-01-03 09:52:38 +02:00
_URL :: Iso' URL Text
_URL = iso (\(URL t) -> t) URL
2020-12-30 23:29:56 +02:00
data BuukaEntry
2021-01-03 09:52:38 +02:00
= BuukaEntry { _url :: URL
, _title :: Maybe Text
2020-12-30 23:29:56 +02:00
}
deriving stock (Show, Eq, Generic)
2021-10-27 20:46:23 +03:00
deriving anyclass (Hashable)
opts :: Options
opts = defaultOptions { fieldLabelModifier = dropWhile (== '_'), omitNothingFields = True }
instance ToJSON BuukaEntry where
toJSON = genericToJSON opts
instance FromJSON BuukaEntry where
parseJSON = genericParseJSON opts
2020-12-30 23:29:56 +02:00
2021-01-03 09:52:38 +02:00
makeLenses ''BuukaEntry
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)
deriving newtype (Semigroup, Monoid, FromJSON, ToJSON, Hashable)
2020-12-30 23:29:56 +02:00
2021-01-03 09:52:38 +02:00
_Buuka :: Iso' Buuka [BuukaEntry]
_Buuka = iso (\(Buuka b) -> b) Buuka
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
-- | 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)