--
-- MinIO Haskell SDK, (C) 2017-2023 MinIO, Inc.
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
--     http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--

module Network.Minio.XmlCommon where

import qualified Data.Text as T
import Data.Text.Read (decimal)
import Data.Time (UTCTime)
import Data.Time.Format.ISO8601 (iso8601ParseM)
import Lib.Prelude (throwIO)
import Network.Minio.Errors
import Text.XML (Name (Name), def, parseLBS)
import Text.XML.Cursor (Axis, Cursor, content, element, fromDocument, laxElement, ($/), (&/))

s3Name :: Text -> Text -> Name
s3Name :: Text -> Text -> Name
s3Name Text
ns Text
s = Text -> Maybe Text -> Maybe Text -> Name
Name Text
s (forall a. a -> Maybe a
Just Text
ns) forall a. Maybe a
Nothing

uncurry4 :: (a -> b -> c -> d -> e) -> (a, b, c, d) -> e
uncurry4 :: forall a b c d e. (a -> b -> c -> d -> e) -> (a, b, c, d) -> e
uncurry4 a -> b -> c -> d -> e
f (a
a, b
b, c
c, d
d) = a -> b -> c -> d -> e
f a
a b
b c
c d
d

uncurry6 :: (a -> b -> c -> d -> e -> f -> g) -> (a, b, c, d, e, f) -> g
uncurry6 :: forall a b c d e f g.
(a -> b -> c -> d -> e -> f -> g) -> (a, b, c, d, e, f) -> g
uncurry6 a -> b -> c -> d -> e -> f -> g
f (a
a, b
b, c
c, d
d, e
e, f
g) = a -> b -> c -> d -> e -> f -> g
f a
a b
b c
c d
d e
e f
g

-- | Parse time strings from XML
parseS3XMLTime :: (MonadIO m) => Text -> m UTCTime
parseS3XMLTime :: forall (m :: * -> *). MonadIO m => Text -> m UTCTime
parseS3XMLTime Text
t =
  forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall (m :: * -> *) e a. (MonadIO m, Exception e) => e -> m a
throwIO forall a b. (a -> b) -> a -> b
$ Text -> MErrV
MErrVXmlParse forall a b. (a -> b) -> a -> b
$ Text
"timestamp parse failure: " forall a. Semigroup a => a -> a -> a
<> Text
t) forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$
    forall (m :: * -> *) t. (MonadFail m, ISO8601 t) => String -> m t
iso8601ParseM forall a b. (a -> b) -> a -> b
$
      forall a. ToString a => a -> String
toString Text
t

parseDecimal :: (MonadIO m, Integral a) => Text -> m a
parseDecimal :: forall (m :: * -> *) a. (MonadIO m, Integral a) => Text -> m a
parseDecimal Text
numStr =
  forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (forall (m :: * -> *) e a. (MonadIO m, Exception e) => e -> m a
throwIO forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> MErrV
MErrVXmlParse forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall b a. (Show a, IsString b) => a -> b
show) forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$
    forall a b. (a, b) -> a
fst forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Integral a => Reader a
decimal Text
numStr

parseDecimals :: (MonadIO m, Integral a) => [Text] -> m [a]
parseDecimals :: forall (m :: * -> *) a. (MonadIO m, Integral a) => [Text] -> m [a]
parseDecimals [Text]
numStr = forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [Text]
numStr forall (m :: * -> *) a. (MonadIO m, Integral a) => Text -> m a
parseDecimal

s3Elem :: Text -> Text -> Axis
s3Elem :: Text -> Text -> Axis
s3Elem Text
ns = Name -> Axis
element forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text -> Name
s3Name Text
ns

parseRoot :: (MonadIO m) => LByteString -> m Cursor
parseRoot :: forall (m :: * -> *). MonadIO m => LByteString -> m Cursor
parseRoot =
  forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (forall (m :: * -> *) e a. (MonadIO m, Exception e) => e -> m a
throwIO forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> MErrV
MErrVXmlParse forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall b a. (Show a, IsString b) => a -> b
show) (forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. Document -> Cursor
fromDocument)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
. ParseSettings -> LByteString -> Either SomeException Document
parseLBS forall a. Default a => a
def

parseErrResponse :: (MonadIO m) => LByteString -> m ServiceErr
parseErrResponse :: forall (m :: * -> *). MonadIO m => LByteString -> m ServiceErr
parseErrResponse LByteString
xmldata = do
  Cursor
r <- forall (m :: * -> *). MonadIO m => LByteString -> m Cursor
parseRoot LByteString
xmldata
  let code :: Text
code = [Text] -> Text
T.concat forall a b. (a -> b) -> a -> b
$ Cursor
r forall node a. Cursor node -> (Cursor node -> [a]) -> [a]
$/ Text -> Axis
laxElement Text
"Code" forall node a.
Axis node -> (Cursor node -> [a]) -> Cursor node -> [a]
&/ Cursor -> [Text]
content
      message :: Text
message = [Text] -> Text
T.concat forall a b. (a -> b) -> a -> b
$ Cursor
r forall node a. Cursor node -> (Cursor node -> [a]) -> [a]
$/ Text -> Axis
laxElement Text
"Message" forall node a.
Axis node -> (Cursor node -> [a]) -> Cursor node -> [a]
&/ Cursor -> [Text]
content
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Text -> Text -> ServiceErr
toServiceErr Text
code Text
message