keystore-0.1.0.0: src/Data/KeyStore/Opt.hs
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE OverloadedStrings #-}
module Data.KeyStore.Opt
( Opt
, getSettingsOpt
, setSettingsOpt
, opt__debug_enabled
, opt__verify_enabled
, opt__backup_keys
, opt__hash_comment
, opt__hash_prf
, opt__hash_iterations
, opt__hash_width_octets
, opt__hash_salt_octets
, opt__crypt_cipher
, opt__crypt_prf
, opt__crypt_iterations
, opt__crypt_salt_octets
, Opt_(..)
, opt_
) where
import Data.KeyStore.Types
import Data.Aeson
import qualified Data.Vector as V
import qualified Data.Map as Map
import qualified Data.HashMap.Strict as HM
import Data.Attoparsec.Number
import qualified Data.Text as T
import Data.Maybe
import Data.Char
data Opt a
= Opt
{ opt_enum :: OptEnum
, opt_default :: a
, opt_from :: Value -> a
, opt_to :: a -> Value
}
getSettingsOpt :: Opt a -> Settings -> a
getSettingsOpt Opt{..} (Settings hm) =
maybe opt_default opt_from $ HM.lookup (opt_name opt_enum) hm
setSettingsOpt :: Opt a -> a -> Settings -> Settings
setSettingsOpt Opt{..} x (Settings hm) =
Settings $ HM.insert (opt_name opt_enum) (opt_to x) hm
opt__debug_enabled :: Opt Bool
opt__debug_enabled = bool_opt False Debug__enabled
opt__verify_enabled :: Opt Bool
opt__verify_enabled = bool_opt False Verify__enabled
opt__backup_keys :: Opt [Name]
opt__backup_keys = backup_opt Backup__keys
opt__hash_comment :: Opt Comment
opt__hash_comment = text_opt (Comment ,_Comment) "" Hash__comment
opt__hash_prf :: Opt HashPRF
opt__hash_prf = enum_opt _text_HashPRF PRF_sha512 Hash__prf
opt__hash_iterations :: Opt Iterations
opt__hash_iterations = intg_opt (Iterations,_Iterations) 5000 Hash__iterations
opt__hash_width_octets :: Opt Octets
opt__hash_width_octets = intg_opt (Octets ,_Octets ) 64 Hash__width_octets
opt__hash_salt_octets :: Opt Octets
opt__hash_salt_octets = intg_opt (Octets ,_Octets ) 16 Hash__salt_octets
opt__crypt_cipher :: Opt Cipher
opt__crypt_cipher = enum_opt _text_Cipher CPH_aes256 Crypt__cipher
opt__crypt_prf :: Opt HashPRF
opt__crypt_prf = enum_opt _text_HashPRF PRF_sha512 Crypt__prf
opt__crypt_iterations :: Opt Iterations
opt__crypt_iterations = intg_opt (Iterations,_Iterations) 5000 Crypt__iterations
opt__crypt_salt_octets :: Opt Octets
opt__crypt_salt_octets = intg_opt (Octets ,_Octets ) 16 Crypt__salt_octets
data OptEnum
= Debug__enabled
| Verify__enabled
| Backup__keys
| Hash__comment
| Hash__prf
| Hash__iterations
| Hash__width_octets
| Hash__salt_octets
| Crypt__cipher
| Crypt__prf
| Crypt__iterations
| Crypt__salt_octets
deriving (Bounded,Enum,Eq,Ord,Show)
data Opt_ = forall a. Opt_ (Opt a)
opt_ :: OptEnum -> Opt_
opt_ enm =
case enm of
Debug__enabled -> Opt_ $ opt__debug_enabled
Verify__enabled -> Opt_ $ opt__verify_enabled
Backup__keys -> Opt_ $ opt__backup_keys
Hash__comment -> Opt_ $ opt__hash_comment
Hash__prf -> Opt_ $ opt__hash_prf
Hash__iterations -> Opt_ $ opt__hash_iterations
Hash__width_octets -> Opt_ $ opt__hash_width_octets
Hash__salt_octets -> Opt_ $ opt__hash_salt_octets
Crypt__cipher -> Opt_ $ opt__crypt_cipher
Crypt__prf -> Opt_ $ opt__crypt_prf
Crypt__iterations -> Opt_ $ opt__crypt_iterations
Crypt__salt_octets -> Opt_ $ opt__crypt_salt_octets
opt_name :: OptEnum -> T.Text
opt_name opt = T.pack $ map toLower grp ++ "." ++ drop 2 __nme
where
(grp,__nme) = splitAt (f (-1) ' ' so) so
where
f i _ [] = i+1
f i '_' ('_':_) = i
f i _ (h:t) = f (i+1) h t
so = show opt
backup_opt :: OptEnum -> Opt [Name]
backup_opt ce =
Opt
{ opt_enum = ce
, opt_default = []
, opt_from = frm
, opt_to = Array . V.fromList . map (String . T.pack . _name)
}
where
frm val =
case val of
Array v -> catMaybes $ map extr $ V.toList v
_ -> []
extr val =
case val of
String t | Right nm <- name $ T.unpack t -> Just nm
_ -> Nothing
bool_opt :: Bool -> OptEnum -> Opt Bool
bool_opt x0 ce =
Opt
{ opt_enum = ce
, opt_default = x0
, opt_from = frm
, opt_to = Bool
}
where
frm v =
case v of
Bool b -> b
_ -> x0
intg_opt :: (Int->a,a->Int) -> a -> OptEnum -> Opt a
intg_opt (inj,prj) x0 ce =
Opt
{ opt_enum = ce
, opt_default = x0
, opt_from = frm
, opt_to = Number . I . toInteger . prj
}
where
frm v =
case v of
Number (I i) -> inj $ fromInteger i
_ -> x0
text_opt :: (T.Text->a,a->T.Text) -> a -> OptEnum -> Opt a
text_opt (inj,prj) x0 ce =
Opt
{ opt_enum = ce
, opt_default = x0
, opt_from = frm
, opt_to = String . prj
}
where
frm v =
case v of
String t -> inj t
_ -> x0
enum_opt :: (Bounded a,Enum a) => (a->T.Text) -> a -> OptEnum -> Opt a
enum_opt shw x0 ce =
Opt
{ opt_enum = ce
, opt_default = x0
, opt_from = frm
, opt_to = String . shw
}
where
frm v =
case v of
String s | Just x <- Map.lookup s mp -> x
_ -> x0
mp = Map.fromList [ (shw v,v) | v<-[minBound..maxBound] ]