{- |
Ini data essentially consists of 'String's, that cannot contain every character
because of the simple format it is contained in. The types in this module are
restricted to contain only allowed characters. They also can not be empty or
start or end with whitespace. Values of these types can not be created with
data constructors. Use the @mk*@ functions instead!
-}

module Trivialini.SafeTypes
  (
    -- * Safe 'String' types
    IniHeading(getHeading), IniKey(getKey), IniValue(getValue)
      -- (No data constructors!)
    -- ** Value creation
  , mkHdg, mkKey, mkVal
    -- ** Validity predicates
  , isValidHeading, isValidKey, isValidValue
    -- ** Invalid character lists (useful for parsers)
  , invalidHdgChars, invalidKeyChars, invalidValChars
    -- ** Utility predicate
  , isValidStr
  ) where

import Data.Bool
import Data.Char
import Data.String
import Data.Maybe
import Control.Applicative

-- Utility function
guarded :: Alternative m => (a -> Bool) -> a -> m a
guarded :: forall (m :: * -> *) a. Alternative m => (a -> Bool) -> a -> m a
guarded = (m a -> Bool -> m a) -> (a -> m a) -> (a -> Bool) -> a -> m a
forall a b c. (a -> b -> c) -> (a -> a) -> (a -> b) -> a -> c
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 (m a -> m a -> Bool -> m a
forall a. a -> a -> Bool -> a
bool m a
forall a. m a
forall (f :: * -> *) a. Alternative f => f a
empty) a -> m a
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure

-- | A section heading
newtype IniHeading  = Hdg { IniHeading -> String
getHeading  :: String } deriving (IniHeading -> IniHeading -> Bool
(IniHeading -> IniHeading -> Bool)
-> (IniHeading -> IniHeading -> Bool) -> Eq IniHeading
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: IniHeading -> IniHeading -> Bool
== :: IniHeading -> IniHeading -> Bool
$c/= :: IniHeading -> IniHeading -> Bool
/= :: IniHeading -> IniHeading -> Bool
Eq, Eq IniHeading
Eq IniHeading
-> (IniHeading -> IniHeading -> Ordering)
-> (IniHeading -> IniHeading -> Bool)
-> (IniHeading -> IniHeading -> Bool)
-> (IniHeading -> IniHeading -> Bool)
-> (IniHeading -> IniHeading -> Bool)
-> (IniHeading -> IniHeading -> IniHeading)
-> (IniHeading -> IniHeading -> IniHeading)
-> Ord IniHeading
IniHeading -> IniHeading -> Bool
IniHeading -> IniHeading -> Ordering
IniHeading -> IniHeading -> IniHeading
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: IniHeading -> IniHeading -> Ordering
compare :: IniHeading -> IniHeading -> Ordering
$c< :: IniHeading -> IniHeading -> Bool
< :: IniHeading -> IniHeading -> Bool
$c<= :: IniHeading -> IniHeading -> Bool
<= :: IniHeading -> IniHeading -> Bool
$c> :: IniHeading -> IniHeading -> Bool
> :: IniHeading -> IniHeading -> Bool
$c>= :: IniHeading -> IniHeading -> Bool
>= :: IniHeading -> IniHeading -> Bool
$cmax :: IniHeading -> IniHeading -> IniHeading
max :: IniHeading -> IniHeading -> IniHeading
$cmin :: IniHeading -> IniHeading -> IniHeading
min :: IniHeading -> IniHeading -> IniHeading
Ord)
-- | A key of a key-value pair
newtype IniKey      = Key { IniKey -> String
getKey      :: String } deriving (IniKey -> IniKey -> Bool
(IniKey -> IniKey -> Bool)
-> (IniKey -> IniKey -> Bool) -> Eq IniKey
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: IniKey -> IniKey -> Bool
== :: IniKey -> IniKey -> Bool
$c/= :: IniKey -> IniKey -> Bool
/= :: IniKey -> IniKey -> Bool
Eq, Eq IniKey
Eq IniKey
-> (IniKey -> IniKey -> Ordering)
-> (IniKey -> IniKey -> Bool)
-> (IniKey -> IniKey -> Bool)
-> (IniKey -> IniKey -> Bool)
-> (IniKey -> IniKey -> Bool)
-> (IniKey -> IniKey -> IniKey)
-> (IniKey -> IniKey -> IniKey)
-> Ord IniKey
IniKey -> IniKey -> Bool
IniKey -> IniKey -> Ordering
IniKey -> IniKey -> IniKey
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: IniKey -> IniKey -> Ordering
compare :: IniKey -> IniKey -> Ordering
$c< :: IniKey -> IniKey -> Bool
< :: IniKey -> IniKey -> Bool
$c<= :: IniKey -> IniKey -> Bool
<= :: IniKey -> IniKey -> Bool
$c> :: IniKey -> IniKey -> Bool
> :: IniKey -> IniKey -> Bool
$c>= :: IniKey -> IniKey -> Bool
>= :: IniKey -> IniKey -> Bool
$cmax :: IniKey -> IniKey -> IniKey
max :: IniKey -> IniKey -> IniKey
$cmin :: IniKey -> IniKey -> IniKey
min :: IniKey -> IniKey -> IniKey
Ord)
-- | A value of a key-value pair
newtype IniValue    = Val { IniValue -> String
getValue    :: String } deriving (IniValue -> IniValue -> Bool
(IniValue -> IniValue -> Bool)
-> (IniValue -> IniValue -> Bool) -> Eq IniValue
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: IniValue -> IniValue -> Bool
== :: IniValue -> IniValue -> Bool
$c/= :: IniValue -> IniValue -> Bool
/= :: IniValue -> IniValue -> Bool
Eq, Eq IniValue
Eq IniValue
-> (IniValue -> IniValue -> Ordering)
-> (IniValue -> IniValue -> Bool)
-> (IniValue -> IniValue -> Bool)
-> (IniValue -> IniValue -> Bool)
-> (IniValue -> IniValue -> Bool)
-> (IniValue -> IniValue -> IniValue)
-> (IniValue -> IniValue -> IniValue)
-> Ord IniValue
IniValue -> IniValue -> Bool
IniValue -> IniValue -> Ordering
IniValue -> IniValue -> IniValue
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: IniValue -> IniValue -> Ordering
compare :: IniValue -> IniValue -> Ordering
$c< :: IniValue -> IniValue -> Bool
< :: IniValue -> IniValue -> Bool
$c<= :: IniValue -> IniValue -> Bool
<= :: IniValue -> IniValue -> Bool
$c> :: IniValue -> IniValue -> Bool
> :: IniValue -> IniValue -> Bool
$c>= :: IniValue -> IniValue -> Bool
>= :: IniValue -> IniValue -> Bool
$cmax :: IniValue -> IniValue -> IniValue
max :: IniValue -> IniValue -> IniValue
$cmin :: IniValue -> IniValue -> IniValue
min :: IniValue -> IniValue -> IniValue
Ord)

invalidHdgChars :: String
invalidKeyChars :: String
invalidValChars :: String
invalidHdgChars :: String
invalidHdgChars = String
"=]\n"
invalidKeyChars :: String
invalidKeyChars = String
"=[\n"
invalidValChars :: String
invalidValChars = String
"\n"

isValidHeading  :: String -> Bool
isValidKey      :: String -> Bool
isValidValue    :: String -> Bool
isValidHeading :: String -> Bool
isValidHeading  = (Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` String
invalidHdgChars) (String -> Bool) -> (String -> Bool) -> String -> Bool
forall a. (a -> Bool) -> (a -> Bool) -> a -> Bool
&&& String -> Bool
isValidStr
isValidKey :: String -> Bool
isValidKey      = (Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` String
invalidKeyChars) (String -> Bool) -> (String -> Bool) -> String -> Bool
forall a. (a -> Bool) -> (a -> Bool) -> a -> Bool
&&& String -> Bool
isValidStr
isValidValue :: String -> Bool
isValidValue    = (Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` String
invalidValChars) (String -> Bool) -> (String -> Bool) -> String -> Bool
forall a. (a -> Bool) -> (a -> Bool) -> a -> Bool
&&& String -> Bool
isValidStr

isValidStr :: String -> Bool
isValidStr :: String -> Bool
isValidStr =  (Bool -> Bool
not (Bool -> Bool) -> (String -> Bool) -> String -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null)
          (String -> Bool) -> (String -> Bool) -> String -> Bool
forall a. (a -> Bool) -> (a -> Bool) -> a -> Bool
&&& (Bool -> Bool
not (Bool -> Bool) -> (String -> Bool) -> String -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Char -> Bool
isControl)
          (String -> Bool) -> (String -> Bool) -> String -> Bool
forall a. (a -> Bool) -> (a -> Bool) -> a -> Bool
&&& (Bool -> Bool
not (Bool -> Bool) -> (String -> Bool) -> String -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Bool
isSpace (Char -> Bool) -> (String -> Char) -> String -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Char
forall a. HasCallStack => [a] -> a
head)
          (String -> Bool) -> (String -> Bool) -> String -> Bool
forall a. (a -> Bool) -> (a -> Bool) -> a -> Bool
&&& (Bool -> Bool
not (Bool -> Bool) -> (String -> Bool) -> String -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Bool
isSpace (Char -> Bool) -> (String -> Char) -> String -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Char
forall a. HasCallStack => [a] -> a
last)

(&&&) :: (a -> Bool) -> (a -> Bool) -> a -> Bool
&&& :: forall a. (a -> Bool) -> (a -> Bool) -> a -> Bool
(&&&) = (Bool -> Bool -> Bool) -> (a -> Bool) -> (a -> Bool) -> a -> Bool
forall a b c. (a -> b -> c) -> (a -> a) -> (a -> b) -> a -> c
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 Bool -> Bool -> Bool
(&&)

mkHdg :: String -> Maybe IniHeading
mkKey :: String -> Maybe IniKey
mkVal :: String -> Maybe IniValue
mkHdg :: String -> Maybe IniHeading
mkHdg = (String -> IniHeading) -> Maybe String -> Maybe IniHeading
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap String -> IniHeading
Hdg (Maybe String -> Maybe IniHeading)
-> (String -> Maybe String) -> String -> Maybe IniHeading
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> Bool) -> String -> Maybe String
forall (m :: * -> *) a. Alternative m => (a -> Bool) -> a -> m a
guarded String -> Bool
isValidHeading
mkKey :: String -> Maybe IniKey
mkKey = (String -> IniKey) -> Maybe String -> Maybe IniKey
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap String -> IniKey
Key (Maybe String -> Maybe IniKey)
-> (String -> Maybe String) -> String -> Maybe IniKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> Bool) -> String -> Maybe String
forall (m :: * -> *) a. Alternative m => (a -> Bool) -> a -> m a
guarded String -> Bool
isValidKey
mkVal :: String -> Maybe IniValue
mkVal = (String -> IniValue) -> Maybe String -> Maybe IniValue
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap String -> IniValue
Val (Maybe String -> Maybe IniValue)
-> (String -> Maybe String) -> String -> Maybe IniValue
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> Bool) -> String -> Maybe String
forall (m :: * -> *) a. Alternative m => (a -> Bool) -> a -> m a
guarded String -> Bool
isValidValue

instance Show IniHeading  where show :: IniHeading -> String
show = IniHeading -> String
getHeading
instance Show IniKey      where show :: IniKey -> String
show = IniKey -> String
getKey
instance Show IniValue    where show :: IniValue -> String
show = IniValue -> String
getValue

instance IsString IniHeading where
  fromString :: String -> IniHeading
fromString = IniHeading -> Maybe IniHeading -> IniHeading
forall a. a -> Maybe a -> a
fromMaybe (IniHeading -> Maybe IniHeading -> IniHeading)
-> (String -> IniHeading)
-> String
-> Maybe IniHeading
-> IniHeading
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IniHeading
forall a. HasCallStack => String -> a
error (String -> IniHeading)
-> (String -> String) -> String -> IniHeading
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
"Not a heading: " String -> String -> String
forall a. [a] -> [a] -> [a]
++) (String -> Maybe IniHeading -> IniHeading)
-> (String -> Maybe IniHeading) -> String -> IniHeading
forall a b. (String -> a -> b) -> (String -> a) -> String -> b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> String -> Maybe IniHeading
mkHdg
instance IsString IniKey where
  fromString :: String -> IniKey
fromString = IniKey -> Maybe IniKey -> IniKey
forall a. a -> Maybe a -> a
fromMaybe (IniKey -> Maybe IniKey -> IniKey)
-> (String -> IniKey) -> String -> Maybe IniKey -> IniKey
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IniKey
forall a. HasCallStack => String -> a
error (String -> IniKey) -> (String -> String) -> String -> IniKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
"Not a key: " String -> String -> String
forall a. [a] -> [a] -> [a]
++) (String -> Maybe IniKey -> IniKey)
-> (String -> Maybe IniKey) -> String -> IniKey
forall a b. (String -> a -> b) -> (String -> a) -> String -> b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> String -> Maybe IniKey
mkKey
instance IsString IniValue where
  fromString :: String -> IniValue
fromString = IniValue -> Maybe IniValue -> IniValue
forall a. a -> Maybe a -> a
fromMaybe (IniValue -> Maybe IniValue -> IniValue)
-> (String -> IniValue) -> String -> Maybe IniValue -> IniValue
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IniValue
forall a. HasCallStack => String -> a
error (String -> IniValue) -> (String -> String) -> String -> IniValue
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
"Not a value: " String -> String -> String
forall a. [a] -> [a] -> [a]
++) (String -> Maybe IniValue -> IniValue)
-> (String -> Maybe IniValue) -> String -> IniValue
forall a b. (String -> a -> b) -> (String -> a) -> String -> b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> String -> Maybe IniValue
mkVal