{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies          #-}

module HaskellWorks.Data.Unsnoc
    ( Container(..)
    , Unsnoc(..)
    ) where

import Data.Int
import Data.Maybe
import Data.Word
import HaskellWorks.Data.Container
import Prelude                     hiding (drop)

import qualified Data.ByteString      as BS
import qualified Data.Vector          as DV
import qualified Data.Vector.Storable as DVS

class Unsnoc v where
  unsnoc :: v -> Maybe (Elem v, v)

instance Unsnoc String where
  unsnoc :: String -> Maybe (Elem String, String)
unsnoc String
s = case forall a. [a] -> [a]
reverse String
s of
    (Char
x:String
xs) -> forall a. a -> Maybe a
Just (Char
x, forall a. [a] -> [a]
reverse String
xs)
    String
_      -> forall a. Maybe a
Nothing
  {-# INLINE unsnoc   #-}

instance Unsnoc BS.ByteString where
  unsnoc :: ByteString -> Maybe (Elem ByteString, ByteString)
unsnoc ByteString
s = if ByteString -> Int
BS.length ByteString
s forall a. Eq a => a -> a -> Bool
== Int
0 then forall a. Maybe a
Nothing else forall a. a -> Maybe a
Just (HasCallStack => ByteString -> Word8
BS.last ByteString
s, Int -> ByteString -> ByteString
BS.take (ByteString -> Int
BS.length ByteString
s forall a. Num a => a -> a -> a
- Int
1) ByteString
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DV.Vector Word8) where
  unsnoc :: Vector Word8 -> Maybe (Elem (Vector Word8), Vector Word8)
unsnoc Vector Word8
s = if forall a. Vector a -> Int
DV.length Vector Word8
s forall a. Eq a => a -> a -> Bool
== Int
0 then forall a. Maybe a
Nothing else forall a. a -> Maybe a
Just (forall a. Vector a -> a
DV.last Vector Word8
s, forall a. Int -> Vector a -> Vector a
DV.take (forall a. Vector a -> Int
DV.length Vector Word8
s forall a. Num a => a -> a -> a
- Int
1) Vector Word8
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DV.Vector Word16) where
  unsnoc :: Vector Word16 -> Maybe (Elem (Vector Word16), Vector Word16)
unsnoc Vector Word16
s = if forall a. Vector a -> Int
DV.length Vector Word16
s forall a. Eq a => a -> a -> Bool
== Int
0 then forall a. Maybe a
Nothing else forall a. a -> Maybe a
Just (forall a. Vector a -> a
DV.last Vector Word16
s, forall a. Int -> Vector a -> Vector a
DV.take (forall a. Vector a -> Int
DV.length Vector Word16
s forall a. Num a => a -> a -> a
- Int
1) Vector Word16
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DV.Vector Word32) where
  unsnoc :: Vector Word32 -> Maybe (Elem (Vector Word32), Vector Word32)
unsnoc Vector Word32
s = if forall a. Vector a -> Int
DV.length Vector Word32
s forall a. Eq a => a -> a -> Bool
== Int
0 then forall a. Maybe a
Nothing else forall a. a -> Maybe a
Just (forall a. Vector a -> a
DV.last Vector Word32
s, forall a. Int -> Vector a -> Vector a
DV.take (forall a. Vector a -> Int
DV.length Vector Word32
s forall a. Num a => a -> a -> a
- Int
1) Vector Word32
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DV.Vector Word64) where
  unsnoc :: Vector Word64 -> Maybe (Elem (Vector Word64), Vector Word64)
unsnoc Vector Word64
s = if forall a. Vector a -> Int
DV.length Vector Word64
s forall a. Eq a => a -> a -> Bool
== Int
0 then forall a. Maybe a
Nothing else forall a. a -> Maybe a
Just (forall a. Vector a -> a
DV.last Vector Word64
s, forall a. Int -> Vector a -> Vector a
DV.take (forall a. Vector a -> Int
DV.length Vector Word64
s forall a. Num a => a -> a -> a
- Int
1) Vector Word64
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DVS.Vector Word8) where
  unsnoc :: Vector Word8 -> Maybe (Elem (Vector Word8), Vector Word8)
unsnoc Vector Word8
s = if forall a. Storable a => Vector a -> Int
DVS.length Vector Word8
s forall a. Eq a => a -> a -> Bool
== Int
0 then forall a. Maybe a
Nothing else forall a. a -> Maybe a
Just (forall a. Storable a => Vector a -> a
DVS.last Vector Word8
s, forall a. Storable a => Int -> Vector a -> Vector a
DVS.take (forall a. Storable a => Vector a -> Int
DVS.length Vector Word8
s forall a. Num a => a -> a -> a
- Int
1) Vector Word8
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DVS.Vector Word16) where
  unsnoc :: Vector Word16 -> Maybe (Elem (Vector Word16), Vector Word16)
unsnoc Vector Word16
s = if forall a. Storable a => Vector a -> Int
DVS.length Vector Word16
s forall a. Eq a => a -> a -> Bool
== Int
0 then forall a. Maybe a
Nothing else forall a. a -> Maybe a
Just (forall a. Storable a => Vector a -> a
DVS.last Vector Word16
s, forall a. Storable a => Int -> Vector a -> Vector a
DVS.take (forall a. Storable a => Vector a -> Int
DVS.length Vector Word16
s forall a. Num a => a -> a -> a
- Int
1) Vector Word16
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DVS.Vector Word32) where
  unsnoc :: Vector Word32 -> Maybe (Elem (Vector Word32), Vector Word32)
unsnoc Vector Word32
s = if forall a. Storable a => Vector a -> Int
DVS.length Vector Word32
s forall a. Eq a => a -> a -> Bool
== Int
0 then forall a. Maybe a
Nothing else forall a. a -> Maybe a
Just (forall a. Storable a => Vector a -> a
DVS.last Vector Word32
s, forall a. Storable a => Int -> Vector a -> Vector a
DVS.take (forall a. Storable a => Vector a -> Int
DVS.length Vector Word32
s forall a. Num a => a -> a -> a
- Int
1) Vector Word32
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DVS.Vector Word64) where
  unsnoc :: Vector Word64 -> Maybe (Elem (Vector Word64), Vector Word64)
unsnoc Vector Word64
s = if forall a. Storable a => Vector a -> Int
DVS.length Vector Word64
s forall a. Eq a => a -> a -> Bool
== Int
0 then forall a. Maybe a
Nothing else forall a. a -> Maybe a
Just (forall a. Storable a => Vector a -> a
DVS.last Vector Word64
s, forall a. Storable a => Int -> Vector a -> Vector a
DVS.take (forall a. Storable a => Vector a -> Int
DVS.length Vector Word64
s forall a. Num a => a -> a -> a
- Int
1) Vector Word64
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DV.Vector Int8) where
  unsnoc :: Vector Int8 -> Maybe (Elem (Vector Int8), Vector Int8)
unsnoc Vector Int8
s = if forall a. Vector a -> Int
DV.length Vector Int8
s forall a. Eq a => a -> a -> Bool
== Int
0 then forall a. Maybe a
Nothing else forall a. a -> Maybe a
Just (forall a. Vector a -> a
DV.last Vector Int8
s, forall a. Int -> Vector a -> Vector a
DV.take (forall a. Vector a -> Int
DV.length Vector Int8
s forall a. Num a => a -> a -> a
- Int
1) Vector Int8
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DV.Vector Int16) where
  unsnoc :: Vector Int16 -> Maybe (Elem (Vector Int16), Vector Int16)
unsnoc Vector Int16
s = if forall a. Vector a -> Int
DV.length Vector Int16
s forall a. Eq a => a -> a -> Bool
== Int
0 then forall a. Maybe a
Nothing else forall a. a -> Maybe a
Just (forall a. Vector a -> a
DV.last Vector Int16
s, forall a. Int -> Vector a -> Vector a
DV.take (forall a. Vector a -> Int
DV.length Vector Int16
s forall a. Num a => a -> a -> a
- Int
1) Vector Int16
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DV.Vector Int32) where
  unsnoc :: Vector Int32 -> Maybe (Elem (Vector Int32), Vector Int32)
unsnoc Vector Int32
s = if forall a. Vector a -> Int
DV.length Vector Int32
s forall a. Eq a => a -> a -> Bool
== Int
0 then forall a. Maybe a
Nothing else forall a. a -> Maybe a
Just (forall a. Vector a -> a
DV.last Vector Int32
s, forall a. Int -> Vector a -> Vector a
DV.take (forall a. Vector a -> Int
DV.length Vector Int32
s forall a. Num a => a -> a -> a
- Int
1) Vector Int32
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DV.Vector Int64) where
  unsnoc :: Vector Int64 -> Maybe (Elem (Vector Int64), Vector Int64)
unsnoc Vector Int64
s = if forall a. Vector a -> Int
DV.length Vector Int64
s forall a. Eq a => a -> a -> Bool
== Int
0 then forall a. Maybe a
Nothing else forall a. a -> Maybe a
Just (forall a. Vector a -> a
DV.last Vector Int64
s, forall a. Int -> Vector a -> Vector a
DV.take (forall a. Vector a -> Int
DV.length Vector Int64
s forall a. Num a => a -> a -> a
- Int
1) Vector Int64
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DVS.Vector Int8) where
  unsnoc :: Vector Int8 -> Maybe (Elem (Vector Int8), Vector Int8)
unsnoc Vector Int8
s = if forall a. Storable a => Vector a -> Int
DVS.length Vector Int8
s forall a. Eq a => a -> a -> Bool
== Int
0 then forall a. Maybe a
Nothing else forall a. a -> Maybe a
Just (forall a. Storable a => Vector a -> a
DVS.last Vector Int8
s, forall a. Storable a => Int -> Vector a -> Vector a
DVS.take (forall a. Storable a => Vector a -> Int
DVS.length Vector Int8
s forall a. Num a => a -> a -> a
- Int
1) Vector Int8
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DVS.Vector Int16) where
  unsnoc :: Vector Int16 -> Maybe (Elem (Vector Int16), Vector Int16)
unsnoc Vector Int16
s = if forall a. Storable a => Vector a -> Int
DVS.length Vector Int16
s forall a. Eq a => a -> a -> Bool
== Int
0 then forall a. Maybe a
Nothing else forall a. a -> Maybe a
Just (forall a. Storable a => Vector a -> a
DVS.last Vector Int16
s, forall a. Storable a => Int -> Vector a -> Vector a
DVS.take (forall a. Storable a => Vector a -> Int
DVS.length Vector Int16
s forall a. Num a => a -> a -> a
- Int
1) Vector Int16
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DVS.Vector Int32) where
  unsnoc :: Vector Int32 -> Maybe (Elem (Vector Int32), Vector Int32)
unsnoc Vector Int32
s = if forall a. Storable a => Vector a -> Int
DVS.length Vector Int32
s forall a. Eq a => a -> a -> Bool
== Int
0 then forall a. Maybe a
Nothing else forall a. a -> Maybe a
Just (forall a. Storable a => Vector a -> a
DVS.last Vector Int32
s, forall a. Storable a => Int -> Vector a -> Vector a
DVS.take (forall a. Storable a => Vector a -> Int
DVS.length Vector Int32
s forall a. Num a => a -> a -> a
- Int
1) Vector Int32
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DVS.Vector Int64) where
  unsnoc :: Vector Int64 -> Maybe (Elem (Vector Int64), Vector Int64)
unsnoc Vector Int64
s = if forall a. Storable a => Vector a -> Int
DVS.length Vector Int64
s forall a. Eq a => a -> a -> Bool
== Int
0 then forall a. Maybe a
Nothing else forall a. a -> Maybe a
Just (forall a. Storable a => Vector a -> a
DVS.last Vector Int64
s, forall a. Storable a => Int -> Vector a -> Vector a
DVS.take (forall a. Storable a => Vector a -> Int
DVS.length Vector Int64
s forall a. Num a => a -> a -> a
- Int
1) Vector Int64
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DVS.Vector Int) where
  unsnoc :: Vector Int -> Maybe (Elem (Vector Int), Vector Int)
unsnoc Vector Int
s = if forall a. Storable a => Vector a -> Int
DVS.length Vector Int
s forall a. Eq a => a -> a -> Bool
== Int
0 then forall a. Maybe a
Nothing else forall a. a -> Maybe a
Just (forall a. Storable a => Vector a -> a
DVS.last Vector Int
s, forall a. Storable a => Int -> Vector a -> Vector a
DVS.take (forall a. Storable a => Vector a -> Int
DVS.length Vector Int
s forall a. Num a => a -> a -> a
- Int
1) Vector Int
s)
  {-# INLINE unsnoc   #-}