{-# LANGUAGE GeneralizedNewtypeDeriving #-}

-- | Name is an atomic symbol
--
-- Note that `IsString` instance is a partial function

module Pdf.Core.Name
(
  Name,
  make,
  toByteString
)
where

import Data.String
import Data.ByteString (ByteString)
import qualified Data.ByteString as ByteString
import Data.Hashable (Hashable)

-- | Names usually are used as keys in dictionaries
--
-- Byte 0 is not allowed inside names
newtype Name = Name ByteString
  deriving (Name -> Name -> Bool
(Name -> Name -> Bool) -> (Name -> Name -> Bool) -> Eq Name
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Name -> Name -> Bool
$c/= :: Name -> Name -> Bool
== :: Name -> Name -> Bool
$c== :: Name -> Name -> Bool
Eq, Int -> Name -> ShowS
[Name] -> ShowS
Name -> String
(Int -> Name -> ShowS)
-> (Name -> String) -> ([Name] -> ShowS) -> Show Name
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Name] -> ShowS
$cshowList :: [Name] -> ShowS
show :: Name -> String
$cshow :: Name -> String
showsPrec :: Int -> Name -> ShowS
$cshowsPrec :: Int -> Name -> ShowS
Show, Eq Name
Eq Name
-> (Name -> Name -> Ordering)
-> (Name -> Name -> Bool)
-> (Name -> Name -> Bool)
-> (Name -> Name -> Bool)
-> (Name -> Name -> Bool)
-> (Name -> Name -> Name)
-> (Name -> Name -> Name)
-> Ord Name
Name -> Name -> Bool
Name -> Name -> Ordering
Name -> Name -> Name
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 :: Name -> Name -> Name
$cmin :: Name -> Name -> Name
max :: Name -> Name -> Name
$cmax :: Name -> Name -> Name
>= :: Name -> Name -> Bool
$c>= :: Name -> Name -> Bool
> :: Name -> Name -> Bool
$c> :: Name -> Name -> Bool
<= :: Name -> Name -> Bool
$c<= :: Name -> Name -> Bool
< :: Name -> Name -> Bool
$c< :: Name -> Name -> Bool
compare :: Name -> Name -> Ordering
$ccompare :: Name -> Name -> Ordering
$cp1Ord :: Eq Name
Ord, Semigroup Name
Name
Semigroup Name
-> Name
-> (Name -> Name -> Name)
-> ([Name] -> Name)
-> Monoid Name
[Name] -> Name
Name -> Name -> Name
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
mconcat :: [Name] -> Name
$cmconcat :: [Name] -> Name
mappend :: Name -> Name -> Name
$cmappend :: Name -> Name -> Name
mempty :: Name
$cmempty :: Name
$cp1Monoid :: Semigroup Name
Monoid, b -> Name -> Name
NonEmpty Name -> Name
Name -> Name -> Name
(Name -> Name -> Name)
-> (NonEmpty Name -> Name)
-> (forall b. Integral b => b -> Name -> Name)
-> Semigroup Name
forall b. Integral b => b -> Name -> Name
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: b -> Name -> Name
$cstimes :: forall b. Integral b => b -> Name -> Name
sconcat :: NonEmpty Name -> Name
$csconcat :: NonEmpty Name -> Name
<> :: Name -> Name -> Name
$c<> :: Name -> Name -> Name
Semigroup, Int -> Name -> Int
Name -> Int
(Int -> Name -> Int) -> (Name -> Int) -> Hashable Name
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: Name -> Int
$chash :: Name -> Int
hashWithSalt :: Int -> Name -> Int
$chashWithSalt :: Int -> Name -> Int
Hashable)

-- | Make a name.
--
-- Throws if the bytestring contains 0
make :: ByteString -> Either String Name
make :: ByteString -> Either String Name
make ByteString
bs
  | (Word8 -> Bool) -> ByteString -> Bool
ByteString.any (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0) ByteString
bs
  = String -> Either String Name
forall a b. a -> Either a b
Left String
"Name.make: 0 byte is not allowed"
  | Bool
otherwise
  = Name -> Either String Name
forall a b. b -> Either a b
Right (ByteString -> Name
Name ByteString
bs)

-- | Unwrap name to bytestring
toByteString :: Name -> ByteString
toByteString :: Name -> ByteString
toByteString (Name ByteString
bs) = ByteString
bs

instance IsString Name where
  fromString :: String -> Name
fromString = (String -> Name) -> (Name -> Name) -> Either String Name -> Name
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> Name
forall a. HasCallStack => String -> a
error Name -> Name
forall a. a -> a
id (Either String Name -> Name)
-> (String -> Either String Name) -> String -> Name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either String Name
make (ByteString -> Either String Name)
-> (String -> ByteString) -> String -> Either String Name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ByteString
forall a. IsString a => String -> a
fromString