{- |
Copyright: © 2019 James Alexander Feldman-Crough
License: MPL-2.0
-}
module ProSource.Offset (Offset (..)) where

import qualified Data.Vector.Generic as VG
import qualified Data.Vector.Generic.Mutable as VGM
import Data.Vector.Unboxed (MVector, Unbox, Vector)

-- | An offset into a 'Source', counted by UTF-8 codepoint.
newtype Offset = Offset Word
  deriving stock (Offset -> Offset -> Bool
(Offset -> Offset -> Bool)
-> (Offset -> Offset -> Bool) -> Eq Offset
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Offset -> Offset -> Bool
$c/= :: Offset -> Offset -> Bool
== :: Offset -> Offset -> Bool
$c== :: Offset -> Offset -> Bool
Eq, Int -> Offset -> ShowS
[Offset] -> ShowS
Offset -> String
(Int -> Offset -> ShowS)
-> (Offset -> String) -> ([Offset] -> ShowS) -> Show Offset
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Offset] -> ShowS
$cshowList :: [Offset] -> ShowS
show :: Offset -> String
$cshow :: Offset -> String
showsPrec :: Int -> Offset -> ShowS
$cshowsPrec :: Int -> Offset -> ShowS
Show, Eq Offset
Eq Offset
-> (Offset -> Offset -> Ordering)
-> (Offset -> Offset -> Bool)
-> (Offset -> Offset -> Bool)
-> (Offset -> Offset -> Bool)
-> (Offset -> Offset -> Bool)
-> (Offset -> Offset -> Offset)
-> (Offset -> Offset -> Offset)
-> Ord Offset
Offset -> Offset -> Bool
Offset -> Offset -> Ordering
Offset -> Offset -> Offset
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 :: Offset -> Offset -> Offset
$cmin :: Offset -> Offset -> Offset
max :: Offset -> Offset -> Offset
$cmax :: Offset -> Offset -> Offset
>= :: Offset -> Offset -> Bool
$c>= :: Offset -> Offset -> Bool
> :: Offset -> Offset -> Bool
$c> :: Offset -> Offset -> Bool
<= :: Offset -> Offset -> Bool
$c<= :: Offset -> Offset -> Bool
< :: Offset -> Offset -> Bool
$c< :: Offset -> Offset -> Bool
compare :: Offset -> Offset -> Ordering
$ccompare :: Offset -> Offset -> Ordering
$cp1Ord :: Eq Offset
Ord, (forall x. Offset -> Rep Offset x)
-> (forall x. Rep Offset x -> Offset) -> Generic Offset
forall x. Rep Offset x -> Offset
forall x. Offset -> Rep Offset x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Offset x -> Offset
$cfrom :: forall x. Offset -> Rep Offset x
Generic)
  deriving anyclass (Eq Offset
Eq Offset
-> (Int -> Offset -> Int) -> (Offset -> Int) -> Hashable Offset
Int -> Offset -> Int
Offset -> Int
forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: Offset -> Int
$chash :: Offset -> Int
hashWithSalt :: Int -> Offset -> Int
$chashWithSalt :: Int -> Offset -> Int
$cp1Hashable :: Eq Offset
Hashable, Offset -> ()
(Offset -> ()) -> NFData Offset
forall a. (a -> ()) -> NFData a
rnf :: Offset -> ()
$crnf :: Offset -> ()
NFData)
  deriving newtype Int -> Offset
Offset -> Int
Offset -> [Offset]
Offset -> Offset
Offset -> Offset -> [Offset]
Offset -> Offset -> Offset -> [Offset]
(Offset -> Offset)
-> (Offset -> Offset)
-> (Int -> Offset)
-> (Offset -> Int)
-> (Offset -> [Offset])
-> (Offset -> Offset -> [Offset])
-> (Offset -> Offset -> [Offset])
-> (Offset -> Offset -> Offset -> [Offset])
-> Enum Offset
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Offset -> Offset -> Offset -> [Offset]
$cenumFromThenTo :: Offset -> Offset -> Offset -> [Offset]
enumFromTo :: Offset -> Offset -> [Offset]
$cenumFromTo :: Offset -> Offset -> [Offset]
enumFromThen :: Offset -> Offset -> [Offset]
$cenumFromThen :: Offset -> Offset -> [Offset]
enumFrom :: Offset -> [Offset]
$cenumFrom :: Offset -> [Offset]
fromEnum :: Offset -> Int
$cfromEnum :: Offset -> Int
toEnum :: Int -> Offset
$ctoEnum :: Int -> Offset
pred :: Offset -> Offset
$cpred :: Offset -> Offset
succ :: Offset -> Offset
$csucc :: Offset -> Offset
Enum

instance Pretty Offset where
    pretty :: Offset -> Doc ann
pretty (Offset Word
n) = Doc ann
"+" Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Word -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty Word
n

newtype instance MVector s Offset = MV_Offset (MVector s Word)

instance VGM.MVector MVector Offset where
    basicLength :: MVector s Offset -> Int
basicLength (MV_Offset m) = MVector s Word -> Int
forall (v :: * -> * -> *) a s. MVector v a => v s a -> Int
VGM.basicLength MVector s Word
m
    basicUnsafeSlice :: Int -> Int -> MVector s Offset -> MVector s Offset
basicUnsafeSlice Int
ix Int
len (MV_Offset m) = MVector s Word -> MVector s Offset
forall s. MVector s Word -> MVector s Offset
MV_Offset (MVector s Word -> MVector s Offset)
-> MVector s Word -> MVector s Offset
forall a b. (a -> b) -> a -> b
$ Int -> Int -> MVector s Word -> MVector s Word
forall (v :: * -> * -> *) a s.
MVector v a =>
Int -> Int -> v s a -> v s a
VGM.basicUnsafeSlice Int
ix Int
len MVector s Word
m
    basicOverlaps :: MVector s Offset -> MVector s Offset -> Bool
basicOverlaps (MV_Offset x) (MV_Offset y) = MVector s Word -> MVector s Word -> Bool
forall (v :: * -> * -> *) a s.
MVector v a =>
v s a -> v s a -> Bool
VGM.basicOverlaps MVector s Word
x MVector s Word
y
    basicUnsafeNew :: Int -> m (MVector (PrimState m) Offset)
basicUnsafeNew Int
len = MVector (PrimState m) Word -> MVector (PrimState m) Offset
forall s. MVector s Word -> MVector s Offset
MV_Offset (MVector (PrimState m) Word -> MVector (PrimState m) Offset)
-> m (MVector (PrimState m) Word)
-> m (MVector (PrimState m) Offset)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> m (MVector (PrimState m) Word)
forall (v :: * -> * -> *) a (m :: * -> *).
(MVector v a, PrimMonad m) =>
Int -> m (v (PrimState m) a)
VGM.basicUnsafeNew Int
len
    basicInitialize :: MVector (PrimState m) Offset -> m ()
basicInitialize (MV_Offset v) = MVector (PrimState m) Word -> m ()
forall (v :: * -> * -> *) a (m :: * -> *).
(MVector v a, PrimMonad m) =>
v (PrimState m) a -> m ()
VGM.basicInitialize MVector (PrimState m) Word
v
    basicUnsafeRead :: MVector (PrimState m) Offset -> Int -> m Offset
basicUnsafeRead (MV_Offset v) = (Word -> Offset) -> m Word -> m Offset
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Word -> Offset
Offset (m Word -> m Offset) -> (Int -> m Word) -> Int -> m Offset
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MVector (PrimState m) Word -> Int -> m Word
forall (v :: * -> * -> *) a (m :: * -> *).
(MVector v a, PrimMonad m) =>
v (PrimState m) a -> Int -> m a
VGM.basicUnsafeRead MVector (PrimState m) Word
v
    basicUnsafeWrite :: MVector (PrimState m) Offset -> Int -> Offset -> m ()
basicUnsafeWrite (MV_Offset v) Int
ix (Offset Word
w) = MVector (PrimState m) Word -> Int -> Word -> m ()
forall (v :: * -> * -> *) a (m :: * -> *).
(MVector v a, PrimMonad m) =>
v (PrimState m) a -> Int -> a -> m ()
VGM.basicUnsafeWrite MVector (PrimState m) Word
v Int
ix Word
w

newtype instance Vector Offset = V_Offset (Vector Word)

instance VG.Vector Vector Offset where
    basicUnsafeFreeze :: Mutable Vector (PrimState m) Offset -> m (Vector Offset)
basicUnsafeFreeze (MV_Offset v) = Vector Word -> Vector Offset
V_Offset (Vector Word -> Vector Offset)
-> m (Vector Word) -> m (Vector Offset)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Mutable Vector (PrimState m) Word -> m (Vector Word)
forall (v :: * -> *) a (m :: * -> *).
(Vector v a, PrimMonad m) =>
Mutable v (PrimState m) a -> m (v a)
VG.basicUnsafeFreeze MVector (PrimState m) Word
Mutable Vector (PrimState m) Word
v
    basicUnsafeThaw :: Vector Offset -> m (Mutable Vector (PrimState m) Offset)
basicUnsafeThaw (V_Offset v) = MVector (PrimState m) Word -> MVector (PrimState m) Offset
forall s. MVector s Word -> MVector s Offset
MV_Offset (MVector (PrimState m) Word -> MVector (PrimState m) Offset)
-> m (MVector (PrimState m) Word)
-> m (MVector (PrimState m) Offset)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Vector Word -> m (Mutable Vector (PrimState m) Word)
forall (v :: * -> *) a (m :: * -> *).
(Vector v a, PrimMonad m) =>
v a -> m (Mutable v (PrimState m) a)
VG.basicUnsafeThaw Vector Word
v
    basicLength :: Vector Offset -> Int
basicLength (V_Offset v) = Vector Word -> Int
forall (v :: * -> *) a. Vector v a => v a -> Int
VG.basicLength Vector Word
v
    basicUnsafeSlice :: Int -> Int -> Vector Offset -> Vector Offset
basicUnsafeSlice Int
ix Int
len (V_Offset v) = Vector Word -> Vector Offset
V_Offset (Vector Word -> Vector Offset) -> Vector Word -> Vector Offset
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Vector Word -> Vector Word
forall (v :: * -> *) a. Vector v a => Int -> Int -> v a -> v a
VG.basicUnsafeSlice Int
ix Int
len Vector Word
v
    basicUnsafeIndexM :: Vector Offset -> Int -> m Offset
basicUnsafeIndexM (V_Offset v) Int
ix = Word -> Offset
Offset (Word -> Offset) -> m Word -> m Offset
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Vector Word -> Int -> m Word
forall (v :: * -> *) a (m :: * -> *).
(Vector v a, Monad m) =>
v a -> Int -> m a
VG.basicUnsafeIndexM Vector Word
v Int
ix

instance Unbox Offset where