{-# LANGUAGE BangPatterns #-}
-- | This module exposes internals of the package: its API may change independently of the PVP-compliant version number.
module Text.Parsix.Internal where

import qualified Data.IntervalMap.FingerTree as IntervalMap
import Data.Text(Text)
import qualified Data.Text.Unsafe as Unsafe

codeUnitSlice :: Int -> Int -> Text -> Text
codeUnitSlice start end text
  = Unsafe.takeWord16 (end' - start')
  $ Unsafe.dropWord16 start' text
  where
    start' = clamp start
    end' = clamp end
    clamp x = max 0 $ min x $ Unsafe.lengthWord16 text

nextNewline :: Text -> Int -> Int
nextNewline inp i = go inp i'
  where
    i' = max 0 i
    go text index
      | index >= len = len
      | otherwise = case Unsafe.iter text index of
        Unsafe.Iter '\n' _ -> index
        Unsafe.Iter _ delta -> nextNewline text $ index + delta
      where
        len = Unsafe.lengthWord16 text

prevNewline :: Text -> Int -> Int
prevNewline inp i = go inp (i' - 1) + 1
  where
    i' = min i $ Unsafe.lengthWord16 inp
    go text index
      | index < 0 = -1
      | otherwise = case Unsafe.reverseIter text index of
        ('\n', _) -> index
        (_, delta) -> go text $ index + delta

rightOpen :: Int -> Int -> IntervalMap.Interval Int
rightOpen !start !end = IntervalMap.Interval start $! end - 1

rightOpenView :: IntervalMap.Interval Int -> (Int, Int)
rightOpenView (IntervalMap.Interval !start !end) = (,) start $! end + 1