-- | Types related to working with NameLookups.
-- We define these low-level types rather than use Path's because we don't have
-- access to those domain types given the package dependency tree.
module U.Codebase.Sqlite.NameLookups
  ( ReversedName (..),
    ReversedPath (..),
    PathSegments (..),
    NamespaceText,
    reversedNameToNamespaceText,
    reversedNameToPathSegments,
    pathSegmentsToText,
    textToPathSegments,
  )
where

import Data.List.NonEmpty (NonEmpty)
import Data.Text qualified as Text
import Unison.Prelude

newtype ReversedName = ReversedName (NonEmpty Text)
  deriving stock (ReversedName -> ReversedName -> Bool
(ReversedName -> ReversedName -> Bool)
-> (ReversedName -> ReversedName -> Bool) -> Eq ReversedName
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ReversedName -> ReversedName -> Bool
== :: ReversedName -> ReversedName -> Bool
$c/= :: ReversedName -> ReversedName -> Bool
/= :: ReversedName -> ReversedName -> Bool
Eq, Eq ReversedName
Eq ReversedName =>
(ReversedName -> ReversedName -> Ordering)
-> (ReversedName -> ReversedName -> Bool)
-> (ReversedName -> ReversedName -> Bool)
-> (ReversedName -> ReversedName -> Bool)
-> (ReversedName -> ReversedName -> Bool)
-> (ReversedName -> ReversedName -> ReversedName)
-> (ReversedName -> ReversedName -> ReversedName)
-> Ord ReversedName
ReversedName -> ReversedName -> Bool
ReversedName -> ReversedName -> Ordering
ReversedName -> ReversedName -> ReversedName
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 :: ReversedName -> ReversedName -> Ordering
compare :: ReversedName -> ReversedName -> Ordering
$c< :: ReversedName -> ReversedName -> Bool
< :: ReversedName -> ReversedName -> Bool
$c<= :: ReversedName -> ReversedName -> Bool
<= :: ReversedName -> ReversedName -> Bool
$c> :: ReversedName -> ReversedName -> Bool
> :: ReversedName -> ReversedName -> Bool
$c>= :: ReversedName -> ReversedName -> Bool
>= :: ReversedName -> ReversedName -> Bool
$cmax :: ReversedName -> ReversedName -> ReversedName
max :: ReversedName -> ReversedName -> ReversedName
$cmin :: ReversedName -> ReversedName -> ReversedName
min :: ReversedName -> ReversedName -> ReversedName
Ord, Int -> ReversedName -> ShowS
[ReversedName] -> ShowS
ReversedName -> String
(Int -> ReversedName -> ShowS)
-> (ReversedName -> String)
-> ([ReversedName] -> ShowS)
-> Show ReversedName
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ReversedName -> ShowS
showsPrec :: Int -> ReversedName -> ShowS
$cshow :: ReversedName -> String
show :: ReversedName -> String
$cshowList :: [ReversedName] -> ShowS
showList :: [ReversedName] -> ShowS
Show)

instance From ReversedName (NonEmpty Text)

instance From (NonEmpty Text) ReversedName

instance From ReversedName [Text] where
  from :: ReversedName -> [Text]
from (ReversedName NonEmpty Text
n) = NonEmpty Text -> [Text]
forall a. NonEmpty a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList NonEmpty Text
n

newtype ReversedPath = ReversedPath [Text]
  deriving (ReversedPath -> ReversedPath -> Bool
(ReversedPath -> ReversedPath -> Bool)
-> (ReversedPath -> ReversedPath -> Bool) -> Eq ReversedPath
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ReversedPath -> ReversedPath -> Bool
== :: ReversedPath -> ReversedPath -> Bool
$c/= :: ReversedPath -> ReversedPath -> Bool
/= :: ReversedPath -> ReversedPath -> Bool
Eq, Eq ReversedPath
Eq ReversedPath =>
(ReversedPath -> ReversedPath -> Ordering)
-> (ReversedPath -> ReversedPath -> Bool)
-> (ReversedPath -> ReversedPath -> Bool)
-> (ReversedPath -> ReversedPath -> Bool)
-> (ReversedPath -> ReversedPath -> Bool)
-> (ReversedPath -> ReversedPath -> ReversedPath)
-> (ReversedPath -> ReversedPath -> ReversedPath)
-> Ord ReversedPath
ReversedPath -> ReversedPath -> Bool
ReversedPath -> ReversedPath -> Ordering
ReversedPath -> ReversedPath -> ReversedPath
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 :: ReversedPath -> ReversedPath -> Ordering
compare :: ReversedPath -> ReversedPath -> Ordering
$c< :: ReversedPath -> ReversedPath -> Bool
< :: ReversedPath -> ReversedPath -> Bool
$c<= :: ReversedPath -> ReversedPath -> Bool
<= :: ReversedPath -> ReversedPath -> Bool
$c> :: ReversedPath -> ReversedPath -> Bool
> :: ReversedPath -> ReversedPath -> Bool
$c>= :: ReversedPath -> ReversedPath -> Bool
>= :: ReversedPath -> ReversedPath -> Bool
$cmax :: ReversedPath -> ReversedPath -> ReversedPath
max :: ReversedPath -> ReversedPath -> ReversedPath
$cmin :: ReversedPath -> ReversedPath -> ReversedPath
min :: ReversedPath -> ReversedPath -> ReversedPath
Ord, Int -> ReversedPath -> ShowS
[ReversedPath] -> ShowS
ReversedPath -> String
(Int -> ReversedPath -> ShowS)
-> (ReversedPath -> String)
-> ([ReversedPath] -> ShowS)
-> Show ReversedPath
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ReversedPath -> ShowS
showsPrec :: Int -> ReversedPath -> ShowS
$cshow :: ReversedPath -> String
show :: ReversedPath -> String
$cshowList :: [ReversedPath] -> ShowS
showList :: [ReversedPath] -> ShowS
Show)

instance From ReversedPath [Text]

instance From [Text] ReversedPath

newtype PathSegments = PathSegments [Text]
  deriving stock (PathSegments -> PathSegments -> Bool
(PathSegments -> PathSegments -> Bool)
-> (PathSegments -> PathSegments -> Bool) -> Eq PathSegments
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PathSegments -> PathSegments -> Bool
== :: PathSegments -> PathSegments -> Bool
$c/= :: PathSegments -> PathSegments -> Bool
/= :: PathSegments -> PathSegments -> Bool
Eq, Eq PathSegments
Eq PathSegments =>
(PathSegments -> PathSegments -> Ordering)
-> (PathSegments -> PathSegments -> Bool)
-> (PathSegments -> PathSegments -> Bool)
-> (PathSegments -> PathSegments -> Bool)
-> (PathSegments -> PathSegments -> Bool)
-> (PathSegments -> PathSegments -> PathSegments)
-> (PathSegments -> PathSegments -> PathSegments)
-> Ord PathSegments
PathSegments -> PathSegments -> Bool
PathSegments -> PathSegments -> Ordering
PathSegments -> PathSegments -> PathSegments
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 :: PathSegments -> PathSegments -> Ordering
compare :: PathSegments -> PathSegments -> Ordering
$c< :: PathSegments -> PathSegments -> Bool
< :: PathSegments -> PathSegments -> Bool
$c<= :: PathSegments -> PathSegments -> Bool
<= :: PathSegments -> PathSegments -> Bool
$c> :: PathSegments -> PathSegments -> Bool
> :: PathSegments -> PathSegments -> Bool
$c>= :: PathSegments -> PathSegments -> Bool
>= :: PathSegments -> PathSegments -> Bool
$cmax :: PathSegments -> PathSegments -> PathSegments
max :: PathSegments -> PathSegments -> PathSegments
$cmin :: PathSegments -> PathSegments -> PathSegments
min :: PathSegments -> PathSegments -> PathSegments
Ord, Int -> PathSegments -> ShowS
[PathSegments] -> ShowS
PathSegments -> String
(Int -> PathSegments -> ShowS)
-> (PathSegments -> String)
-> ([PathSegments] -> ShowS)
-> Show PathSegments
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PathSegments -> ShowS
showsPrec :: Int -> PathSegments -> ShowS
$cshow :: PathSegments -> String
show :: PathSegments -> String
$cshowList :: [PathSegments] -> ShowS
showList :: [PathSegments] -> ShowS
Show)
  deriving newtype (NonEmpty PathSegments -> PathSegments
PathSegments -> PathSegments -> PathSegments
(PathSegments -> PathSegments -> PathSegments)
-> (NonEmpty PathSegments -> PathSegments)
-> (forall b. Integral b => b -> PathSegments -> PathSegments)
-> Semigroup PathSegments
forall b. Integral b => b -> PathSegments -> PathSegments
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
$c<> :: PathSegments -> PathSegments -> PathSegments
<> :: PathSegments -> PathSegments -> PathSegments
$csconcat :: NonEmpty PathSegments -> PathSegments
sconcat :: NonEmpty PathSegments -> PathSegments
$cstimes :: forall b. Integral b => b -> PathSegments -> PathSegments
stimes :: forall b. Integral b => b -> PathSegments -> PathSegments
Semigroup, Semigroup PathSegments
PathSegments
Semigroup PathSegments =>
PathSegments
-> (PathSegments -> PathSegments -> PathSegments)
-> ([PathSegments] -> PathSegments)
-> Monoid PathSegments
[PathSegments] -> PathSegments
PathSegments -> PathSegments -> PathSegments
forall a.
Semigroup a =>
a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
$cmempty :: PathSegments
mempty :: PathSegments
$cmappend :: PathSegments -> PathSegments -> PathSegments
mappend :: PathSegments -> PathSegments -> PathSegments
$cmconcat :: [PathSegments] -> PathSegments
mconcat :: [PathSegments] -> PathSegments
Monoid)

instance From PathSegments [Text]

instance From [Text] PathSegments

-- | A namespace rendered as a path, no leading '.'
-- E.g. "base.data"
type NamespaceText = Text

-- |
-- >>> pathSegmentsToText (PathSegments ["base", "data", "List"])
-- "base.data.List"
pathSegmentsToText :: PathSegments -> Text
pathSegmentsToText :: PathSegments -> Text
pathSegmentsToText (PathSegments [Text]
txt) = Text -> [Text] -> Text
Text.intercalate Text
"." [Text]
txt

-- |
-- >>> textToPathSegments "base.data.List"
-- PathSegments ["base","data","List"]
textToPathSegments :: Text -> PathSegments
textToPathSegments :: Text -> PathSegments
textToPathSegments Text
txt = [Text] -> PathSegments
PathSegments ([Text] -> PathSegments) -> [Text] -> PathSegments
forall a b. (a -> b) -> a -> b
$ HasCallStack => Text -> Text -> [Text]
Text -> Text -> [Text]
Text.splitOn Text
"." Text
txt

-- |
-- >>> reversedSegmentsToNamespaceText (["List", "data", "base"])
-- "base.data.List"
reversedNameToNamespaceText :: ReversedName -> NamespaceText
reversedNameToNamespaceText :: ReversedName -> Text
reversedNameToNamespaceText (ReversedName NonEmpty Text
txt) = Text -> [Text] -> Text
Text.intercalate Text
"." ([Text] -> Text)
-> (NonEmpty Text -> [Text]) -> NonEmpty Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Text] -> [Text]
forall a. [a] -> [a]
reverse ([Text] -> [Text])
-> (NonEmpty Text -> [Text]) -> NonEmpty Text -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmpty Text -> [Text]
forall a. NonEmpty a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (NonEmpty Text -> Text) -> NonEmpty Text -> Text
forall a b. (a -> b) -> a -> b
$ NonEmpty Text
txt

reversedNameToPathSegments :: ReversedName -> PathSegments
reversedNameToPathSegments :: ReversedName -> PathSegments
reversedNameToPathSegments (ReversedName NonEmpty Text
revName) = [Text] -> PathSegments
PathSegments ([Text] -> PathSegments)
-> (NonEmpty Text -> [Text]) -> NonEmpty Text -> PathSegments
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Text] -> [Text]
forall a. [a] -> [a]
reverse ([Text] -> [Text])
-> (NonEmpty Text -> [Text]) -> NonEmpty Text -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmpty Text -> [Text]
forall a. NonEmpty a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (NonEmpty Text -> PathSegments) -> NonEmpty Text -> PathSegments
forall a b. (a -> b) -> a -> b
$ NonEmpty Text
revName