{-# LANGUAGE Trustworthy #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE UndecidableInstances #-} -- | -- Module : Codec.Rot13 -- Description : Fast ROT13 cipher for Haskell. -- Copyright : (c) Kyle Van Berendonck, 2014 -- License : BSD3 -- Maintainer : kvanberendonck@gmail.com -- Stability : experimental -- Portability : portable -- -- This module exposes the API for this package. module Codec.Rot13 ( -- * Typeclass Interfaces Rot13(..) , Rot13Bytes(..) -- * Constraint Interfaces , rot13enum , rot13int -- * Compatibility , rot13word , rot13word8 , rot13char , rot13string ) where import Data.Char import Data.Word import Data.Int import qualified Data.ByteString as BS import qualified Data.ByteString.Internal as BS import qualified Data.Text as Text import Foreign.Ptr import Foreign.Storable import qualified Foreign.C.Types as Foreign -- | The 'Rot13' typeclass is intended to perform the ROT13 cipher on the provided data, as if it -- were representing a single ANSI-encoded character. This interface doesn't consider the storage -- behaviour of the type at all, but is the fastest implementation if you need to integrate the -- transformation as part of a stream. class Rot13 a where rot13 :: a -> a -- | The 'Rot13Bytes' typeclass is intended for when you need to perform the ROT13 cipher on some -- data at the memory level. It stores the given data into a temporary buffer in memory, then runs -- the cipher over the stored bytes to produce a new buffer. This operation is typically slower -- than just using 'rot13' as part of a fusion pipeline. class Rot13Bytes a where rot13bs :: a -> BS.ByteString -- | Perform the ROT13 cipher on the given 'Integral' instance (in the sense of 'Rot13'). rot13int :: Integral a => a -> a rot13int x | (fromIntegral x :: Word) - 97 < 26 = 97 + rem (x - 84) 26 | (fromIntegral x :: Word) - 65 < 26 = 65 + rem (x - 52) 26 | otherwise = x {-# INLINE rot13int #-} {-# SPECIALIZE rot13int :: Word -> Word #-} {-# SPECIALIZE rot13int :: Word8 -> Word8 #-} {-# SPECIALIZE rot13int :: Word16 -> Word16 #-} {-# SPECIALIZE rot13int :: Word32 -> Word32 #-} {-# SPECIALIZE rot13int :: Word64 -> Word64 #-} {-# SPECIALIZE rot13int :: Int -> Int #-} {-# SPECIALIZE rot13int :: Int8 -> Int8 #-} {-# SPECIALIZE rot13int :: Int16 -> Int16 #-} {-# SPECIALIZE rot13int :: Int32 -> Int32 #-} {-# SPECIALIZE rot13int :: Int64 -> Int64 #-} {-# SPECIALIZE rot13int :: Integer -> Integer #-} {-# SPECIALIZE rot13int :: Foreign.CChar -> Foreign.CChar #-} {-# SPECIALIZE rot13int :: Foreign.CSChar -> Foreign.CSChar #-} {-# SPECIALIZE rot13int :: Foreign.CUChar -> Foreign.CUChar #-} {-# SPECIALIZE rot13int :: Foreign.CShort -> Foreign.CShort #-} {-# SPECIALIZE rot13int :: Foreign.CUShort -> Foreign.CUShort #-} {-# SPECIALIZE rot13int :: Foreign.CInt -> Foreign.CInt #-} {-# SPECIALIZE rot13int :: Foreign.CUInt -> Foreign.CUInt #-} {-# SPECIALIZE rot13int :: Foreign.CLong -> Foreign.CLong #-} {-# SPECIALIZE rot13int :: Foreign.CULong -> Foreign.CULong #-} {-# SPECIALIZE rot13int :: Foreign.CWchar -> Foreign.CWchar #-} {-# SPECIALIZE rot13int :: Foreign.CLLong -> Foreign.CLLong #-} {-# SPECIALIZE rot13int :: Foreign.CULLong -> Foreign.CULLong #-} -- | Perform the ROT13 cipher on the given 'Enum' instance (in the sense of 'Rot13'). {-# INLINE rot13enum #-} rot13enum :: Enum a => a -> a rot13enum = toEnum . (rot13int :: Int -> Int) . fromEnum -- | Perform the ROT13 cipher on the given 'Storable' instance bytes to yield a 'BS.ByteString'. {-# INLINE rot13stor #-} rot13stor :: Storable a => a -> BS.ByteString rot13stor x = rot13bs $! BS.unsafeCreate (sizeOf x) $ \ptr -> poke (castPtr ptr) x -------------------------------------------------------------------------------------------------- -- Rot13 Instances instance Rot13 Char where rot13 = rot13enum instance Rot13 String where rot13 = map rot13 instance Rot13 BS.ByteString where rot13 = BS.map rot13 instance Rot13 Text.Text where rot13 = Text.map rot13 instance Rot13 Word where rot13 = rot13int instance Rot13 Word8 where rot13 = rot13int instance Rot13 Word16 where rot13 = rot13int instance Rot13 Word32 where rot13 = rot13int instance Rot13 Word64 where rot13 = rot13int instance Rot13 Int where rot13 = rot13int instance Rot13 Int8 where rot13 = rot13int instance Rot13 Int16 where rot13 = rot13int instance Rot13 Int32 where rot13 = rot13int instance Rot13 Int64 where rot13 = rot13int instance Rot13 Integer where rot13 = rot13int instance Rot13 Foreign.CChar where rot13 = rot13 instance Rot13 Foreign.CSChar where rot13 = rot13 instance Rot13 Foreign.CUChar where rot13 = rot13 instance Rot13 Foreign.CShort where rot13 = rot13 instance Rot13 Foreign.CUShort where rot13 = rot13 instance Rot13 Foreign.CInt where rot13 = rot13 instance Rot13 Foreign.CUInt where rot13 = rot13 instance Rot13 Foreign.CLong where rot13 = rot13 instance Rot13 Foreign.CULong where rot13 = rot13 instance Rot13 Foreign.CWchar where rot13 = rot13 instance Rot13 Foreign.CLLong where rot13 = rot13 instance Rot13 Foreign.CULLong where rot13 = rot13 -------------------------------------------------------------------------------------------------- -- Rot13Bytes Instances instance {-# OVERLAPPING #-} Rot13Bytes BS.ByteString where rot13bs = rot13 instance {-# OVERLAPPING #-} Storable a => Rot13Bytes a where rot13bs = rot13stor -------------------------------------------------------------------------------------------------- -- Compatibility {-# INLINE rot13word #-} rot13word :: Word -> Word rot13word = rot13 {-# INLINE rot13word8 #-} rot13word8 :: Word8 -> Word8 rot13word8 = rot13 {-# INLINE rot13char #-} rot13char :: Char -> Char rot13char = rot13 {-# INLINE rot13string #-} rot13string :: String -> String rot13string = rot13