module Aws.SimpleDb.Core where import Aws.Core import qualified Blaze.ByteString.Builder as Blaze import qualified Blaze.ByteString.Builder.Char8 as Blaze8 import qualified Control.Exception as C import Control.Monad import Control.Monad.Trans.Resource (MonadThrow, throwM) import qualified Data.ByteString as B import qualified Data.ByteString.Base64 as Base64 import Data.IORef import Data.List import Data.Maybe import Data.Monoid import qualified Data.Semigroup as Sem import qualified Data.Text as T import qualified Data.Text.Encoding as T import Data.Typeable import Prelude import qualified Network.HTTP.Conduit as HTTP import qualified Network.HTTP.Types as HTTP import Text.XML.Cursor (($|), ($/), ($//), (&|)) import qualified Text.XML.Cursor as Cu type ErrorCode = String data SdbError = SdbError { SdbError -> Status sdbStatusCode :: HTTP.Status , SdbError -> ErrorCode sdbErrorCode :: ErrorCode , SdbError -> ErrorCode sdbErrorMessage :: String } deriving (Int -> SdbError -> ShowS [SdbError] -> ShowS SdbError -> ErrorCode (Int -> SdbError -> ShowS) -> (SdbError -> ErrorCode) -> ([SdbError] -> ShowS) -> Show SdbError forall a. (Int -> a -> ShowS) -> (a -> ErrorCode) -> ([a] -> ShowS) -> Show a showList :: [SdbError] -> ShowS $cshowList :: [SdbError] -> ShowS show :: SdbError -> ErrorCode $cshow :: SdbError -> ErrorCode showsPrec :: Int -> SdbError -> ShowS $cshowsPrec :: Int -> SdbError -> ShowS Show, Typeable) instance C.Exception SdbError data SdbMetadata = SdbMetadata { SdbMetadata -> Maybe Text requestId :: Maybe T.Text , SdbMetadata -> Maybe Text boxUsage :: Maybe T.Text } deriving (Int -> SdbMetadata -> ShowS [SdbMetadata] -> ShowS SdbMetadata -> ErrorCode (Int -> SdbMetadata -> ShowS) -> (SdbMetadata -> ErrorCode) -> ([SdbMetadata] -> ShowS) -> Show SdbMetadata forall a. (Int -> a -> ShowS) -> (a -> ErrorCode) -> ([a] -> ShowS) -> Show a showList :: [SdbMetadata] -> ShowS $cshowList :: [SdbMetadata] -> ShowS show :: SdbMetadata -> ErrorCode $cshow :: SdbMetadata -> ErrorCode showsPrec :: Int -> SdbMetadata -> ShowS $cshowsPrec :: Int -> SdbMetadata -> ShowS Show, Typeable) instance Loggable SdbMetadata where toLogText :: SdbMetadata -> Text toLogText (SdbMetadata Maybe Text rid Maybe Text bu) = Text "SimpleDB: request ID=" Text -> Text -> Text forall a. Monoid a => a -> a -> a `mappend` Text -> Maybe Text -> Text forall a. a -> Maybe a -> a fromMaybe Text "<none>" Maybe Text rid Text -> Text -> Text forall a. Monoid a => a -> a -> a `mappend` Text ", box usage=" Text -> Text -> Text forall a. Monoid a => a -> a -> a `mappend` Text -> Maybe Text -> Text forall a. a -> Maybe a -> a fromMaybe Text "<not available>" Maybe Text bu instance Sem.Semigroup SdbMetadata where SdbMetadata Maybe Text r1 Maybe Text b1 <> :: SdbMetadata -> SdbMetadata -> SdbMetadata <> SdbMetadata Maybe Text r2 Maybe Text b2 = Maybe Text -> Maybe Text -> SdbMetadata SdbMetadata (Maybe Text r1 Maybe Text -> Maybe Text -> Maybe Text forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a `mplus` Maybe Text r2) (Maybe Text b1 Maybe Text -> Maybe Text -> Maybe Text forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a `mplus` Maybe Text b2) instance Monoid SdbMetadata where mempty :: SdbMetadata mempty = Maybe Text -> Maybe Text -> SdbMetadata SdbMetadata Maybe Text forall a. Maybe a Nothing Maybe Text forall a. Maybe a Nothing mappend :: SdbMetadata -> SdbMetadata -> SdbMetadata mappend = SdbMetadata -> SdbMetadata -> SdbMetadata forall a. Semigroup a => a -> a -> a (Sem.<>) data SdbConfiguration qt = SdbConfiguration { SdbConfiguration qt -> Protocol sdbiProtocol :: Protocol , SdbConfiguration qt -> Method sdbiHttpMethod :: Method , SdbConfiguration qt -> ByteString sdbiHost :: B.ByteString , SdbConfiguration qt -> Int sdbiPort :: Int } deriving (Int -> SdbConfiguration qt -> ShowS [SdbConfiguration qt] -> ShowS SdbConfiguration qt -> ErrorCode (Int -> SdbConfiguration qt -> ShowS) -> (SdbConfiguration qt -> ErrorCode) -> ([SdbConfiguration qt] -> ShowS) -> Show (SdbConfiguration qt) forall qt. Int -> SdbConfiguration qt -> ShowS forall qt. [SdbConfiguration qt] -> ShowS forall qt. SdbConfiguration qt -> ErrorCode forall a. (Int -> a -> ShowS) -> (a -> ErrorCode) -> ([a] -> ShowS) -> Show a showList :: [SdbConfiguration qt] -> ShowS $cshowList :: forall qt. [SdbConfiguration qt] -> ShowS show :: SdbConfiguration qt -> ErrorCode $cshow :: forall qt. SdbConfiguration qt -> ErrorCode showsPrec :: Int -> SdbConfiguration qt -> ShowS $cshowsPrec :: forall qt. Int -> SdbConfiguration qt -> ShowS Show) instance DefaultServiceConfiguration (SdbConfiguration NormalQuery) where defServiceConfig :: SdbConfiguration NormalQuery defServiceConfig = ByteString -> SdbConfiguration NormalQuery sdbHttpsPost ByteString sdbUsEast debugServiceConfig :: SdbConfiguration NormalQuery debugServiceConfig = ByteString -> SdbConfiguration NormalQuery sdbHttpPost ByteString sdbUsEast instance DefaultServiceConfiguration (SdbConfiguration UriOnlyQuery) where defServiceConfig :: SdbConfiguration UriOnlyQuery defServiceConfig = ByteString -> SdbConfiguration UriOnlyQuery forall qt. ByteString -> SdbConfiguration qt sdbHttpsGet ByteString sdbUsEast debugServiceConfig :: SdbConfiguration UriOnlyQuery debugServiceConfig = ByteString -> SdbConfiguration UriOnlyQuery forall qt. ByteString -> SdbConfiguration qt sdbHttpGet ByteString sdbUsEast sdbUsEast :: B.ByteString sdbUsEast :: ByteString sdbUsEast = ByteString "sdb.amazonaws.com" sdbUsWest :: B.ByteString sdbUsWest :: ByteString sdbUsWest = ByteString "sdb.us-west-1.amazonaws.com" sdbEuWest :: B.ByteString sdbEuWest :: ByteString sdbEuWest = ByteString "sdb.eu-west-1.amazonaws.com" sdbApSoutheast :: B.ByteString sdbApSoutheast :: ByteString sdbApSoutheast = ByteString "sdb.ap-southeast-1.amazonaws.com" sdbApNortheast :: B.ByteString sdbApNortheast :: ByteString sdbApNortheast = ByteString "sdb.ap-northeast-1.amazonaws.com" sdbHttpGet :: B.ByteString -> SdbConfiguration qt sdbHttpGet :: ByteString -> SdbConfiguration qt sdbHttpGet ByteString endpoint = Protocol -> Method -> ByteString -> Int -> SdbConfiguration qt forall qt. Protocol -> Method -> ByteString -> Int -> SdbConfiguration qt SdbConfiguration Protocol HTTP Method Get ByteString endpoint (Protocol -> Int defaultPort Protocol HTTP) sdbHttpPost :: B.ByteString -> SdbConfiguration NormalQuery sdbHttpPost :: ByteString -> SdbConfiguration NormalQuery sdbHttpPost ByteString endpoint = Protocol -> Method -> ByteString -> Int -> SdbConfiguration NormalQuery forall qt. Protocol -> Method -> ByteString -> Int -> SdbConfiguration qt SdbConfiguration Protocol HTTP Method PostQuery ByteString endpoint (Protocol -> Int defaultPort Protocol HTTP) sdbHttpsGet :: B.ByteString -> SdbConfiguration qt sdbHttpsGet :: ByteString -> SdbConfiguration qt sdbHttpsGet ByteString endpoint = Protocol -> Method -> ByteString -> Int -> SdbConfiguration qt forall qt. Protocol -> Method -> ByteString -> Int -> SdbConfiguration qt SdbConfiguration Protocol HTTPS Method Get ByteString endpoint (Protocol -> Int defaultPort Protocol HTTPS) sdbHttpsPost :: B.ByteString -> SdbConfiguration NormalQuery sdbHttpsPost :: ByteString -> SdbConfiguration NormalQuery sdbHttpsPost ByteString endpoint = Protocol -> Method -> ByteString -> Int -> SdbConfiguration NormalQuery forall qt. Protocol -> Method -> ByteString -> Int -> SdbConfiguration qt SdbConfiguration Protocol HTTPS Method PostQuery ByteString endpoint (Protocol -> Int defaultPort Protocol HTTPS) sdbSignQuery :: [(B.ByteString, B.ByteString)] -> SdbConfiguration qt -> SignatureData -> SignedQuery sdbSignQuery :: [(ByteString, ByteString)] -> SdbConfiguration qt -> SignatureData -> SignedQuery sdbSignQuery [(ByteString, ByteString)] q SdbConfiguration qt si SignatureData sd = SignedQuery :: Method -> Protocol -> ByteString -> Int -> ByteString -> Query -> Maybe UTCTime -> Maybe (IO ByteString) -> Maybe ByteString -> Maybe (Digest MD5) -> RequestHeaders -> RequestHeaders -> Maybe RequestBody -> ByteString -> SignedQuery SignedQuery { sqMethod :: Method sqMethod = Method method , sqProtocol :: Protocol sqProtocol = SdbConfiguration qt -> Protocol forall qt. SdbConfiguration qt -> Protocol sdbiProtocol SdbConfiguration qt si , sqHost :: ByteString sqHost = ByteString host , sqPort :: Int sqPort = SdbConfiguration qt -> Int forall qt. SdbConfiguration qt -> Int sdbiPort SdbConfiguration qt si , sqPath :: ByteString sqPath = ByteString path , sqQuery :: Query sqQuery = Query sq , sqDate :: Maybe UTCTime sqDate = UTCTime -> Maybe UTCTime forall a. a -> Maybe a Just (UTCTime -> Maybe UTCTime) -> UTCTime -> Maybe UTCTime forall a b. (a -> b) -> a -> b $ SignatureData -> UTCTime signatureTime SignatureData sd , sqAuthorization :: Maybe (IO ByteString) sqAuthorization = Maybe (IO ByteString) forall a. Maybe a Nothing , sqContentType :: Maybe ByteString sqContentType = Maybe ByteString forall a. Maybe a Nothing , sqContentMd5 :: Maybe (Digest MD5) sqContentMd5 = Maybe (Digest MD5) forall a. Maybe a Nothing , sqAmzHeaders :: RequestHeaders sqAmzHeaders = [] , sqOtherHeaders :: RequestHeaders sqOtherHeaders = [] , sqBody :: Maybe RequestBody sqBody = Maybe RequestBody forall a. Maybe a Nothing , sqStringToSign :: ByteString sqStringToSign = ByteString stringToSign } where ah :: AuthorizationHash ah = AuthorizationHash HmacSHA256 q' :: Query q' = [(ByteString, ByteString)] -> Query forall a. QueryLike a => a -> Query HTTP.toQuery ([(ByteString, ByteString)] -> Query) -> ([(ByteString, ByteString)] -> [(ByteString, ByteString)]) -> [(ByteString, ByteString)] -> Query forall b c a. (b -> c) -> (a -> b) -> a -> c . [(ByteString, ByteString)] -> [(ByteString, ByteString)] forall a. Ord a => [a] -> [a] sort ([(ByteString, ByteString)] -> Query) -> [(ByteString, ByteString)] -> Query forall a b. (a -> b) -> a -> b $ [(ByteString, ByteString)] q [(ByteString, ByteString)] -> [(ByteString, ByteString)] -> [(ByteString, ByteString)] forall a. [a] -> [a] -> [a] ++ (ByteString "Version", ByteString "2009-04-15") (ByteString, ByteString) -> [(ByteString, ByteString)] -> [(ByteString, ByteString)] forall a. a -> [a] -> [a] : [(ByteString, ByteString)] queryAuth ti :: AbsoluteTimeInfo ti = SignatureData -> AbsoluteTimeInfo signatureTimeInfo SignatureData sd cr :: Credentials cr = SignatureData -> Credentials signatureCredentials SignatureData sd queryAuth :: [(ByteString, ByteString)] queryAuth = [case AbsoluteTimeInfo ti of AbsoluteTimestamp UTCTime time -> (ByteString "Timestamp", UTCTime -> ByteString fmtAmzTime UTCTime time) AbsoluteExpires UTCTime time -> (ByteString "Expires", UTCTime -> ByteString fmtAmzTime UTCTime time) , (ByteString "AWSAccessKeyId", Credentials -> ByteString accessKeyID Credentials cr) , (ByteString "SignatureMethod", AuthorizationHash -> ByteString amzHash AuthorizationHash ah) , (ByteString "SignatureVersion", ByteString "2")] [(ByteString, ByteString)] -> [(ByteString, ByteString)] -> [(ByteString, ByteString)] forall a. [a] -> [a] -> [a] ++ [(ByteString, ByteString)] -> (ByteString -> [(ByteString, ByteString)]) -> Maybe ByteString -> [(ByteString, ByteString)] forall b a. b -> (a -> b) -> Maybe a -> b maybe [] (\ByteString tok -> [(ByteString "SecurityToken", ByteString tok)]) (Credentials -> Maybe ByteString iamToken Credentials cr) sq :: Query sq = (ByteString "Signature", ByteString -> Maybe ByteString forall a. a -> Maybe a Just ByteString sig) (ByteString, Maybe ByteString) -> Query -> Query forall a. a -> [a] -> [a] : Query q' method :: Method method = SdbConfiguration qt -> Method forall qt. SdbConfiguration qt -> Method sdbiHttpMethod SdbConfiguration qt si host :: ByteString host = SdbConfiguration qt -> ByteString forall qt. SdbConfiguration qt -> ByteString sdbiHost SdbConfiguration qt si path :: ByteString path = ByteString "/" sig :: ByteString sig = Credentials -> AuthorizationHash -> ByteString -> ByteString signature Credentials cr AuthorizationHash ah ByteString stringToSign stringToSign :: ByteString stringToSign = Builder -> ByteString Blaze.toByteString (Builder -> ByteString) -> ([Builder] -> Builder) -> [Builder] -> ByteString forall b c a. (b -> c) -> (a -> b) -> a -> c . [Builder] -> Builder forall a. Monoid a => [a] -> a mconcat ([Builder] -> ByteString) -> [Builder] -> ByteString forall a b. (a -> b) -> a -> b $ Builder -> [Builder] -> [Builder] forall a. a -> [a] -> [a] intersperse (Char -> Builder Blaze8.fromChar Char '\n') [ByteString -> Builder Blaze.copyByteString (ByteString -> Builder) -> ByteString -> Builder forall a b. (a -> b) -> a -> b $ Method -> ByteString httpMethod Method method , ByteString -> Builder Blaze.copyByteString (ByteString -> Builder) -> ByteString -> Builder forall a b. (a -> b) -> a -> b $ ByteString host , ByteString -> Builder Blaze.copyByteString (ByteString -> Builder) -> ByteString -> Builder forall a b. (a -> b) -> a -> b $ ByteString path , Bool -> Query -> Builder HTTP.renderQueryBuilder Bool False Query q'] sdbResponseConsumer :: (Cu.Cursor -> Response SdbMetadata a) -> IORef SdbMetadata -> HTTPResponseConsumer a sdbResponseConsumer :: (Cursor -> Response SdbMetadata a) -> IORef SdbMetadata -> HTTPResponseConsumer a sdbResponseConsumer Cursor -> Response SdbMetadata a inner IORef SdbMetadata metadataRef Response (ConduitM () ByteString (ResourceT IO) ()) resp = (Cursor -> Response SdbMetadata a) -> IORef SdbMetadata -> HTTPResponseConsumer a forall m a. Monoid m => (Cursor -> Response m a) -> IORef m -> HTTPResponseConsumer a xmlCursorConsumer Cursor -> Response SdbMetadata a parse IORef SdbMetadata metadataRef Response (ConduitM () ByteString (ResourceT IO) ()) resp where parse :: Cursor -> Response SdbMetadata a parse Cursor cursor = do let requestId' :: Maybe Text requestId' = [Text] -> Maybe Text forall a. [a] -> Maybe a listToMaybe ([Text] -> Maybe Text) -> [Text] -> Maybe Text forall a b. (a -> b) -> a -> b $ Cursor cursor Cursor -> (Cursor -> [Text]) -> [Text] forall node a. Cursor node -> (Cursor node -> [a]) -> [a] $// Text -> Cursor -> [Text] elContent Text "RequestID" let boxUsage' :: Maybe Text boxUsage' = [Text] -> Maybe Text forall a. [a] -> Maybe a listToMaybe ([Text] -> Maybe Text) -> [Text] -> Maybe Text forall a b. (a -> b) -> a -> b $ Cursor cursor Cursor -> (Cursor -> [Text]) -> [Text] forall node a. Cursor node -> (Cursor node -> [a]) -> [a] $// Text -> Cursor -> [Text] elContent Text "BoxUsage" SdbMetadata -> Response SdbMetadata () forall m. m -> Response m () tellMetadata (SdbMetadata -> Response SdbMetadata ()) -> SdbMetadata -> Response SdbMetadata () forall a b. (a -> b) -> a -> b $ Maybe Text -> Maybe Text -> SdbMetadata SdbMetadata Maybe Text requestId' Maybe Text boxUsage' case Cursor cursor Cursor -> (Cursor -> [Cursor]) -> [Cursor] forall node a. Cursor node -> (Cursor node -> [a]) -> [a] $// Text -> Cursor -> [Cursor] Cu.laxElement Text "Error" of [] -> Cursor -> Response SdbMetadata a inner Cursor cursor (Cursor err:[Cursor] _) -> Cursor -> Response SdbMetadata a fromError Cursor err fromError :: Cursor -> Response SdbMetadata a fromError Cursor cursor = do ErrorCode errCode <- ErrorCode -> [ErrorCode] -> Response SdbMetadata ErrorCode forall (m :: * -> *) a. MonadThrow m => ErrorCode -> [a] -> m a force ErrorCode "Missing Error Code" ([ErrorCode] -> Response SdbMetadata ErrorCode) -> [ErrorCode] -> Response SdbMetadata ErrorCode forall a b. (a -> b) -> a -> b $ Cursor cursor Cursor -> (Cursor -> [ErrorCode]) -> [ErrorCode] forall node a. Cursor node -> (Cursor node -> [a]) -> [a] $// Text -> Cursor -> [ErrorCode] elCont Text "Code" ErrorCode errMessage <- ErrorCode -> [ErrorCode] -> Response SdbMetadata ErrorCode forall (m :: * -> *) a. MonadThrow m => ErrorCode -> [a] -> m a force ErrorCode "Missing Error Message" ([ErrorCode] -> Response SdbMetadata ErrorCode) -> [ErrorCode] -> Response SdbMetadata ErrorCode forall a b. (a -> b) -> a -> b $ Cursor cursor Cursor -> (Cursor -> [ErrorCode]) -> [ErrorCode] forall node a. Cursor node -> (Cursor node -> [a]) -> [a] $// Text -> Cursor -> [ErrorCode] elCont Text "Message" SdbError -> Response SdbMetadata a forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a throwM (SdbError -> Response SdbMetadata a) -> SdbError -> Response SdbMetadata a forall a b. (a -> b) -> a -> b $ Status -> ErrorCode -> ErrorCode -> SdbError SdbError (Response (ConduitM () ByteString (ResourceT IO) ()) -> Status forall body. Response body -> Status HTTP.responseStatus Response (ConduitM () ByteString (ResourceT IO) ()) resp) ErrorCode errCode ErrorCode errMessage class SdbFromResponse a where sdbFromResponse :: Cu.Cursor -> Response SdbMetadata a sdbCheckResponseType :: MonadThrow m => a -> T.Text -> Cu.Cursor -> m a sdbCheckResponseType :: a -> Text -> Cursor -> m a sdbCheckResponseType a a Text n Cursor c = do Cursor _ <- ErrorCode -> [Cursor] -> m Cursor forall (m :: * -> *) a. MonadThrow m => ErrorCode -> [a] -> m a force (ErrorCode "Expected response type " ErrorCode -> ShowS forall a. [a] -> [a] -> [a] ++ Text -> ErrorCode T.unpack Text n) (Text -> Cursor -> [Cursor] Cu.laxElement Text n Cursor c) a -> m a forall (m :: * -> *) a. Monad m => a -> m a return a a decodeBase64 :: MonadThrow m => Cu.Cursor -> m T.Text decodeBase64 :: Cursor -> m Text decodeBase64 Cursor cursor = let encoded :: Text encoded = [Text] -> Text T.concat ([Text] -> Text) -> [Text] -> Text forall a b. (a -> b) -> a -> b $ Cursor cursor Cursor -> (Cursor -> [Text]) -> [Text] forall node a. Cursor node -> (Cursor node -> [a]) -> [a] $/ Cursor -> [Text] Cu.content encoding :: Maybe Text encoding = [Text] -> Maybe Text forall a. [a] -> Maybe a listToMaybe ([Text] -> Maybe Text) -> [Text] -> Maybe Text forall a b. (a -> b) -> a -> b $ Cursor cursor Cursor -> (Cursor -> [Text]) -> [Text] forall node a. Cursor node -> (Cursor node -> a) -> a $| Text -> Cursor -> [Text] Cu.laxAttribute Text "encoding" (Cursor -> [Text]) -> (Text -> Text) -> Cursor -> [Text] forall node a b. (Cursor node -> [a]) -> (a -> b) -> Cursor node -> [b] &| Text -> Text T.toCaseFold in case Maybe Text encoding of Maybe Text Nothing -> Text -> m Text forall (m :: * -> *) a. Monad m => a -> m a return Text encoded Just Text "base64" -> case ByteString -> Either ErrorCode ByteString Base64.decode (ByteString -> Either ErrorCode ByteString) -> (Text -> ByteString) -> Text -> Either ErrorCode ByteString forall b c a. (b -> c) -> (a -> b) -> a -> c . Text -> ByteString T.encodeUtf8 (Text -> Either ErrorCode ByteString) -> Text -> Either ErrorCode ByteString forall a b. (a -> b) -> a -> b $ Text encoded of Left ErrorCode msg -> XmlException -> m Text forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a throwM (XmlException -> m Text) -> XmlException -> m Text forall a b. (a -> b) -> a -> b $ ErrorCode -> XmlException XmlException (ErrorCode "Invalid Base64 data: " ErrorCode -> ShowS forall a. [a] -> [a] -> [a] ++ ErrorCode msg) Right ByteString x -> Text -> m Text forall (m :: * -> *) a. Monad m => a -> m a return (Text -> m Text) -> Text -> m Text forall a b. (a -> b) -> a -> b $ ByteString -> Text T.decodeUtf8 ByteString x Just Text actual -> XmlException -> m Text forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a throwM (XmlException -> m Text) -> XmlException -> m Text forall a b. (a -> b) -> a -> b $ ErrorCode -> XmlException XmlException (ErrorCode "Unrecognized encoding " ErrorCode -> ShowS forall a. [a] -> [a] -> [a] ++ Text -> ErrorCode T.unpack Text actual) data Attribute a = ForAttribute { Attribute a -> Text attributeName :: T.Text, Attribute a -> a attributeData :: a } deriving (Int -> Attribute a -> ShowS [Attribute a] -> ShowS Attribute a -> ErrorCode (Int -> Attribute a -> ShowS) -> (Attribute a -> ErrorCode) -> ([Attribute a] -> ShowS) -> Show (Attribute a) forall a. Show a => Int -> Attribute a -> ShowS forall a. Show a => [Attribute a] -> ShowS forall a. Show a => Attribute a -> ErrorCode forall a. (Int -> a -> ShowS) -> (a -> ErrorCode) -> ([a] -> ShowS) -> Show a showList :: [Attribute a] -> ShowS $cshowList :: forall a. Show a => [Attribute a] -> ShowS show :: Attribute a -> ErrorCode $cshow :: forall a. Show a => Attribute a -> ErrorCode showsPrec :: Int -> Attribute a -> ShowS $cshowsPrec :: forall a. Show a => Int -> Attribute a -> ShowS Show) readAttribute :: MonadThrow m => Cu.Cursor -> m (Attribute T.Text) readAttribute :: Cursor -> m (Attribute Text) readAttribute Cursor cursor = do Text name <- ErrorCode -> [m Text] -> m Text forall (m :: * -> *) a. MonadThrow m => ErrorCode -> [m a] -> m a forceM ErrorCode "Missing Name" ([m Text] -> m Text) -> [m Text] -> m Text forall a b. (a -> b) -> a -> b $ Cursor cursor Cursor -> (Cursor -> [m Text]) -> [m Text] forall node a. Cursor node -> (Cursor node -> [a]) -> [a] $/ Text -> Cursor -> [Cursor] Cu.laxElement Text "Name" (Cursor -> [Cursor]) -> (Cursor -> m Text) -> Cursor -> [m Text] forall node a b. (Cursor node -> [a]) -> (a -> b) -> Cursor node -> [b] &| Cursor -> m Text forall (m :: * -> *). MonadThrow m => Cursor -> m Text decodeBase64 Text value <- ErrorCode -> [m Text] -> m Text forall (m :: * -> *) a. MonadThrow m => ErrorCode -> [m a] -> m a forceM ErrorCode "Missing Value" ([m Text] -> m Text) -> [m Text] -> m Text forall a b. (a -> b) -> a -> b $ Cursor cursor Cursor -> (Cursor -> [m Text]) -> [m Text] forall node a. Cursor node -> (Cursor node -> [a]) -> [a] $/ Text -> Cursor -> [Cursor] Cu.laxElement Text "Value" (Cursor -> [Cursor]) -> (Cursor -> m Text) -> Cursor -> [m Text] forall node a b. (Cursor node -> [a]) -> (a -> b) -> Cursor node -> [b] &| Cursor -> m Text forall (m :: * -> *). MonadThrow m => Cursor -> m Text decodeBase64 Attribute Text -> m (Attribute Text) forall (m :: * -> *) a. Monad m => a -> m a return (Attribute Text -> m (Attribute Text)) -> Attribute Text -> m (Attribute Text) forall a b. (a -> b) -> a -> b $ Text -> Text -> Attribute Text forall a. Text -> a -> Attribute a ForAttribute Text name Text value data SetAttribute = SetAttribute { SetAttribute -> Text setAttribute :: T.Text, SetAttribute -> Bool isReplaceAttribute :: Bool } deriving (Int -> SetAttribute -> ShowS [SetAttribute] -> ShowS SetAttribute -> ErrorCode (Int -> SetAttribute -> ShowS) -> (SetAttribute -> ErrorCode) -> ([SetAttribute] -> ShowS) -> Show SetAttribute forall a. (Int -> a -> ShowS) -> (a -> ErrorCode) -> ([a] -> ShowS) -> Show a showList :: [SetAttribute] -> ShowS $cshowList :: [SetAttribute] -> ShowS show :: SetAttribute -> ErrorCode $cshow :: SetAttribute -> ErrorCode showsPrec :: Int -> SetAttribute -> ShowS $cshowsPrec :: Int -> SetAttribute -> ShowS Show) attributeQuery :: (a -> [(B.ByteString, B.ByteString)]) -> Attribute a -> [(B.ByteString, B.ByteString)] attributeQuery :: (a -> [(ByteString, ByteString)]) -> Attribute a -> [(ByteString, ByteString)] attributeQuery a -> [(ByteString, ByteString)] f (ForAttribute Text name a x) = (ByteString "Name", Text -> ByteString T.encodeUtf8 Text name) (ByteString, ByteString) -> [(ByteString, ByteString)] -> [(ByteString, ByteString)] forall a. a -> [a] -> [a] : a -> [(ByteString, ByteString)] f a x addAttribute :: T.Text -> T.Text -> Attribute SetAttribute addAttribute :: Text -> Text -> Attribute SetAttribute addAttribute Text name Text value = Text -> SetAttribute -> Attribute SetAttribute forall a. Text -> a -> Attribute a ForAttribute Text name (Text -> Bool -> SetAttribute SetAttribute Text value Bool False) replaceAttribute :: T.Text -> T.Text -> Attribute SetAttribute replaceAttribute :: Text -> Text -> Attribute SetAttribute replaceAttribute Text name Text value = Text -> SetAttribute -> Attribute SetAttribute forall a. Text -> a -> Attribute a ForAttribute Text name (Text -> Bool -> SetAttribute SetAttribute Text value Bool True) setAttributeQuery :: SetAttribute -> [(B.ByteString, B.ByteString)] setAttributeQuery :: SetAttribute -> [(ByteString, ByteString)] setAttributeQuery (SetAttribute Text value Bool replace) = (ByteString "Value", Text -> ByteString T.encodeUtf8 Text value) (ByteString, ByteString) -> [(ByteString, ByteString)] -> [(ByteString, ByteString)] forall a. a -> [a] -> [a] : [(ByteString "Replace", ByteString awsTrue) | Bool replace] data DeleteAttribute = DeleteAttribute | ValuedDeleteAttribute { DeleteAttribute -> Text deleteAttributeValue :: T.Text } deriving (Int -> DeleteAttribute -> ShowS [DeleteAttribute] -> ShowS DeleteAttribute -> ErrorCode (Int -> DeleteAttribute -> ShowS) -> (DeleteAttribute -> ErrorCode) -> ([DeleteAttribute] -> ShowS) -> Show DeleteAttribute forall a. (Int -> a -> ShowS) -> (a -> ErrorCode) -> ([a] -> ShowS) -> Show a showList :: [DeleteAttribute] -> ShowS $cshowList :: [DeleteAttribute] -> ShowS show :: DeleteAttribute -> ErrorCode $cshow :: DeleteAttribute -> ErrorCode showsPrec :: Int -> DeleteAttribute -> ShowS $cshowsPrec :: Int -> DeleteAttribute -> ShowS Show) deleteAttributeQuery :: DeleteAttribute -> [(B.ByteString, B.ByteString)] deleteAttributeQuery :: DeleteAttribute -> [(ByteString, ByteString)] deleteAttributeQuery DeleteAttribute DeleteAttribute = [] deleteAttributeQuery (ValuedDeleteAttribute Text value) = [(ByteString "Value", Text -> ByteString T.encodeUtf8 Text value)] data ExpectedAttribute = ExpectedValue { ExpectedAttribute -> Text expectedAttributeValue :: T.Text } | ExpectedExists { ExpectedAttribute -> Bool expectedAttributeExists :: Bool } deriving (Int -> ExpectedAttribute -> ShowS [ExpectedAttribute] -> ShowS ExpectedAttribute -> ErrorCode (Int -> ExpectedAttribute -> ShowS) -> (ExpectedAttribute -> ErrorCode) -> ([ExpectedAttribute] -> ShowS) -> Show ExpectedAttribute forall a. (Int -> a -> ShowS) -> (a -> ErrorCode) -> ([a] -> ShowS) -> Show a showList :: [ExpectedAttribute] -> ShowS $cshowList :: [ExpectedAttribute] -> ShowS show :: ExpectedAttribute -> ErrorCode $cshow :: ExpectedAttribute -> ErrorCode showsPrec :: Int -> ExpectedAttribute -> ShowS $cshowsPrec :: Int -> ExpectedAttribute -> ShowS Show) expectedValue :: T.Text -> T.Text -> Attribute ExpectedAttribute expectedValue :: Text -> Text -> Attribute ExpectedAttribute expectedValue Text name Text value = Text -> ExpectedAttribute -> Attribute ExpectedAttribute forall a. Text -> a -> Attribute a ForAttribute Text name (Text -> ExpectedAttribute ExpectedValue Text value) expectedExists :: T.Text -> Bool -> Attribute ExpectedAttribute expectedExists :: Text -> Bool -> Attribute ExpectedAttribute expectedExists Text name Bool exists = Text -> ExpectedAttribute -> Attribute ExpectedAttribute forall a. Text -> a -> Attribute a ForAttribute Text name (Bool -> ExpectedAttribute ExpectedExists Bool exists) expectedAttributeQuery :: ExpectedAttribute -> [(B.ByteString, B.ByteString)] expectedAttributeQuery :: ExpectedAttribute -> [(ByteString, ByteString)] expectedAttributeQuery (ExpectedValue Text value) = [(ByteString "Value", Text -> ByteString T.encodeUtf8 Text value)] expectedAttributeQuery (ExpectedExists Bool exists) = [(ByteString "Exists", Bool -> ByteString awsBool Bool exists)] data Item a = Item { Item a -> Text itemName :: T.Text, Item a -> a itemData :: a } deriving (Int -> Item a -> ShowS [Item a] -> ShowS Item a -> ErrorCode (Int -> Item a -> ShowS) -> (Item a -> ErrorCode) -> ([Item a] -> ShowS) -> Show (Item a) forall a. Show a => Int -> Item a -> ShowS forall a. Show a => [Item a] -> ShowS forall a. Show a => Item a -> ErrorCode forall a. (Int -> a -> ShowS) -> (a -> ErrorCode) -> ([a] -> ShowS) -> Show a showList :: [Item a] -> ShowS $cshowList :: forall a. Show a => [Item a] -> ShowS show :: Item a -> ErrorCode $cshow :: forall a. Show a => Item a -> ErrorCode showsPrec :: Int -> Item a -> ShowS $cshowsPrec :: forall a. Show a => Int -> Item a -> ShowS Show) readItem :: MonadThrow m => Cu.Cursor -> m (Item [Attribute T.Text]) readItem :: Cursor -> m (Item [Attribute Text]) readItem Cursor cursor = do Text name <- ErrorCode -> [Text] -> m Text forall (m :: * -> *) a. MonadThrow m => ErrorCode -> [a] -> m a force ErrorCode "Missing Name" ([Text] -> m Text) -> ([m Text] -> m [Text]) -> [m Text] -> m Text forall (m :: * -> *) b c a. Monad m => (b -> m c) -> (a -> m b) -> a -> m c <=< [m Text] -> m [Text] forall (t :: * -> *) (m :: * -> *) a. (Traversable t, Monad m) => t (m a) -> m (t a) sequence ([m Text] -> m Text) -> [m Text] -> m Text forall a b. (a -> b) -> a -> b $ Cursor cursor Cursor -> (Cursor -> [m Text]) -> [m Text] forall node a. Cursor node -> (Cursor node -> [a]) -> [a] $/ Text -> Cursor -> [Cursor] Cu.laxElement Text "Name" (Cursor -> [Cursor]) -> (Cursor -> m Text) -> Cursor -> [m Text] forall node a b. (Cursor node -> [a]) -> (a -> b) -> Cursor node -> [b] &| Cursor -> m Text forall (m :: * -> *). MonadThrow m => Cursor -> m Text decodeBase64 [Attribute Text] attributes <- [m (Attribute Text)] -> m [Attribute Text] forall (t :: * -> *) (m :: * -> *) a. (Traversable t, Monad m) => t (m a) -> m (t a) sequence ([m (Attribute Text)] -> m [Attribute Text]) -> [m (Attribute Text)] -> m [Attribute Text] forall a b. (a -> b) -> a -> b $ Cursor cursor Cursor -> (Cursor -> [m (Attribute Text)]) -> [m (Attribute Text)] forall node a. Cursor node -> (Cursor node -> [a]) -> [a] $/ Text -> Cursor -> [Cursor] Cu.laxElement Text "Attribute" (Cursor -> [Cursor]) -> (Cursor -> m (Attribute Text)) -> Cursor -> [m (Attribute Text)] forall node a b. (Cursor node -> [a]) -> (a -> b) -> Cursor node -> [b] &| Cursor -> m (Attribute Text) forall (m :: * -> *). MonadThrow m => Cursor -> m (Attribute Text) readAttribute Item [Attribute Text] -> m (Item [Attribute Text]) forall (m :: * -> *) a. Monad m => a -> m a return (Item [Attribute Text] -> m (Item [Attribute Text])) -> Item [Attribute Text] -> m (Item [Attribute Text]) forall a b. (a -> b) -> a -> b $ Text -> [Attribute Text] -> Item [Attribute Text] forall a. Text -> a -> Item a Item Text name [Attribute Text] attributes itemQuery :: (a -> [(B.ByteString, B.ByteString)]) -> Item a -> [(B.ByteString, B.ByteString)] itemQuery :: (a -> [(ByteString, ByteString)]) -> Item a -> [(ByteString, ByteString)] itemQuery a -> [(ByteString, ByteString)] f (Item Text name a x) = (ByteString "ItemName", Text -> ByteString T.encodeUtf8 Text name) (ByteString, ByteString) -> [(ByteString, ByteString)] -> [(ByteString, ByteString)] forall a. a -> [a] -> [a] : a -> [(ByteString, ByteString)] f a x