module Data.API.Utils
    ( simpleParseVersion
    , (?!)
    , (?!?)
      -- * Utils for merging and diffing maps
    , MergeResult(..)
    , mergeMaps
    , diffMaps
    , matchMaps
    ) where

import           Data.Map ( Map )
import qualified Data.Map                       as Map
import           Data.Version
import qualified Text.ParserCombinators.ReadP as ReadP

simpleParseVersion :: String -> Maybe Version
simpleParseVersion :: String -> Maybe Version
simpleParseVersion String
s = case forall a. (a -> Bool) -> [a] -> [a]
filter (forall (t :: * -> *) a. Foldable t => t a -> Bool
null forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd) (forall a. ReadP a -> ReadS a
ReadP.readP_to_S ReadP Version
parseVersion String
s) of
  [(Version
v,String
_)] -> forall a. a -> Maybe a
Just Version
v
  [(Version, String)]
_       -> forall a. Maybe a
Nothing


-- | The \"oh noes!\" operator.
--
(?!) :: Maybe a -> e -> Either e a
Maybe a
Nothing ?! :: forall a e. Maybe a -> e -> Either e a
?! e
e = forall a b. a -> Either a b
Left  e
e
Just a
x  ?! e
_ = forall a b. b -> Either a b
Right a
x

(?!?) :: Either e a -> (e -> e') -> Either e' a
Left  e
e ?!? :: forall e a e'. Either e a -> (e -> e') -> Either e' a
?!? e -> e'
f = forall a b. a -> Either a b
Left  (e -> e'
f e
e)
Right a
x ?!? e -> e'
_ = forall a b. b -> Either a b
Right a
x


-------------------------------------
-- Utils for merging and diffing maps
--

data MergeResult a b = OnlyInLeft a | InBoth a b | OnlyInRight b
  deriving (MergeResult a b -> MergeResult a b -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall a b.
(Eq a, Eq b) =>
MergeResult a b -> MergeResult a b -> Bool
/= :: MergeResult a b -> MergeResult a b -> Bool
$c/= :: forall a b.
(Eq a, Eq b) =>
MergeResult a b -> MergeResult a b -> Bool
== :: MergeResult a b -> MergeResult a b -> Bool
$c== :: forall a b.
(Eq a, Eq b) =>
MergeResult a b -> MergeResult a b -> Bool
Eq, Int -> MergeResult a b -> ShowS
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall a b. (Show a, Show b) => Int -> MergeResult a b -> ShowS
forall a b. (Show a, Show b) => [MergeResult a b] -> ShowS
forall a b. (Show a, Show b) => MergeResult a b -> String
showList :: [MergeResult a b] -> ShowS
$cshowList :: forall a b. (Show a, Show b) => [MergeResult a b] -> ShowS
show :: MergeResult a b -> String
$cshow :: forall a b. (Show a, Show b) => MergeResult a b -> String
showsPrec :: Int -> MergeResult a b -> ShowS
$cshowsPrec :: forall a b. (Show a, Show b) => Int -> MergeResult a b -> ShowS
Show)

mergeMaps :: Ord k => Map k a -> Map k b -> Map k (MergeResult a b)
mergeMaps :: forall k a b.
Ord k =>
Map k a -> Map k b -> Map k (MergeResult a b)
mergeMaps Map k a
m1 Map k b
m2 = forall k a. Ord k => (a -> a -> a) -> Map k a -> Map k a -> Map k a
Map.unionWith (\(OnlyInLeft a
a) (OnlyInRight b
b) -> forall a b. a -> b -> MergeResult a b
InBoth a
a b
b)
                      (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. a -> MergeResult a b
OnlyInLeft Map k a
m1) (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. b -> MergeResult a b
OnlyInRight Map k b
m2)

diffMaps :: (Eq a, Ord k) => Map k a -> Map k a -> Map k (MergeResult a a)
diffMaps :: forall a k.
(Eq a, Ord k) =>
Map k a -> Map k a -> Map k (MergeResult a a)
diffMaps Map k a
m1 Map k a
m2 = forall a k. (a -> Bool) -> Map k a -> Map k a
Map.filter forall {a}. Eq a => MergeResult a a -> Bool
different forall a b. (a -> b) -> a -> b
$ forall k a b.
Ord k =>
Map k a -> Map k b -> Map k (MergeResult a b)
mergeMaps Map k a
m1 Map k a
m2
  where
    different :: MergeResult a a -> Bool
different (InBoth a
a a
b) = a
a forall a. Eq a => a -> a -> Bool
/= a
b
    different MergeResult a a
_            = Bool
True

-- | Attempts to match the keys of the maps to produce a map from keys
-- to pairs.
matchMaps :: Ord k => Map k a -> Map k b -> Either (k, Either a b) (Map k (a, b))
matchMaps :: forall k a b.
Ord k =>
Map k a -> Map k b -> Either (k, Either a b) (Map k (a, b))
matchMaps Map k a
m1 Map k b
m2 = forall (t :: * -> *) k a b.
Applicative t =>
(k -> a -> t b) -> Map k a -> t (Map k b)
Map.traverseWithKey forall {a} {a} {b}.
a -> MergeResult a b -> Either (a, Either a b) (a, b)
win forall a b. (a -> b) -> a -> b
$ forall k a b.
Ord k =>
Map k a -> Map k b -> Map k (MergeResult a b)
mergeMaps Map k a
m1 Map k b
m2
  where
    win :: a -> MergeResult a b -> Either (a, Either a b) (a, b)
win a
_ (InBoth a
x b
y)    = forall (m :: * -> *) a. Monad m => a -> m a
return (a
x, b
y)
    win a
k (OnlyInLeft a
x)  = forall a b. a -> Either a b
Left (a
k, forall a b. a -> Either a b
Left a
x)
    win a
k (OnlyInRight b
x) = forall a b. a -> Either a b
Left (a
k, forall a b. b -> Either a b
Right b
x)