cardano-crypto-1.3.0: src/Crypto/Encoding/BIP39/Dictionary.hs
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE OverloadedStrings #-}
module Crypto.Encoding.BIP39.Dictionary
( -- ** Dictionary
Dictionary(..)
, WordIndex
, wordIndex
, unWordIndex
, DictionaryError(..)
) where
import Basement.NormalForm
import Basement.Compat.Typeable
import Basement.Types.OffsetSize (Offset(..))
import Basement.From (TryFrom(..))
import Basement.Imports
-- | this discribe the property of the Dictionary and will alllow to
-- convert from a mnemonic phrase to 'MnemonicSentence'
--
-- This is especially needed to build the BIP39 'Seed'
--
data Dictionary = Dictionary
{ dictionaryIndexToWord :: WordIndex -> String
-- ^ This function will retrieve the mnemonic word associated to the
-- given 'WordIndex'.
, dictionaryWordToIndex :: String -> Either DictionaryError WordIndex
-- ^ This function will retrieve the 'WordIndex' from a given mnemonic
-- word.
, dictionaryTestWord :: String -> Bool
-- ^ test a given word is in the dictionary
, dictionaryWordSeparator :: String
-- ^ joining string (e.g. space for english)
}
deriving (Typeable)
-- | Index of the mnemonic word in the 'Dictionary'
--
-- 'WordIndex' are within range of [0..2047]
--
newtype WordIndex = WordIndex { unWordIndex :: Offset String }
deriving (Show, Eq, Ord, Typeable, NormalForm)
instance Enum WordIndex where
toEnum = wordIndex . toEnum
fromEnum = fromEnum . unWordIndex
succ (WordIndex (Offset v))
| v < 2047 = WordIndex (Offset (succ v))
| otherwise = error "WordIndex out of bound"
pred (WordIndex (Offset v))
| v <= 0 = error "WordIndex out of bound"
| otherwise = WordIndex (Offset (pred v))
instance Bounded WordIndex where
minBound = WordIndex (Offset 0)
maxBound = WordIndex (Offset 2047)
instance TryFrom (Offset String) WordIndex where
tryFrom w
| w < 2048 = Just (WordIndex w)
| otherwise = Nothing
instance TryFrom Int WordIndex where
tryFrom v
| v >= 0 = tryFrom (Offset v :: Offset String)
| otherwise = Nothing
wordIndex :: Offset String -> WordIndex
wordIndex w = case tryFrom w of
Nothing -> error ("Error: word index should be between 0 to 2047. " <> show w)
Just wi -> wi
-- -------------------------------------------------------------------------- --
-- Errors
-- -------------------------------------------------------------------------- --
data DictionaryError
= ErrInvalidDictionaryWord String
deriving (Show)