{-# LANGUAGE PatternSynonyms #-}
module Toml.Type.Key
(
Key (..)
, Prefix
, Piece (..)
, pattern (:||)
, (<|)
, KeysDiff (..)
, keysDiff
) where
import Control.DeepSeq (NFData)
import Data.Coerce (coerce)
import Data.Hashable (Hashable)
import Data.List.NonEmpty (NonEmpty (..))
import Data.String (IsString (..))
import Data.Text (Text)
import GHC.Generics (Generic)
import qualified Data.List.NonEmpty as NonEmpty
import qualified Data.Text as Text
newtype Piece = Piece
{ Piece -> Text
unPiece :: Text
} deriving stock (forall x. Rep Piece x -> Piece
forall x. Piece -> Rep Piece x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Piece x -> Piece
$cfrom :: forall x. Piece -> Rep Piece x
Generic)
deriving newtype (Int -> Piece -> ShowS
[Piece] -> ShowS
Piece -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Piece] -> ShowS
$cshowList :: [Piece] -> ShowS
show :: Piece -> String
$cshow :: Piece -> String
showsPrec :: Int -> Piece -> ShowS
$cshowsPrec :: Int -> Piece -> ShowS
Show, Piece -> Piece -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Piece -> Piece -> Bool
$c/= :: Piece -> Piece -> Bool
== :: Piece -> Piece -> Bool
$c== :: Piece -> Piece -> Bool
Eq, Eq Piece
Piece -> Piece -> Bool
Piece -> Piece -> Ordering
Piece -> Piece -> Piece
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
min :: Piece -> Piece -> Piece
$cmin :: Piece -> Piece -> Piece
max :: Piece -> Piece -> Piece
$cmax :: Piece -> Piece -> Piece
>= :: Piece -> Piece -> Bool
$c>= :: Piece -> Piece -> Bool
> :: Piece -> Piece -> Bool
$c> :: Piece -> Piece -> Bool
<= :: Piece -> Piece -> Bool
$c<= :: Piece -> Piece -> Bool
< :: Piece -> Piece -> Bool
$c< :: Piece -> Piece -> Bool
compare :: Piece -> Piece -> Ordering
$ccompare :: Piece -> Piece -> Ordering
Ord, Eq Piece
Int -> Piece -> Int
Piece -> Int
forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: Piece -> Int
$chash :: Piece -> Int
hashWithSalt :: Int -> Piece -> Int
$chashWithSalt :: Int -> Piece -> Int
Hashable, String -> Piece
forall a. (String -> a) -> IsString a
fromString :: String -> Piece
$cfromString :: String -> Piece
IsString, Piece -> ()
forall a. (a -> ()) -> NFData a
rnf :: Piece -> ()
$crnf :: Piece -> ()
NFData)
newtype Key = Key
{ Key -> NonEmpty Piece
unKey :: NonEmpty Piece
} deriving stock (forall x. Rep Key x -> Key
forall x. Key -> Rep Key x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Key x -> Key
$cfrom :: forall x. Key -> Rep Key x
Generic)
deriving newtype (Int -> Key -> ShowS
[Key] -> ShowS
Key -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Key] -> ShowS
$cshowList :: [Key] -> ShowS
show :: Key -> String
$cshow :: Key -> String
showsPrec :: Int -> Key -> ShowS
$cshowsPrec :: Int -> Key -> ShowS
Show, Key -> Key -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Key -> Key -> Bool
$c/= :: Key -> Key -> Bool
== :: Key -> Key -> Bool
$c== :: Key -> Key -> Bool
Eq, Eq Key
Key -> Key -> Bool
Key -> Key -> Ordering
Key -> Key -> Key
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
min :: Key -> Key -> Key
$cmin :: Key -> Key -> Key
max :: Key -> Key -> Key
$cmax :: Key -> Key -> Key
>= :: Key -> Key -> Bool
$c>= :: Key -> Key -> Bool
> :: Key -> Key -> Bool
$c> :: Key -> Key -> Bool
<= :: Key -> Key -> Bool
$c<= :: Key -> Key -> Bool
< :: Key -> Key -> Bool
$c< :: Key -> Key -> Bool
compare :: Key -> Key -> Ordering
$ccompare :: Key -> Key -> Ordering
Ord, Eq Key
Int -> Key -> Int
Key -> Int
forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: Key -> Int
$chash :: Key -> Int
hashWithSalt :: Int -> Key -> Int
$chashWithSalt :: Int -> Key -> Int
Hashable, Key -> ()
forall a. (a -> ()) -> NFData a
rnf :: Key -> ()
$crnf :: Key -> ()
NFData, NonEmpty Key -> Key
Key -> Key -> Key
forall b. Integral b => b -> Key -> Key
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: forall b. Integral b => b -> Key -> Key
$cstimes :: forall b. Integral b => b -> Key -> Key
sconcat :: NonEmpty Key -> Key
$csconcat :: NonEmpty Key -> Key
<> :: Key -> Key -> Key
$c<> :: Key -> Key -> Key
Semigroup)
type Prefix = Key
instance IsString Key where
fromString :: String -> Key
fromString :: String -> Key
fromString = \case
String
"" -> NonEmpty Piece -> Key
Key (Piece
"" forall a. a -> [a] -> NonEmpty a
:| [])
String
s -> case Text -> Text -> [Text]
Text.splitOn Text
"." (forall a. IsString a => String -> a
fromString String
s) of
[] -> forall a. HasCallStack => String -> a
error String
"Text.splitOn returned empty string"
Text
x:[Text]
xs -> coerce :: forall a b. Coercible a b => a -> b
coerce @(NonEmpty Text) @Key (Text
x forall a. a -> [a] -> NonEmpty a
:| [Text]
xs)
pattern (:||) :: Piece -> [Piece] -> Key
pattern x $b:|| :: Piece -> [Piece] -> Key
$m:|| :: forall {r}. Key -> (Piece -> [Piece] -> r) -> ((# #) -> r) -> r
:|| xs <- Key (x :| xs)
where
Piece
x :|| [Piece]
xs = NonEmpty Piece -> Key
Key (Piece
x forall a. a -> [a] -> NonEmpty a
:| [Piece]
xs)
{-# COMPLETE (:||) #-}
(<|) :: Piece -> Key -> Key
<| :: Piece -> Key -> Key
(<|) Piece
p Key
k = NonEmpty Piece -> Key
Key (Piece
p forall a. a -> NonEmpty a -> NonEmpty a
NonEmpty.<| Key -> NonEmpty Piece
unKey Key
k)
{-# INLINE (<|) #-}
data KeysDiff
= Equal
| NoPrefix
| FstIsPref
!Key
| SndIsPref
!Key
| Diff
!Key
!Key
!Key
deriving stock (Int -> KeysDiff -> ShowS
[KeysDiff] -> ShowS
KeysDiff -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [KeysDiff] -> ShowS
$cshowList :: [KeysDiff] -> ShowS
show :: KeysDiff -> String
$cshow :: KeysDiff -> String
showsPrec :: Int -> KeysDiff -> ShowS
$cshowsPrec :: Int -> KeysDiff -> ShowS
Show, KeysDiff -> KeysDiff -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: KeysDiff -> KeysDiff -> Bool
$c/= :: KeysDiff -> KeysDiff -> Bool
== :: KeysDiff -> KeysDiff -> Bool
$c== :: KeysDiff -> KeysDiff -> Bool
Eq)
keysDiff :: Key -> Key -> KeysDiff
keysDiff :: Key -> Key -> KeysDiff
keysDiff (Piece
x :|| [Piece]
xs) (Piece
y :|| [Piece]
ys)
| Piece
x forall a. Eq a => a -> a -> Bool
== Piece
y = [Piece] -> [Piece] -> [Piece] -> KeysDiff
listSame [Piece]
xs [Piece]
ys []
| Bool
otherwise = KeysDiff
NoPrefix
where
listSame :: [Piece] -> [Piece] -> [Piece] -> KeysDiff
listSame :: [Piece] -> [Piece] -> [Piece] -> KeysDiff
listSame [] [] [Piece]
_ = KeysDiff
Equal
listSame [] (Piece
s:[Piece]
ss) [Piece]
_ = Key -> KeysDiff
FstIsPref forall a b. (a -> b) -> a -> b
$ Piece
s Piece -> [Piece] -> Key
:|| [Piece]
ss
listSame (Piece
f:[Piece]
fs) [] [Piece]
_ = Key -> KeysDiff
SndIsPref forall a b. (a -> b) -> a -> b
$ Piece
f Piece -> [Piece] -> Key
:|| [Piece]
fs
listSame (Piece
f:[Piece]
fs) (Piece
s:[Piece]
ss) [Piece]
pr =
if Piece
f forall a. Eq a => a -> a -> Bool
== Piece
s
then [Piece] -> [Piece] -> [Piece] -> KeysDiff
listSame [Piece]
fs [Piece]
ss ([Piece]
pr forall a. [a] -> [a] -> [a]
++ [Piece
f])
else Key -> Key -> Key -> KeysDiff
Diff (Piece
x Piece -> [Piece] -> Key
:|| [Piece]
pr) (Piece
f Piece -> [Piece] -> Key
:|| [Piece]
fs) (Piece
s Piece -> [Piece] -> Key
:|| [Piece]
ss)