diff --git a/gibberish.cabal b/gibberish.cabal index 95275ac..796d4a2 100644 --- a/gibberish.cabal +++ b/gibberish.cabal @@ -98,6 +98,7 @@ library Data.Elocrypt.Trigraph, Data.Elocrypt.Utils, Data.Gibberish.Format, + Data.Gibberish.GenPass, Data.Gibberish.GenTrigraph, Data.Gibberish.MonadPass, Data.Gibberish.Types diff --git a/src/Data/Gibberish/Format.hs b/src/Data/Gibberish/Format.hs index da9e577..3229f20 100644 --- a/src/Data/Gibberish/Format.hs +++ b/src/Data/Gibberish/Format.hs @@ -4,11 +4,12 @@ module Data.Gibberish.Format MaxHeight (..), Separator (..), ExactNumberWords (..), - Word (..), formatWords, formatLine, ) where +import Data.Gibberish.Types + import Data.List (intersperse) import Data.Text (Text ()) import Data.Text qualified as Text @@ -37,9 +38,6 @@ newtype ExactNumberWords = ExactNumberWords {unExactWords :: Int} deriving stock (Eq, Show) deriving newtype (Enum, Integral, Num, Ord, Real) -newtype Word = Word {unWord :: Text} - deriving stock (Eq, Show) - newtype FormatText = FormatText {fmtLines :: [FormatLine]} deriving stock (Eq, Show) diff --git a/src/Data/Gibberish/MonadPass.hs b/src/Data/Gibberish/MonadPass.hs index 8d37d4d..0da12be 100644 --- a/src/Data/Gibberish/MonadPass.hs +++ b/src/Data/Gibberish/MonadPass.hs @@ -1,36 +1,57 @@ module Data.Gibberish.MonadPass - ( PassT (..), + ( Pass (), + PassT (..), + runPass, + evalPass, + usingPass, runPassT, evalPassT, usingPassT, ) where -import Data.Gibberish.Types (GenPassOptions ()) - import Control.Monad.Random.Class (MonadRandom ()) -import Control.Monad.Reader (MonadReader (), ReaderT (), runReaderT) -import Control.Monad.Trans.Random (RandT (), runRandT) +import Control.Monad.Trans.Random (RandT (), evalRandT, runRandT) +import Data.Functor.Identity (Identity (..)) + +-- | Password/Passphrase generation monad parameterized by the type @gen@ of the generator +-- to carry +type Pass gen = PassT gen Identity + +-- | Run a generation computation with the given options and initial generator +runPass :: Pass gen a -> gen -> (a, gen) +runPass action = runIdentity . runPassT action + +-- | Evaluate a generation computation with the given options and initial +-- generator, discarding the final generator +evalPass :: Pass gen a -> gen -> a +evalPass action = runIdentity . evalPassT action + +-- | Shorter and more readable alias for @flip runPassT@. +usingPass :: gen -> Pass gen a -> (a, gen) +usingPass = flip runPass --- | Password/Passphrase generation monad -newtype PassT g m a = PassT {unPass :: ReaderT GenPassOptions (RandT g m) a} +-- | Password/Passphrase generation transformer monad parameterized by : +-- +-- * @gen@ - the generator. +-- * @m@ - the inner monad. +newtype PassT gen m a = PassT {unPass :: RandT gen m a} deriving newtype ( Applicative, Functor, Monad, MonadFail, - MonadRandom, - MonadReader GenPassOptions + MonadRandom ) -- | Run a generation computation with the given options and initial generator -runPassT :: PassT g m a -> GenPassOptions -> g -> m (a, g) -runPassT act = runRandT . runReaderT (unPass act) +runPassT :: PassT g m a -> g -> m (a, g) +runPassT = runRandT . unPass -- | Evaluate a generation computation with the given options and initial -- generator, discarding the final generator -evalPassT :: Functor m => PassT g m a -> GenPassOptions -> g -> m a -evalPassT act opts gen = fst <$> runPassT act opts gen +evalPassT :: Monad m => PassT g m a -> g -> m a +evalPassT = evalRandT . unPass --- | Like @runGenT@, but the computation is the last argument -usingPassT :: GenPassOptions -> g -> PassT g m a -> m (a, g) -usingPassT opts gen act = runPassT act opts gen +-- | Shorter and more readable alias for @flip runPassT@. +usingPassT :: g -> PassT g m a -> m (a, g) +usingPassT = flip runPassT diff --git a/src/Data/Gibberish/Types.hs b/src/Data/Gibberish/Types.hs index 66d6834..4234e85 100644 --- a/src/Data/Gibberish/Types.hs +++ b/src/Data/Gibberish/Types.hs @@ -8,6 +8,7 @@ module Data.Gibberish.Types Frequency (..), Frequencies (..), Trigraph (..), + Word (..), ) where import Control.DeepSeq (NFData) @@ -18,15 +19,18 @@ import Data.Map (Map ()) import Data.Text (Text ()) import GHC.Generics (Generic ()) import TextShow (TextShow (..), fromString) +import Prelude hiding (Word ()) -- | Password/Passphrase generation options data GenPassOptions = GenPassOptions { -- | Include capitals? - genCapitals :: !Bool, + optsCapitals :: !Bool, -- | Include numerals? - genDigits :: !Bool, + optsDigits :: !Bool, -- | Include special characters? - genSpecials :: !Bool + optsSpecials :: !Bool, + -- | The trigraph to use + optsTrigraph :: Trigraph } deriving stock (Eq, Show) @@ -62,6 +66,10 @@ newtype Trigraph = Trigraph {unTrigraph :: Map Digram Frequencies} deriving stock (Eq, Show) deriving newtype (FromJSON, ToJSON, NFData) +-- | A natural language word +newtype Word = Word {unWord :: Text} + deriving stock (Eq, Show) + instance TextShow Digram where showb (Digram c1 c2) = fromString [c1, c2]