{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TypeApplications #-}
module Data.ByteString.Multibase
(
BaseN.Base(..)
, ToCode
, Multibase
, fromMultibase
, encodedBytes
, encode
, decode
, CompactMultibase
, compact
, expand
)
where
import Control.DeepSeq (NFData)
import Data.ByteString (ByteString)
import Data.ByteString.BaseN (AtBase, ValidBase)
import qualified Data.ByteString.BaseN as BaseN
import qualified Data.ByteString.Char8 as C8
import Data.ByteString.Short (ShortByteString, fromShort, toShort)
import Data.Coerce (coerce)
import Data.Hashable (Hashable)
import Data.Typeable
class ValidBase b => ToCode b where
toCode :: proxy b -> Char
instance ToCode "id" where
toCode :: proxy "id" -> Char
toCode = Char -> proxy "id" -> Char
forall a b. a -> b -> a
const Char
'\000'
instance ToCode "16" where
toCode :: proxy "16" -> Char
toCode = Char -> proxy "16" -> Char
forall a b. a -> b -> a
const Char
'f'
instance ToCode "16u" where
toCode :: proxy "16u" -> Char
toCode = Char -> proxy "16u" -> Char
forall a b. a -> b -> a
const Char
'F'
instance ToCode "32x" where
toCode :: proxy "32x" -> Char
toCode = Char -> proxy "32x" -> Char
forall a b. a -> b -> a
const Char
'v'
instance ToCode "32xu" where
toCode :: proxy "32xu" -> Char
toCode = Char -> proxy "32xu" -> Char
forall a b. a -> b -> a
const Char
'V'
instance ToCode "32xp" where
toCode :: proxy "32xp" -> Char
toCode = Char -> proxy "32xp" -> Char
forall a b. a -> b -> a
const Char
't'
instance ToCode "32xpu" where
toCode :: proxy "32xpu" -> Char
toCode = Char -> proxy "32xpu" -> Char
forall a b. a -> b -> a
const Char
'T'
instance ToCode "32" where
toCode :: proxy "32" -> Char
toCode = Char -> proxy "32" -> Char
forall a b. a -> b -> a
const Char
'b'
instance ToCode "32z" where
toCode :: proxy "32z" -> Char
toCode = Char -> proxy "32z" -> Char
forall a b. a -> b -> a
const Char
'h'
instance ToCode "32u" where
toCode :: proxy "32u" -> Char
toCode = Char -> proxy "32u" -> Char
forall a b. a -> b -> a
const Char
'B'
instance ToCode "32p" where
toCode :: proxy "32p" -> Char
toCode = Char -> proxy "32p" -> Char
forall a b. a -> b -> a
const Char
'c'
instance ToCode "32pu" where
toCode :: proxy "32pu" -> Char
toCode = Char -> proxy "32pu" -> Char
forall a b. a -> b -> a
const Char
'C'
instance ToCode "58flickr" where
toCode :: proxy "58flickr" -> Char
toCode = Char -> proxy "58flickr" -> Char
forall a b. a -> b -> a
const Char
'Z'
instance ToCode "58btc" where
toCode :: proxy "58btc" -> Char
toCode = Char -> proxy "58btc" -> Char
forall a b. a -> b -> a
const Char
'z'
instance ToCode "64" where
toCode :: proxy "64" -> Char
toCode = Char -> proxy "64" -> Char
forall a b. a -> b -> a
const Char
'm'
instance ToCode "64p" where
toCode :: proxy "64p" -> Char
toCode = Char -> proxy "64p" -> Char
forall a b. a -> b -> a
const Char
'M'
instance ToCode "64url" where
toCode :: proxy "64url" -> Char
toCode = Char -> proxy "64url" -> Char
forall a b. a -> b -> a
const Char
'u'
instance ToCode "64urlpad" where
toCode :: proxy "64urlpad" -> Char
toCode = Char -> proxy "64urlpad" -> Char
forall a b. a -> b -> a
const Char
'U'
fromCode :: Char -> Maybe (ByteString -> Either String ByteString)
fromCode :: Char -> Maybe (ByteString -> Either String ByteString)
fromCode Char
'\000' = (ByteString -> Either String ByteString)
-> Maybe (ByteString -> Either String ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ByteString -> Either String ByteString
forall (f :: * -> *) a. Applicative f => a -> f a
pure
fromCode Char
'f' = (ByteString -> Either String ByteString)
-> Maybe (ByteString -> Either String ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Proxy "16" -> ByteString -> Either String ByteString
forall (b :: Symbol) (proxy :: Symbol -> *).
DecodeBase b =>
proxy b -> ByteString -> Either String ByteString
BaseN.decodeAtBaseEither (Proxy "16"
forall k (t :: k). Proxy t
Proxy @"16"))
fromCode Char
'F' = (ByteString -> Either String ByteString)
-> Maybe (ByteString -> Either String ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Proxy "16u" -> ByteString -> Either String ByteString
forall (b :: Symbol) (proxy :: Symbol -> *).
DecodeBase b =>
proxy b -> ByteString -> Either String ByteString
BaseN.decodeAtBaseEither (Proxy "16u"
forall k (t :: k). Proxy t
Proxy @"16u"))
fromCode Char
'v' = (ByteString -> Either String ByteString)
-> Maybe (ByteString -> Either String ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Proxy "32x" -> ByteString -> Either String ByteString
forall (b :: Symbol) (proxy :: Symbol -> *).
DecodeBase b =>
proxy b -> ByteString -> Either String ByteString
BaseN.decodeAtBaseEither (Proxy "32x"
forall k (t :: k). Proxy t
Proxy @"32x"))
fromCode Char
'V' = (ByteString -> Either String ByteString)
-> Maybe (ByteString -> Either String ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Proxy "32xu" -> ByteString -> Either String ByteString
forall (b :: Symbol) (proxy :: Symbol -> *).
DecodeBase b =>
proxy b -> ByteString -> Either String ByteString
BaseN.decodeAtBaseEither (Proxy "32xu"
forall k (t :: k). Proxy t
Proxy @"32xu"))
fromCode Char
't' = (ByteString -> Either String ByteString)
-> Maybe (ByteString -> Either String ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Proxy "32xp" -> ByteString -> Either String ByteString
forall (b :: Symbol) (proxy :: Symbol -> *).
DecodeBase b =>
proxy b -> ByteString -> Either String ByteString
BaseN.decodeAtBaseEither (Proxy "32xp"
forall k (t :: k). Proxy t
Proxy @"32xp"))
fromCode Char
'T' = (ByteString -> Either String ByteString)
-> Maybe (ByteString -> Either String ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Proxy "32xpu" -> ByteString -> Either String ByteString
forall (b :: Symbol) (proxy :: Symbol -> *).
DecodeBase b =>
proxy b -> ByteString -> Either String ByteString
BaseN.decodeAtBaseEither (Proxy "32xpu"
forall k (t :: k). Proxy t
Proxy @"32xpu"))
fromCode Char
'b' = (ByteString -> Either String ByteString)
-> Maybe (ByteString -> Either String ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Proxy "32" -> ByteString -> Either String ByteString
forall (b :: Symbol) (proxy :: Symbol -> *).
DecodeBase b =>
proxy b -> ByteString -> Either String ByteString
BaseN.decodeAtBaseEither (Proxy "32"
forall k (t :: k). Proxy t
Proxy @"32"))
fromCode Char
'h' = (ByteString -> Either String ByteString)
-> Maybe (ByteString -> Either String ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Proxy "32z" -> ByteString -> Either String ByteString
forall (b :: Symbol) (proxy :: Symbol -> *).
DecodeBase b =>
proxy b -> ByteString -> Either String ByteString
BaseN.decodeAtBaseEither (Proxy "32z"
forall k (t :: k). Proxy t
Proxy @"32z"))
fromCode Char
'B' = (ByteString -> Either String ByteString)
-> Maybe (ByteString -> Either String ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Proxy "32u" -> ByteString -> Either String ByteString
forall (b :: Symbol) (proxy :: Symbol -> *).
DecodeBase b =>
proxy b -> ByteString -> Either String ByteString
BaseN.decodeAtBaseEither (Proxy "32u"
forall k (t :: k). Proxy t
Proxy @"32u"))
fromCode Char
'c' = (ByteString -> Either String ByteString)
-> Maybe (ByteString -> Either String ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Proxy "32p" -> ByteString -> Either String ByteString
forall (b :: Symbol) (proxy :: Symbol -> *).
DecodeBase b =>
proxy b -> ByteString -> Either String ByteString
BaseN.decodeAtBaseEither (Proxy "32p"
forall k (t :: k). Proxy t
Proxy @"32p"))
fromCode Char
'C' = (ByteString -> Either String ByteString)
-> Maybe (ByteString -> Either String ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Proxy "32pu" -> ByteString -> Either String ByteString
forall (b :: Symbol) (proxy :: Symbol -> *).
DecodeBase b =>
proxy b -> ByteString -> Either String ByteString
BaseN.decodeAtBaseEither (Proxy "32pu"
forall k (t :: k). Proxy t
Proxy @"32pu"))
fromCode Char
'Z' = (ByteString -> Either String ByteString)
-> Maybe (ByteString -> Either String ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Proxy "58flickr" -> ByteString -> Either String ByteString
forall (b :: Symbol) (proxy :: Symbol -> *).
DecodeBase b =>
proxy b -> ByteString -> Either String ByteString
BaseN.decodeAtBaseEither (Proxy "58flickr"
forall k (t :: k). Proxy t
Proxy @"58flickr"))
fromCode Char
'z' = (ByteString -> Either String ByteString)
-> Maybe (ByteString -> Either String ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Proxy "58btc" -> ByteString -> Either String ByteString
forall (b :: Symbol) (proxy :: Symbol -> *).
DecodeBase b =>
proxy b -> ByteString -> Either String ByteString
BaseN.decodeAtBaseEither (Proxy "58btc"
forall k (t :: k). Proxy t
Proxy @"58btc"))
fromCode Char
'm' = (ByteString -> Either String ByteString)
-> Maybe (ByteString -> Either String ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Proxy "64" -> ByteString -> Either String ByteString
forall (b :: Symbol) (proxy :: Symbol -> *).
DecodeBase b =>
proxy b -> ByteString -> Either String ByteString
BaseN.decodeAtBaseEither (Proxy "64"
forall k (t :: k). Proxy t
Proxy @"64"))
fromCode Char
'M' = (ByteString -> Either String ByteString)
-> Maybe (ByteString -> Either String ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Proxy "64p" -> ByteString -> Either String ByteString
forall (b :: Symbol) (proxy :: Symbol -> *).
DecodeBase b =>
proxy b -> ByteString -> Either String ByteString
BaseN.decodeAtBaseEither (Proxy "64p"
forall k (t :: k). Proxy t
Proxy @"64p"))
fromCode Char
'u' = (ByteString -> Either String ByteString)
-> Maybe (ByteString -> Either String ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Proxy "64url" -> ByteString -> Either String ByteString
forall (b :: Symbol) (proxy :: Symbol -> *).
DecodeBase b =>
proxy b -> ByteString -> Either String ByteString
BaseN.decodeAtBaseEither (Proxy "64url"
forall k (t :: k). Proxy t
Proxy @"64url"))
fromCode Char
'U' = (ByteString -> Either String ByteString)
-> Maybe (ByteString -> Either String ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Proxy "64urlpad" -> ByteString -> Either String ByteString
forall (b :: Symbol) (proxy :: Symbol -> *).
DecodeBase b =>
proxy b -> ByteString -> Either String ByteString
BaseN.decodeAtBaseEither (Proxy "64urlpad"
forall k (t :: k). Proxy t
Proxy @"64urlpad"))
fromCode Char
_ = Maybe (ByteString -> Either String ByteString)
forall a. Maybe a
Nothing
newtype Multibase = Multibase ByteString
deriving (Multibase -> Multibase -> Bool
(Multibase -> Multibase -> Bool)
-> (Multibase -> Multibase -> Bool) -> Eq Multibase
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Multibase -> Multibase -> Bool
$c/= :: Multibase -> Multibase -> Bool
== :: Multibase -> Multibase -> Bool
$c== :: Multibase -> Multibase -> Bool
Eq, Eq Multibase
Eq Multibase
-> (Multibase -> Multibase -> Ordering)
-> (Multibase -> Multibase -> Bool)
-> (Multibase -> Multibase -> Bool)
-> (Multibase -> Multibase -> Bool)
-> (Multibase -> Multibase -> Bool)
-> (Multibase -> Multibase -> Multibase)
-> (Multibase -> Multibase -> Multibase)
-> Ord Multibase
Multibase -> Multibase -> Bool
Multibase -> Multibase -> Ordering
Multibase -> Multibase -> Multibase
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 :: Multibase -> Multibase -> Multibase
$cmin :: Multibase -> Multibase -> Multibase
max :: Multibase -> Multibase -> Multibase
$cmax :: Multibase -> Multibase -> Multibase
>= :: Multibase -> Multibase -> Bool
$c>= :: Multibase -> Multibase -> Bool
> :: Multibase -> Multibase -> Bool
$c> :: Multibase -> Multibase -> Bool
<= :: Multibase -> Multibase -> Bool
$c<= :: Multibase -> Multibase -> Bool
< :: Multibase -> Multibase -> Bool
$c< :: Multibase -> Multibase -> Bool
compare :: Multibase -> Multibase -> Ordering
$ccompare :: Multibase -> Multibase -> Ordering
$cp1Ord :: Eq Multibase
Ord, Int -> Multibase -> Int
Multibase -> Int
(Int -> Multibase -> Int)
-> (Multibase -> Int) -> Hashable Multibase
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: Multibase -> Int
$chash :: Multibase -> Int
hashWithSalt :: Int -> Multibase -> Int
$chashWithSalt :: Int -> Multibase -> Int
Hashable, Multibase -> ()
(Multibase -> ()) -> NFData Multibase
forall a. (a -> ()) -> NFData a
rnf :: Multibase -> ()
$crnf :: Multibase -> ()
NFData)
newtype CompactMultibase = Compact ShortByteString
deriving (CompactMultibase -> CompactMultibase -> Bool
(CompactMultibase -> CompactMultibase -> Bool)
-> (CompactMultibase -> CompactMultibase -> Bool)
-> Eq CompactMultibase
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CompactMultibase -> CompactMultibase -> Bool
$c/= :: CompactMultibase -> CompactMultibase -> Bool
== :: CompactMultibase -> CompactMultibase -> Bool
$c== :: CompactMultibase -> CompactMultibase -> Bool
Eq, Eq CompactMultibase
Eq CompactMultibase
-> (CompactMultibase -> CompactMultibase -> Ordering)
-> (CompactMultibase -> CompactMultibase -> Bool)
-> (CompactMultibase -> CompactMultibase -> Bool)
-> (CompactMultibase -> CompactMultibase -> Bool)
-> (CompactMultibase -> CompactMultibase -> Bool)
-> (CompactMultibase -> CompactMultibase -> CompactMultibase)
-> (CompactMultibase -> CompactMultibase -> CompactMultibase)
-> Ord CompactMultibase
CompactMultibase -> CompactMultibase -> Bool
CompactMultibase -> CompactMultibase -> Ordering
CompactMultibase -> CompactMultibase -> CompactMultibase
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 :: CompactMultibase -> CompactMultibase -> CompactMultibase
$cmin :: CompactMultibase -> CompactMultibase -> CompactMultibase
max :: CompactMultibase -> CompactMultibase -> CompactMultibase
$cmax :: CompactMultibase -> CompactMultibase -> CompactMultibase
>= :: CompactMultibase -> CompactMultibase -> Bool
$c>= :: CompactMultibase -> CompactMultibase -> Bool
> :: CompactMultibase -> CompactMultibase -> Bool
$c> :: CompactMultibase -> CompactMultibase -> Bool
<= :: CompactMultibase -> CompactMultibase -> Bool
$c<= :: CompactMultibase -> CompactMultibase -> Bool
< :: CompactMultibase -> CompactMultibase -> Bool
$c< :: CompactMultibase -> CompactMultibase -> Bool
compare :: CompactMultibase -> CompactMultibase -> Ordering
$ccompare :: CompactMultibase -> CompactMultibase -> Ordering
$cp1Ord :: Eq CompactMultibase
Ord, Int -> CompactMultibase -> Int
CompactMultibase -> Int
(Int -> CompactMultibase -> Int)
-> (CompactMultibase -> Int) -> Hashable CompactMultibase
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: CompactMultibase -> Int
$chash :: CompactMultibase -> Int
hashWithSalt :: Int -> CompactMultibase -> Int
$chashWithSalt :: Int -> CompactMultibase -> Int
Hashable, CompactMultibase -> ()
(CompactMultibase -> ()) -> NFData CompactMultibase
forall a. (a -> ()) -> NFData a
rnf :: CompactMultibase -> ()
$crnf :: CompactMultibase -> ()
NFData)
fromMultibase :: Multibase -> ByteString
fromMultibase :: Multibase -> ByteString
fromMultibase = Multibase -> ByteString
coerce
encodedBytes :: Multibase -> ByteString
encodedBytes :: Multibase -> ByteString
encodedBytes = ByteString -> ByteString
C8.tail (ByteString -> ByteString)
-> (Multibase -> ByteString) -> Multibase -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Multibase -> ByteString
coerce
encode :: ToCode b => AtBase b -> Multibase
encode :: AtBase b -> Multibase
encode AtBase b
base = ByteString -> Multibase
coerce (ByteString -> Multibase)
-> (AtBase b -> ByteString) -> AtBase b -> Multibase
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ByteString -> ByteString
C8.cons (AtBase b -> Char
forall (b :: Symbol) (proxy :: Symbol -> *).
ToCode b =>
proxy b -> Char
toCode AtBase b
base) (ByteString -> ByteString)
-> (AtBase b -> ByteString) -> AtBase b -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AtBase b -> ByteString
forall (b :: Symbol). AtBase b -> ByteString
BaseN.encodedBytes (AtBase b -> Multibase) -> AtBase b -> Multibase
forall a b. (a -> b) -> a -> b
$ AtBase b
base
decode :: ByteString -> Either String ByteString
decode :: ByteString -> Either String ByteString
decode ByteString
bs = do
(Char
c, ByteString
bs') <- String
-> Maybe (Char, ByteString) -> Either String (Char, ByteString)
forall a b. a -> Maybe b -> Either a b
note String
"Empty input" (Maybe (Char, ByteString) -> Either String (Char, ByteString))
-> Maybe (Char, ByteString) -> Either String (Char, ByteString)
forall a b. (a -> b) -> a -> b
$ ByteString -> Maybe (Char, ByteString)
C8.uncons ByteString
bs
case Char -> Maybe (ByteString -> Either String ByteString)
fromCode Char
c of
Just ByteString -> Either String ByteString
decodeIt -> ByteString -> Either String ByteString
decodeIt ByteString
bs'
Maybe (ByteString -> Either String ByteString)
Nothing -> String -> Either String ByteString
forall a b. a -> Either a b
Left (String -> Either String ByteString)
-> String -> Either String ByteString
forall a b. (a -> b) -> a -> b
$ String
"Unknown encoding " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Char -> String
forall a. Show a => a -> String
show Char
c
compact :: Multibase -> CompactMultibase
compact :: Multibase -> CompactMultibase
compact = ShortByteString -> CompactMultibase
coerce (ShortByteString -> CompactMultibase)
-> (Multibase -> ShortByteString) -> Multibase -> CompactMultibase
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ShortByteString
toShort (ByteString -> ShortByteString)
-> (Multibase -> ByteString) -> Multibase -> ShortByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Multibase -> ByteString
coerce
{-# INLINE compact #-}
expand :: CompactMultibase -> Multibase
expand :: CompactMultibase -> Multibase
expand = ByteString -> Multibase
coerce (ByteString -> Multibase)
-> (CompactMultibase -> ByteString)
-> CompactMultibase
-> Multibase
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShortByteString -> ByteString
fromShort (ShortByteString -> ByteString)
-> (CompactMultibase -> ShortByteString)
-> CompactMultibase
-> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CompactMultibase -> ShortByteString
coerce
{-# INLINE expand #-}
note :: a -> Maybe b -> Either a b
note :: a -> Maybe b -> Either a b
note a
a = Either a b -> (b -> Either a b) -> Maybe b -> Either a b
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (a -> Either a b
forall a b. a -> Either a b
Left a
a) b -> Either a b
forall (f :: * -> *) a. Applicative f => a -> f a
pure