{-# LANGUAGE TypeFamilies, FlexibleInstances #-}
module Data.Interned.Internal.String
  ( InternedString(..)
  ) where

import Data.String
import Data.Interned
import Data.Hashable
import Data.Foldable

data InternedString = IS
  { InternedString -> Id
internedStringId :: {-# UNPACK #-} !Id
  , InternedString -> String
uninternString :: String
  }

instance IsString InternedString where
  fromString :: String -> InternedString
fromString = String -> InternedString
forall t. Interned t => Uninterned t -> t
intern

instance Eq InternedString where
  IS Id
i String
_ == :: InternedString -> InternedString -> Bool
== IS Id
j String
_ = Id
i Id -> Id -> Bool
forall a. Eq a => a -> a -> Bool
== Id
j

instance Ord InternedString where
  compare :: InternedString -> InternedString -> Ordering
compare (IS Id
i String
_) (IS Id
j String
_) = Id -> Id -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Id
i Id
j

instance Show InternedString where
  showsPrec :: Id -> InternedString -> ShowS
showsPrec Id
d (IS Id
_ String
b) = Id -> String -> ShowS
forall a. Show a => Id -> a -> ShowS
showsPrec Id
d String
b

instance Hashable InternedString where
  hashWithSalt :: Id -> InternedString -> Id
hashWithSalt Id
s (IS Id
i String
_) = Id -> Id -> Id
forall a. Hashable a => Id -> a -> Id
hashWithSalt Id
s Id
i

instance Interned InternedString where
  type Uninterned InternedString = String
  data Description InternedString = Cons {-# UNPACK #-} !Char String | Nil
    deriving (Description InternedString -> Description InternedString -> Bool
(Description InternedString -> Description InternedString -> Bool)
-> (Description InternedString
    -> Description InternedString -> Bool)
-> Eq (Description InternedString)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Description InternedString -> Description InternedString -> Bool
$c/= :: Description InternedString -> Description InternedString -> Bool
== :: Description InternedString -> Description InternedString -> Bool
$c== :: Description InternedString -> Description InternedString -> Bool
Eq)
  describe :: Uninterned InternedString -> Description InternedString
describe (c:cs) = Char -> String -> Description InternedString
Cons Char
c String
cs
  describe []     = Description InternedString
Nil
  identify :: Id -> Uninterned InternedString -> InternedString
identify = Id -> String -> InternedString
Id -> Uninterned InternedString -> InternedString
IS
  cache :: Cache InternedString
cache = Cache InternedString
stringCache

instance Uninternable InternedString where
  unintern :: InternedString -> Uninterned InternedString
unintern = InternedString -> String
InternedString -> Uninterned InternedString
uninternString

instance Hashable (Description InternedString) where
  hashWithSalt :: Id -> Description InternedString -> Id
hashWithSalt Id
s (Cons c cs) = (Id -> Char -> Id) -> Id -> String -> Id
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Id -> Char -> Id
forall a. Hashable a => Id -> a -> Id
hashWithSalt (Id -> Char -> Id
forall a. Hashable a => Id -> a -> Id
hashWithSalt Id
s Char
c) String
cs
  hashWithSalt Id
s Description InternedString
Nil         = Id
s Id -> Id -> Id
forall a. Hashable a => Id -> a -> Id
`hashWithSalt` (Id
0 :: Int)

stringCache :: Cache InternedString
stringCache :: Cache InternedString
stringCache = Cache InternedString
forall t. Interned t => Cache t
mkCache
{-# NOINLINE stringCache #-}