{-# LANGUAGE FlexibleInstances #-}

module Tahoe.Directory.Internal.Capability where

import qualified Data.Text as T
import Data.Void (Void)
import qualified Tahoe.CHK.Capability as CHK
import Tahoe.Capability (ConfidentialShowable (..))
import qualified Tahoe.SDMF as SDMF

import Text.Megaparsec (Parsec, getInput, setInput)

{- | A wrapper around some other capability type which signals that the
 plaintext is an encoded list of files.
-}
newtype DirectoryCapability a = DirectoryCapability a deriving (DirectoryCapability a -> DirectoryCapability a -> Bool
(DirectoryCapability a -> DirectoryCapability a -> Bool)
-> (DirectoryCapability a -> DirectoryCapability a -> Bool)
-> Eq (DirectoryCapability a)
forall a.
Eq a =>
DirectoryCapability a -> DirectoryCapability a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DirectoryCapability a -> DirectoryCapability a -> Bool
$c/= :: forall a.
Eq a =>
DirectoryCapability a -> DirectoryCapability a -> Bool
== :: DirectoryCapability a -> DirectoryCapability a -> Bool
$c== :: forall a.
Eq a =>
DirectoryCapability a -> DirectoryCapability a -> Bool
Eq, Eq (DirectoryCapability a)
Eq (DirectoryCapability a)
-> (DirectoryCapability a -> DirectoryCapability a -> Ordering)
-> (DirectoryCapability a -> DirectoryCapability a -> Bool)
-> (DirectoryCapability a -> DirectoryCapability a -> Bool)
-> (DirectoryCapability a -> DirectoryCapability a -> Bool)
-> (DirectoryCapability a -> DirectoryCapability a -> Bool)
-> (DirectoryCapability a
    -> DirectoryCapability a -> DirectoryCapability a)
-> (DirectoryCapability a
    -> DirectoryCapability a -> DirectoryCapability a)
-> Ord (DirectoryCapability a)
DirectoryCapability a -> DirectoryCapability a -> Bool
DirectoryCapability a -> DirectoryCapability a -> Ordering
DirectoryCapability a
-> DirectoryCapability a -> DirectoryCapability a
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
forall a. Ord a => Eq (DirectoryCapability a)
forall a.
Ord a =>
DirectoryCapability a -> DirectoryCapability a -> Bool
forall a.
Ord a =>
DirectoryCapability a -> DirectoryCapability a -> Ordering
forall a.
Ord a =>
DirectoryCapability a
-> DirectoryCapability a -> DirectoryCapability a
min :: DirectoryCapability a
-> DirectoryCapability a -> DirectoryCapability a
$cmin :: forall a.
Ord a =>
DirectoryCapability a
-> DirectoryCapability a -> DirectoryCapability a
max :: DirectoryCapability a
-> DirectoryCapability a -> DirectoryCapability a
$cmax :: forall a.
Ord a =>
DirectoryCapability a
-> DirectoryCapability a -> DirectoryCapability a
>= :: DirectoryCapability a -> DirectoryCapability a -> Bool
$c>= :: forall a.
Ord a =>
DirectoryCapability a -> DirectoryCapability a -> Bool
> :: DirectoryCapability a -> DirectoryCapability a -> Bool
$c> :: forall a.
Ord a =>
DirectoryCapability a -> DirectoryCapability a -> Bool
<= :: DirectoryCapability a -> DirectoryCapability a -> Bool
$c<= :: forall a.
Ord a =>
DirectoryCapability a -> DirectoryCapability a -> Bool
< :: DirectoryCapability a -> DirectoryCapability a -> Bool
$c< :: forall a.
Ord a =>
DirectoryCapability a -> DirectoryCapability a -> Bool
compare :: DirectoryCapability a -> DirectoryCapability a -> Ordering
$ccompare :: forall a.
Ord a =>
DirectoryCapability a -> DirectoryCapability a -> Ordering
$cp1Ord :: forall a. Ord a => Eq (DirectoryCapability a)
Ord, Int -> DirectoryCapability a -> ShowS
[DirectoryCapability a] -> ShowS
DirectoryCapability a -> String
(Int -> DirectoryCapability a -> ShowS)
-> (DirectoryCapability a -> String)
-> ([DirectoryCapability a] -> ShowS)
-> Show (DirectoryCapability a)
forall a. Show a => Int -> DirectoryCapability a -> ShowS
forall a. Show a => [DirectoryCapability a] -> ShowS
forall a. Show a => DirectoryCapability a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [DirectoryCapability a] -> ShowS
$cshowList :: forall a. Show a => [DirectoryCapability a] -> ShowS
show :: DirectoryCapability a -> String
$cshow :: forall a. Show a => DirectoryCapability a -> String
showsPrec :: Int -> DirectoryCapability a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> DirectoryCapability a -> ShowS
Show)

instance ConfidentialShowable (DirectoryCapability CHK.Verifier) where
    confidentiallyShow :: DirectoryCapability Verifier -> Text
confidentiallyShow (DirectoryCapability Verifier
a) =
        Text -> Text -> Text -> Text
T.replace Text
"URI:CHK-Verifier:" Text
"URI:DIR2-CHK-Verifier:" (CHK -> Text
CHK.dangerRealShow (Verifier -> CHK
CHK.CHKVerifier Verifier
a))

instance ConfidentialShowable (DirectoryCapability CHK.Reader) where
    confidentiallyShow :: DirectoryCapability Reader -> Text
confidentiallyShow (DirectoryCapability Reader
a) =
        Text -> Text -> Text -> Text
T.replace Text
"URI:CHK:" Text
"URI:DIR2-CHK:" (CHK -> Text
CHK.dangerRealShow (Reader -> CHK
CHK.CHKReader Reader
a))

instance ConfidentialShowable (DirectoryCapability SDMF.Verifier) where
    confidentiallyShow :: DirectoryCapability Verifier -> Text
confidentiallyShow (DirectoryCapability Verifier
a) =
        Text -> Text -> Text -> Text
T.replace Text
"URI:SSK-Verifier:" Text
"URI:DIR2-Verifier:" (Verifier -> Text
forall s. ConfidentialShowable s => s -> Text
confidentiallyShow Verifier
a)

instance ConfidentialShowable (DirectoryCapability SDMF.Reader) where
    confidentiallyShow :: DirectoryCapability Reader -> Text
confidentiallyShow (DirectoryCapability Reader
a) =
        Text -> Text -> Text -> Text
T.replace Text
"URI:SSK-RO:" Text
"URI:DIR2-RO:" (Reader -> Text
forall s. ConfidentialShowable s => s -> Text
confidentiallyShow Reader
a)

instance ConfidentialShowable (DirectoryCapability SDMF.Writer) where
    confidentiallyShow :: DirectoryCapability Writer -> Text
confidentiallyShow (DirectoryCapability Writer
a) =
        Text -> Text -> Text -> Text
T.replace Text
"URI:SSK:" Text
"URI:DIR2:" (Writer -> Text
forall s. ConfidentialShowable s => s -> Text
confidentiallyShow Writer
a)

type Parser = Parsec Void T.Text

{- | Parse a CHK directory verifier capability.

 The implementation is a cheesy hack that does string substitution on the
 input before applying the original CHK verifier parser.
-}
pVerifyCHK :: Parser (DirectoryCapability CHK.Verifier)
pVerifyCHK :: Parser (DirectoryCapability Verifier)
pVerifyCHK = do
    Text
s <- ParsecT Void Text Identity Text
forall e s (m :: * -> *). MonadParsec e s m => m s
getInput
    Text -> ParsecT Void Text Identity ()
forall e s (m :: * -> *). MonadParsec e s m => s -> m ()
setInput (Text -> ParsecT Void Text Identity ())
-> Text -> ParsecT Void Text Identity ()
forall a b. (a -> b) -> a -> b
$ Text -> Text -> Text -> Text
T.replace Text
"URI:DIR2-CHK-Verifier:" Text
"URI:CHK-Verifier:" Text
s
    Verifier -> DirectoryCapability Verifier
forall a. a -> DirectoryCapability a
DirectoryCapability (Verifier -> DirectoryCapability Verifier)
-> ParsecT Void Text Identity Verifier
-> Parser (DirectoryCapability Verifier)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT Void Text Identity Verifier
CHK.pVerifier

{- | Parse a CHK directory reader capability.

 The implementation is a cheesy hack that does string substitution on the
 input before applying the original CHK reader parser.
-}
pReadCHK :: Parser (DirectoryCapability CHK.Reader)
pReadCHK :: Parser (DirectoryCapability Reader)
pReadCHK = do
    Text
s <- ParsecT Void Text Identity Text
forall e s (m :: * -> *). MonadParsec e s m => m s
getInput
    Text -> ParsecT Void Text Identity ()
forall e s (m :: * -> *). MonadParsec e s m => s -> m ()
setInput (Text -> ParsecT Void Text Identity ())
-> Text -> ParsecT Void Text Identity ()
forall a b. (a -> b) -> a -> b
$ Text -> Text -> Text -> Text
T.replace Text
"URI:DIR2-CHK:" Text
"URI:CHK:" Text
s
    Reader -> DirectoryCapability Reader
forall a. a -> DirectoryCapability a
DirectoryCapability (Reader -> DirectoryCapability Reader)
-> ParsecT Void Text Identity Reader
-> Parser (DirectoryCapability Reader)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT Void Text Identity Reader
CHK.pReader

{- | Parse an SDMF directory verifier capability.  As is the case for the other
 directory capability parsers, the implementation is cheesy.
-}
pVerifySDMF :: Parser (DirectoryCapability SDMF.Verifier)
pVerifySDMF :: Parser (DirectoryCapability Verifier)
pVerifySDMF = do
    Text
s <- ParsecT Void Text Identity Text
forall e s (m :: * -> *). MonadParsec e s m => m s
getInput
    Text -> ParsecT Void Text Identity ()
forall e s (m :: * -> *). MonadParsec e s m => s -> m ()
setInput (Text -> ParsecT Void Text Identity ())
-> Text -> ParsecT Void Text Identity ()
forall a b. (a -> b) -> a -> b
$ Text -> Text -> Text -> Text
T.replace Text
"URI:DIR2-Verifier:" Text
"URI:SSK-Verifier:" Text
s
    Verifier -> DirectoryCapability Verifier
forall a. a -> DirectoryCapability a
DirectoryCapability (Verifier -> DirectoryCapability Verifier)
-> ParsecT Void Text Identity Verifier
-> Parser (DirectoryCapability Verifier)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT Void Text Identity Verifier
SDMF.pVerifier

{- | Parse an SDMF directory reader capability.  As is the case for the other
 directory capability parsers, the implementation is cheesy.
-}
pReadSDMF :: Parser (DirectoryCapability SDMF.Reader)
pReadSDMF :: Parser (DirectoryCapability Reader)
pReadSDMF = do
    Text
s <- ParsecT Void Text Identity Text
forall e s (m :: * -> *). MonadParsec e s m => m s
getInput
    Text -> ParsecT Void Text Identity ()
forall e s (m :: * -> *). MonadParsec e s m => s -> m ()
setInput (Text -> ParsecT Void Text Identity ())
-> Text -> ParsecT Void Text Identity ()
forall a b. (a -> b) -> a -> b
$ Text -> Text -> Text -> Text
T.replace Text
"URI:DIR2-RO:" Text
"URI:SSK-RO:" Text
s
    Reader -> DirectoryCapability Reader
forall a. a -> DirectoryCapability a
DirectoryCapability (Reader -> DirectoryCapability Reader)
-> ParsecT Void Text Identity Reader
-> Parser (DirectoryCapability Reader)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT Void Text Identity Reader
SDMF.pReader

{- | Parse an SDMF directory writer capability.  As is the case for the other
 directory capability parsers, the implementation is cheesy.
-}
pWriteSDMF :: Parser (DirectoryCapability SDMF.Writer)
pWriteSDMF :: Parser (DirectoryCapability Writer)
pWriteSDMF = do
    Text
s <- ParsecT Void Text Identity Text
forall e s (m :: * -> *). MonadParsec e s m => m s
getInput
    Text -> ParsecT Void Text Identity ()
forall e s (m :: * -> *). MonadParsec e s m => s -> m ()
setInput (Text -> ParsecT Void Text Identity ())
-> Text -> ParsecT Void Text Identity ()
forall a b. (a -> b) -> a -> b
$ Text -> Text -> Text -> Text
T.replace Text
"URI:DIR2:" Text
"URI:SSK:" Text
s
    Writer -> DirectoryCapability Writer
forall a. a -> DirectoryCapability a
DirectoryCapability (Writer -> DirectoryCapability Writer)
-> ParsecT Void Text Identity Writer
-> Parser (DirectoryCapability Writer)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT Void Text Identity Writer
SDMF.pWriter