{-# LANGUAGE DeriveAnyClass    #-}
{-# LANGUAGE DeriveGeneric     #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications  #-}

module HaskellWorks.CabalCache.AWS.S3.URI
  ( S3Uri(..)
  ) where

import Control.DeepSeq            (NFData)
import Data.Generics.Product.Any  (HasAny(the))
import HaskellWorks.Prelude
import Lens.Micro

import qualified Amazonka.Data.Text         as AWS
import qualified Amazonka.S3                as AWS
import qualified Data.Aeson                 as J
import qualified Data.Aeson.Types           as J
import qualified Data.Attoparsec.Combinator as DAC
import qualified Data.Attoparsec.Text       as DAT
import qualified Data.Text                  as T

data S3Uri = S3Uri
  { S3Uri -> BucketName
bucket    :: AWS.BucketName
  , S3Uri -> ObjectKey
objectKey :: AWS.ObjectKey
  } deriving (Int -> S3Uri -> ShowS
[S3Uri] -> ShowS
S3Uri -> String
(Int -> S3Uri -> ShowS)
-> (S3Uri -> String) -> ([S3Uri] -> ShowS) -> Show S3Uri
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> S3Uri -> ShowS
showsPrec :: Int -> S3Uri -> ShowS
$cshow :: S3Uri -> String
show :: S3Uri -> String
$cshowList :: [S3Uri] -> ShowS
showList :: [S3Uri] -> ShowS
Show, S3Uri -> S3Uri -> Bool
(S3Uri -> S3Uri -> Bool) -> (S3Uri -> S3Uri -> Bool) -> Eq S3Uri
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: S3Uri -> S3Uri -> Bool
== :: S3Uri -> S3Uri -> Bool
$c/= :: S3Uri -> S3Uri -> Bool
/= :: S3Uri -> S3Uri -> Bool
Eq, Eq S3Uri
Eq S3Uri =>
(S3Uri -> S3Uri -> Ordering)
-> (S3Uri -> S3Uri -> Bool)
-> (S3Uri -> S3Uri -> Bool)
-> (S3Uri -> S3Uri -> Bool)
-> (S3Uri -> S3Uri -> Bool)
-> (S3Uri -> S3Uri -> S3Uri)
-> (S3Uri -> S3Uri -> S3Uri)
-> Ord S3Uri
S3Uri -> S3Uri -> Bool
S3Uri -> S3Uri -> Ordering
S3Uri -> S3Uri -> S3Uri
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
$ccompare :: S3Uri -> S3Uri -> Ordering
compare :: S3Uri -> S3Uri -> Ordering
$c< :: S3Uri -> S3Uri -> Bool
< :: S3Uri -> S3Uri -> Bool
$c<= :: S3Uri -> S3Uri -> Bool
<= :: S3Uri -> S3Uri -> Bool
$c> :: S3Uri -> S3Uri -> Bool
> :: S3Uri -> S3Uri -> Bool
$c>= :: S3Uri -> S3Uri -> Bool
>= :: S3Uri -> S3Uri -> Bool
$cmax :: S3Uri -> S3Uri -> S3Uri
max :: S3Uri -> S3Uri -> S3Uri
$cmin :: S3Uri -> S3Uri -> S3Uri
min :: S3Uri -> S3Uri -> S3Uri
Ord, (forall x. S3Uri -> Rep S3Uri x)
-> (forall x. Rep S3Uri x -> S3Uri) -> Generic S3Uri
forall x. Rep S3Uri x -> S3Uri
forall x. S3Uri -> Rep S3Uri x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. S3Uri -> Rep S3Uri x
from :: forall x. S3Uri -> Rep S3Uri x
$cto :: forall x. Rep S3Uri x -> S3Uri
to :: forall x. Rep S3Uri x -> S3Uri
Generic, S3Uri -> ()
(S3Uri -> ()) -> NFData S3Uri
forall a. (a -> ()) -> NFData a
$crnf :: S3Uri -> ()
rnf :: S3Uri -> ()
NFData)

instance AWS.FromText S3Uri where
  fromText :: Text -> Either String S3Uri
fromText = Parser S3Uri -> Text -> Either String S3Uri
forall a. Parser a -> Text -> Either String a
DAT.parseOnly (Parser S3Uri -> Text -> Either String S3Uri)
-> Parser S3Uri -> Text -> Either String S3Uri
forall a b. (a -> b) -> a -> b
$ do
    Text
_  <- Text -> Parser Text
DAT.string Text
"s3://"
    BucketName
bn <- Text -> BucketName
AWS.BucketName (Text -> BucketName) -> (String -> Text) -> String -> BucketName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
T.pack (String -> BucketName)
-> Parser Text String -> Parser Text BucketName
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
DAC.many1 ((Char -> Bool) -> Parser Text Char
DAT.satisfy (\Char
c -> Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'/' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
' '))
    Maybe Char
_  <- Parser Text Char -> Parser Text (Maybe Char)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Char -> Parser Text Char
DAT.char Char
'/')
    ObjectKey
ok <- Text -> ObjectKey
AWS.ObjectKey (Text -> ObjectKey) -> (String -> Text) -> String -> ObjectKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
T.pack (String -> ObjectKey)
-> Parser Text String -> Parser Text ObjectKey
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Char -> Parser Text String
forall a. Parser Text a -> Parser Text [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many Parser Text Char
DAT.anyChar
    Parser Text ()
forall t. Chunk t => Parser t ()
DAT.endOfInput
    S3Uri -> Parser S3Uri
forall a. a -> Parser Text a
forall (m :: * -> *) a. Monad m => a -> m a
return (BucketName -> ObjectKey -> S3Uri
S3Uri BucketName
bn ObjectKey
ok)

instance AWS.ToText S3Uri where
  toText :: S3Uri -> Text
toText S3Uri
loc = BucketName -> ObjectKey -> Text
toS3Uri (S3Uri
loc S3Uri -> Getting BucketName S3Uri BucketName -> BucketName
forall s a. s -> Getting a s a -> a
^. forall {k} (sel :: k) s t a b. HasAny sel s t a b => Lens s t a b
forall (sel :: Symbol) s t a b. HasAny sel s t a b => Lens s t a b
the @"bucket") (S3Uri
loc S3Uri -> Getting ObjectKey S3Uri ObjectKey -> ObjectKey
forall s a. s -> Getting a s a -> a
^. forall {k} (sel :: k) s t a b. HasAny sel s t a b => Lens s t a b
forall (sel :: Symbol) s t a b. HasAny sel s t a b => Lens s t a b
the @"objectKey")

instance J.ToJSON S3Uri where
  toJSON :: S3Uri -> Value
toJSON S3Uri
s3Uri = Text -> Value
J.String (S3Uri -> Text
forall a. ToText a => a -> Text
AWS.toText S3Uri
s3Uri)

instance J.FromJSON S3Uri where
  parseJSON :: Value -> Parser S3Uri
parseJSON Value
v = case Value
v of
    J.String Text
s -> case Text -> Either String S3Uri
forall a. FromText a => Text -> Either String a
AWS.fromText Text
s of
      Right S3Uri
s3Uri -> S3Uri -> Parser S3Uri
forall a. a -> Parser a
forall (m :: * -> *) a. Monad m => a -> m a
return S3Uri
s3Uri
      Left String
msg    -> String -> Value -> Parser S3Uri
forall a. String -> Value -> Parser a
J.typeMismatch (String
"S3Uri (" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
msg String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
")") Value
v
    Value
_ -> String -> Value -> Parser S3Uri
forall a. String -> Value -> Parser a
J.typeMismatch String
"S3Uri" Value
v

toS3Uri :: AWS.BucketName -> AWS.ObjectKey -> Text
toS3Uri :: BucketName -> ObjectKey -> Text
toS3Uri (AWS.BucketName Text
b) (AWS.ObjectKey Text
k) = Text
"s3://" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
b Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"/" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
k