module Text.ValveVKV.Class where
import Text.ValveVKV.Internal
import Control.Monad (forM)
import Data.Maybe (mapMaybe)
import GHC.Base (NonEmpty)
import Data.List.NonEmpty (NonEmpty, nonEmpty)
findFromName :: ValveKeyValueEntry -> String -> [ValveKeyValueEntry]
findFromName :: ValveKeyValueEntry -> String -> [ValveKeyValueEntry]
findFromName (KVObject (Pair String
_ [ValveKeyValueEntry]
stuff)) String
name =
(ValveKeyValueEntry -> Maybe ValveKeyValueEntry)
-> [ValveKeyValueEntry] -> [ValveKeyValueEntry]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe ValveKeyValueEntry -> Maybe ValveKeyValueEntry
finder [ValveKeyValueEntry]
stuff
where
finder :: ValveKeyValueEntry -> Maybe ValveKeyValueEntry
finder :: ValveKeyValueEntry -> Maybe ValveKeyValueEntry
finder this :: ValveKeyValueEntry
this@(KVObject (Pair String
thisname [ValveKeyValueEntry]
s)) = if String
thisname String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
name then ValveKeyValueEntry -> Maybe ValveKeyValueEntry
forall a. a -> Maybe a
Just ValveKeyValueEntry
this else Maybe ValveKeyValueEntry
forall a. Maybe a
Nothing
finder this :: ValveKeyValueEntry
this@(KVString (Pair String
thisname String
s)) = if String
thisname String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
name then ValveKeyValueEntry -> Maybe ValveKeyValueEntry
forall a. a -> Maybe a
Just ValveKeyValueEntry
this else Maybe ValveKeyValueEntry
forall a. Maybe a
Nothing
finder this :: ValveKeyValueEntry
this@(KVInt (Pair String
thisname Int
s)) = if String
thisname String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
name then ValveKeyValueEntry -> Maybe ValveKeyValueEntry
forall a. a -> Maybe a
Just ValveKeyValueEntry
this else Maybe ValveKeyValueEntry
forall a. Maybe a
Nothing
findFromName ValveKeyValueEntry
_ String
_ = []
(.:) :: ValveVKV a => ValveKeyValueEntry -> String -> Either String a
ValveKeyValueEntry
context .: :: ValveKeyValueEntry -> String -> Either String a
.: String
name =
let results :: [ValveKeyValueEntry]
results = ValveKeyValueEntry -> String -> [ValveKeyValueEntry]
findFromName ValveKeyValueEntry
context String
name in
case [ValveKeyValueEntry]
results of
[] -> String -> Either String a
forall a b. a -> Either a b
Left (String -> Either String a) -> String -> Either String a
forall a b. (a -> b) -> a -> b
$ String
"No items with name " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name
ValveKeyValueEntry
x:[ValveKeyValueEntry]
_ -> ValveKeyValueEntry -> ValveKeyValueEntry -> Either String a
forall a.
ValveVKV a =>
ValveKeyValueEntry -> ValveKeyValueEntry -> Either String a
fromValveVKV ValveKeyValueEntry
x ValveKeyValueEntry
context
infixl 5 .:
(^:) :: ValveKeyValueEntry -> String -> Maybe String
ValveKeyValueEntry
context ^: :: ValveKeyValueEntry -> String -> Maybe String
^: String
name =
let results :: [ValveKeyValueEntry]
results = ValveKeyValueEntry -> String -> [ValveKeyValueEntry]
findFromName ValveKeyValueEntry
context String
name in
case [ValveKeyValueEntry]
results of
(KVString (Pair String
_ String
s)):[ValveKeyValueEntry]
_ -> String -> Maybe String
forall a. a -> Maybe a
Just String
s
[ValveKeyValueEntry]
_ -> Maybe String
forall a. Maybe a
Nothing
infixl 5 ^:
type Context = ValveKeyValueEntry
class ValveVKV a where
fromValveVKV :: ValveKeyValueEntry -> Context -> Either String a
instance ValveVKV Int where
fromValveVKV :: ValveKeyValueEntry -> ValveKeyValueEntry -> Either String Int
fromValveVKV (KVInt (Pair String
_ Int
num)) ValveKeyValueEntry
_ = Int -> Either String Int
forall a b. b -> Either a b
Right Int
num
fromValveVKV (KVString (Pair String
name String
x)) ValveKeyValueEntry
_ = String -> Either String Int
forall a b. a -> Either a b
Left (String -> Either String Int) -> String -> Either String Int
forall a b. (a -> b) -> a -> b
$ String
"No int called " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" found. We did find a string with value " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
x
fromValveVKV (KVObject (Pair String
name [ValveKeyValueEntry]
_)) ValveKeyValueEntry
_ = String -> Either String Int
forall a b. a -> Either a b
Left (String -> Either String Int) -> String -> Either String Int
forall a b. (a -> b) -> a -> b
$ String
"No int called " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" found. We did find an object named " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name
instance ValveVKV a => ValveVKV (Maybe a) where
fromValveVKV :: ValveKeyValueEntry -> ValveKeyValueEntry -> Either String (Maybe a)
fromValveVKV ValveKeyValueEntry
entry ValveKeyValueEntry
con = ValveKeyValueEntry -> ValveKeyValueEntry -> Either String (Maybe a)
forall a.
ValveVKV a =>
ValveKeyValueEntry -> ValveKeyValueEntry -> Either String a
fromValveVKV ValveKeyValueEntry
entry ValveKeyValueEntry
con
instance ValveVKV Bool where
fromValveVKV :: ValveKeyValueEntry -> ValveKeyValueEntry -> Either String Bool
fromValveVKV (KVInt (Pair String
_ Int
0)) ValveKeyValueEntry
_ = Bool -> Either String Bool
forall a b. b -> Either a b
Right Bool
False
fromValveVKV (KVInt (Pair String
_ Int
1)) ValveKeyValueEntry
_ = Bool -> Either String Bool
forall a b. b -> Either a b
Right Bool
True
fromValveVKV (KVInt (Pair String
_ Int
x)) ValveKeyValueEntry
_ = String -> Either String Bool
forall a b. a -> Either a b
Left (String -> Either String Bool) -> String -> Either String Bool
forall a b. (a -> b) -> a -> b
$ String
"Could not parse int " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" as a boolean"
fromValveVKV ValveKeyValueEntry
_ ValveKeyValueEntry
_ = String -> Either String Bool
forall a b. a -> Either a b
Left String
"Could not parse as a boolean"
instance ValveVKV a => ValveVKV [a] where
fromValveVKV :: ValveKeyValueEntry -> ValveKeyValueEntry -> Either String [a]
fromValveVKV (KVString (Pair String
name String
_)) ValveKeyValueEntry
context =
(ValveKeyValueEntry -> Either String a)
-> [ValveKeyValueEntry] -> Either String [a]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (ValveKeyValueEntry -> ValveKeyValueEntry -> Either String a
forall a.
ValveVKV a =>
ValveKeyValueEntry -> ValveKeyValueEntry -> Either String a
`fromValveVKV` ValveKeyValueEntry
context) (ValveKeyValueEntry -> String -> [ValveKeyValueEntry]
findFromName ValveKeyValueEntry
context String
name)
fromValveVKV (KVObject (Pair String
name [ValveKeyValueEntry]
_)) ValveKeyValueEntry
context =
(ValveKeyValueEntry -> Either String a)
-> [ValveKeyValueEntry] -> Either String [a]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (ValveKeyValueEntry -> ValveKeyValueEntry -> Either String a
forall a.
ValveVKV a =>
ValveKeyValueEntry -> ValveKeyValueEntry -> Either String a
`fromValveVKV` ValveKeyValueEntry
context) (ValveKeyValueEntry -> String -> [ValveKeyValueEntry]
findFromName ValveKeyValueEntry
context String
name)
fromValveVKV (KVInt (Pair String
name Int
_)) ValveKeyValueEntry
context =
(ValveKeyValueEntry -> Either String a)
-> [ValveKeyValueEntry] -> Either String [a]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (ValveKeyValueEntry -> ValveKeyValueEntry -> Either String a
forall a.
ValveVKV a =>
ValveKeyValueEntry -> ValveKeyValueEntry -> Either String a
`fromValveVKV` ValveKeyValueEntry
context) (ValveKeyValueEntry -> String -> [ValveKeyValueEntry]
findFromName ValveKeyValueEntry
context String
name)
instance ValveVKV a => ValveVKV (NonEmpty a) where
fromValveVKV :: ValveKeyValueEntry
-> ValveKeyValueEntry -> Either String (NonEmpty a)
fromValveVKV ValveKeyValueEntry
entry ValveKeyValueEntry
context =
Either String [a]
forall a. ValveVKV a => Either String [a]
list Either String [a]
-> ([a] -> Either String (NonEmpty a))
-> Either String (NonEmpty a)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \[a]
xs ->
case [a] -> Maybe (NonEmpty a)
forall a. [a] -> Maybe (NonEmpty a)
nonEmpty [a]
xs of
Just NonEmpty a
x -> NonEmpty a -> Either String (NonEmpty a)
forall a b. b -> Either a b
Right NonEmpty a
x
Maybe (NonEmpty a)
Nothing -> String -> Either String (NonEmpty a)
forall a b. a -> Either a b
Left String
"List was empty"
where
list :: ValveVKV a => Either String [a]
list :: Either String [a]
list = ValveKeyValueEntry -> ValveKeyValueEntry -> Either String [a]
forall a.
ValveVKV a =>
ValveKeyValueEntry -> ValveKeyValueEntry -> Either String a
fromValveVKV ValveKeyValueEntry
entry ValveKeyValueEntry
context