{-# OPTIONS_GHC -Wno-orphans #-}

module Data.Vector.Orphans () where

import Data.Hashable (Hashable (hashWithSalt))
import Data.Vector.Strict qualified as Strict
import Flat (Flat (..))
import Flat.Instances.Vector ()

instance (Hashable a) => Hashable (Strict.Vector a) where
  hashWithSalt :: Int -> Vector a -> Int
hashWithSalt = (Int -> a -> Int) -> Int -> Vector a -> Int
forall a b. (a -> b -> a) -> a -> Vector b -> a
Strict.foldl' Int -> a -> Int
forall a. Hashable a => Int -> a -> Int
hashWithSalt

{- The `flat` library does not provide a `Flat` instance for
`Vector.Strict.Vector`.  We could encode and decode strict vectors by converting
them to and from lazy vectors (for which there is a `Flat` instance), but
experiments show that deserialisation is actually faster by about 5-10% if we
encode vectors as lists.  This incurs a slight size penalty (lists require one
bit of overhead per entry whereas vectors can be encoded with an overhead of one
byte per 255 elements), but this is offset by the decoding speedup.  Encoding
vectors as lists also simplifies maintenance and specification. -}
instance (Flat a) => Flat (Strict.Vector a) where
  size :: Vector a -> Int -> Int
size = [a] -> Int -> Int
forall a. Flat a => a -> Int -> Int
size ([a] -> Int -> Int) -> (Vector a -> [a]) -> Vector a -> Int -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector a -> [a]
forall a. Vector a -> [a]
Strict.toList
  encode :: Vector a -> Encoding
encode = [a] -> Encoding
forall a. Flat a => a -> Encoding
encode ([a] -> Encoding) -> (Vector a -> [a]) -> Vector a -> Encoding
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector a -> [a]
forall a. Vector a -> [a]
Strict.toList
  decode :: Get (Vector a)
decode = [a] -> Vector a
forall a. [a] -> Vector a
Strict.fromList ([a] -> Vector a) -> Get [a] -> Get (Vector a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get [a]
forall a. Flat a => Get a
decode