module Ecluse.Core.Registry.VersionList (
VersionListItem (..),
VersionListState,
emptyVersionList,
collectVersionList,
finishVersionList,
) where
import Data.Map.Strict qualified as Map
import Ecluse.Core.Registry (ParseError (ParseError))
import Ecluse.Core.Security (LimitError, Limits, checkVersionCountOf)
import Ecluse.Core.Version (Version, renderVersion)
data VersionListItem = VersionListObject | VersionListContainer | VersionListInvalidContainer | VersionListEntry (Maybe Version)
data VersionListState = VersionListState
{ VersionListState -> Bool
inventoryObjectSeen :: Bool
, VersionListState -> Bool
inventoryContainerSeen :: Bool
, VersionListState -> Bool
inventoryAcceptEntries :: Bool
, VersionListState -> Bool
inventoryInvalidContainer :: Bool
, VersionListState -> Int
inventoryCount :: Int
, VersionListState -> Map Text Version
inventoryVersions :: Map Text Version
}
emptyVersionList :: VersionListState
emptyVersionList :: VersionListState
emptyVersionList = Bool
-> Bool
-> Bool
-> Bool
-> Int
-> Map Text Version
-> VersionListState
VersionListState Bool
False Bool
False Bool
False Bool
False Int
0 Map Text Version
forall a. Monoid a => a
mempty
collectVersionList :: Limits -> VersionListState -> VersionListItem -> Either LimitError VersionListState
collectVersionList :: Limits
-> VersionListState
-> VersionListItem
-> Either LimitError VersionListState
collectVersionList Limits
limits VersionListState
inventory = \case
VersionListItem
VersionListObject -> VersionListState -> Either LimitError VersionListState
forall a b. b -> Either a b
Right VersionListState
inventory{inventoryObjectSeen = True}
VersionListItem
VersionListContainer ->
VersionListState -> Either LimitError VersionListState
forall a b. b -> Either a b
Right
VersionListState
inventory
{ inventoryContainerSeen = True
, inventoryAcceptEntries = not (inventoryContainerSeen inventory)
}
VersionListItem
VersionListInvalidContainer ->
VersionListState -> Either LimitError VersionListState
forall a b. b -> Either a b
Right
VersionListState
inventory
{ inventoryContainerSeen = True
, inventoryAcceptEntries = False
, inventoryInvalidContainer = inventoryInvalidContainer inventory || not (inventoryContainerSeen inventory)
}
VersionListEntry Maybe Version
_ | Bool -> Bool
not (VersionListState -> Bool
inventoryAcceptEntries VersionListState
inventory) -> VersionListState -> Either LimitError VersionListState
forall a b. b -> Either a b
Right VersionListState
inventory
VersionListEntry Maybe Version
candidate -> do
let count :: Int
count = VersionListState -> Int
inventoryCount VersionListState
inventory Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
Limits -> Int -> Either LimitError ()
checkVersionCountOf Limits
limits Int
count
VersionListState -> Either LimitError VersionListState
forall a. a -> Either LimitError a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
VersionListState
inventory
{ inventoryCount = count
, inventoryVersions = maybe (inventoryVersions inventory) (\Version
version -> Text -> Version -> Map Text Version -> Map Text Version
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert (Version -> Text
renderVersion Version
version) Version
version (VersionListState -> Map Text Version
inventoryVersions VersionListState
inventory)) candidate
}
finishVersionList :: VersionListState -> Either ParseError [Version]
finishVersionList :: VersionListState -> Either ParseError [Version]
finishVersionList VersionListState
inventory
| Bool -> Bool
not (VersionListState -> Bool
inventoryObjectSeen VersionListState
inventory) = ParseError -> Either ParseError [Version]
forall a b. a -> Either a b
Left (Text -> ParseError
ParseError Text
"the version list is not a JSON object")
| VersionListState -> Bool
inventoryInvalidContainer VersionListState
inventory = ParseError -> Either ParseError [Version]
forall a b. a -> Either a b
Left (Text -> ParseError
ParseError Text
"the versions field is not an object or null")
| Bool
otherwise = [Version] -> Either ParseError [Version]
forall a b. b -> Either a b
Right (Map Text Version -> [Version]
forall k a. Map k a -> [a]
Map.elems (VersionListState -> Map Text Version
inventoryVersions VersionListState
inventory))