module Ecluse.Core.Registry.PyPI.Streaming (
PyPIRead (..),
PyPIField (..),
fileScalars,
hashNames,
SelectedFileEvent (..),
SelectedFile (..),
collectSelected,
finishSelected,
) where
import Data.Aeson (Value (Object, String))
import Data.Aeson.Key qualified as Key
import Data.Aeson.KeyMap qualified as KeyMap
import Data.Universe.Class qualified as Universe
import Ecluse.Core.Package (PackageName)
import Ecluse.Core.Package.Hash (HashAlg (SRI), renderHashAlg)
import Ecluse.Core.Registry.PyPI.Project (FileProject, fileVersionKey)
data PyPIRead = FullRead | SelectedRead PackageName Text
deriving stock (PyPIRead -> PyPIRead -> Bool
(PyPIRead -> PyPIRead -> Bool)
-> (PyPIRead -> PyPIRead -> Bool) -> Eq PyPIRead
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PyPIRead -> PyPIRead -> Bool
== :: PyPIRead -> PyPIRead -> Bool
$c/= :: PyPIRead -> PyPIRead -> Bool
/= :: PyPIRead -> PyPIRead -> Bool
Eq, Int -> PyPIRead -> ShowS
[PyPIRead] -> ShowS
PyPIRead -> String
(Int -> PyPIRead -> ShowS)
-> (PyPIRead -> String) -> ([PyPIRead] -> ShowS) -> Show PyPIRead
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PyPIRead -> ShowS
showsPrec :: Int -> PyPIRead -> ShowS
$cshow :: PyPIRead -> String
show :: PyPIRead -> String
$cshowList :: [PyPIRead] -> ShowS
showList :: [PyPIRead] -> ShowS
Show)
data PyPIField
= EnvelopeField Text Value
| FilesShape Bool
| FileField Int (Maybe Value)
| VersionsShape Bool
| InvalidVersionField Int Value
| IgnoredField
deriving stock (PyPIField -> PyPIField -> Bool
(PyPIField -> PyPIField -> Bool)
-> (PyPIField -> PyPIField -> Bool) -> Eq PyPIField
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PyPIField -> PyPIField -> Bool
== :: PyPIField -> PyPIField -> Bool
$c/= :: PyPIField -> PyPIField -> Bool
/= :: PyPIField -> PyPIField -> Bool
Eq, Int -> PyPIField -> ShowS
[PyPIField] -> ShowS
PyPIField -> String
(Int -> PyPIField -> ShowS)
-> (PyPIField -> String)
-> ([PyPIField] -> ShowS)
-> Show PyPIField
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PyPIField -> ShowS
showsPrec :: Int -> PyPIField -> ShowS
$cshow :: PyPIField -> String
show :: PyPIField -> String
$cshowList :: [PyPIField] -> ShowS
showList :: [PyPIField] -> ShowS
Show)
fileScalars :: [Text]
fileScalars :: [Text]
fileScalars = [Text
"filename", Text
"url", Text
"requires-python", Text
"size", Text
"upload-time", Text
"yanked", Text
"provenance"]
hashNames :: [Text]
hashNames :: [Text]
hashNames = [HashAlg -> Text
renderHashAlg HashAlg
alg | HashAlg
alg <- [HashAlg]
forall a. Universe a => [a]
Universe.universe, HashAlg
alg HashAlg -> HashAlg -> Bool
forall a. Eq a => a -> a -> Bool
/= HashAlg
SRI]
data SelectedFileEvent
= FileScalar Key.Key Value
| HashesStart
| HashesEnd
| HashField Key.Key Value
| HashesValue Value
data SelectedFile
= RejectedFile
| CandidateFile Bool [(Key.Key, Value)] (Maybe Value) Bool
collectSelected :: FileProject -> Text -> SelectedFile -> SelectedFileEvent -> SelectedFile
collectSelected :: FileProject
-> Text -> SelectedFile -> SelectedFileEvent -> SelectedFile
collectSelected FileProject
_ Text
_ SelectedFile
RejectedFile SelectedFileEvent
_ = SelectedFile
RejectedFile
collectSelected FileProject
project Text
wanted current :: SelectedFile
current@(CandidateFile Bool
matched [(Key, Value)]
scalars Maybe Value
hashes Bool
active) SelectedFileEvent
event = case SelectedFileEvent
event of
FileScalar Key
key Value
value
| ((Key, Value) -> Bool) -> [(Key, Value)] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any ((Key -> Key -> Bool
forall a. Eq a => a -> a -> Bool
== Key
key) (Key -> Bool) -> ((Key, Value) -> Key) -> (Key, Value) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Key, Value) -> Key
forall a b. (a, b) -> a
fst) [(Key, Value)]
scalars -> SelectedFile
current
| Key
key Key -> Key -> Bool
forall a. Eq a => a -> a -> Bool
== Key
"filename" -> case Value
value of
String Text
filename
| FileProject -> Text -> Maybe Text
fileVersionKey FileProject
project Text
filename Maybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text -> Maybe Text
forall a. a -> Maybe a
Just Text
wanted ->
Bool -> [(Key, Value)] -> Maybe Value -> Bool -> SelectedFile
CandidateFile Bool
True ((Key
key, Value
value) (Key, Value) -> [(Key, Value)] -> [(Key, Value)]
forall a. a -> [a] -> [a]
: [(Key, Value)]
scalars) Maybe Value
hashes Bool
active
Value
_ -> SelectedFile
RejectedFile
| Bool
otherwise -> Bool -> [(Key, Value)] -> Maybe Value -> Bool -> SelectedFile
CandidateFile Bool
matched ((Key
key, Value
value) (Key, Value) -> [(Key, Value)] -> [(Key, Value)]
forall a. a -> [a] -> [a]
: [(Key, Value)]
scalars) Maybe Value
hashes Bool
active
SelectedFileEvent
HashesStart ->
Bool -> [(Key, Value)] -> Maybe Value -> Bool -> SelectedFile
CandidateFile Bool
matched [(Key, Value)]
scalars (Maybe Value
hashes Maybe Value -> Maybe Value -> Maybe Value
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Value -> Maybe Value
forall a. a -> Maybe a
Just (Object -> Value
Object Object
forall a. Monoid a => a
mempty)) (Maybe Value -> Bool
forall a. Maybe a -> Bool
isNothing Maybe Value
hashes)
SelectedFileEvent
HashesEnd -> Bool -> [(Key, Value)] -> Maybe Value -> Bool -> SelectedFile
CandidateFile Bool
matched [(Key, Value)]
scalars Maybe Value
hashes Bool
False
HashesValue Value
value -> Bool -> [(Key, Value)] -> Maybe Value -> Bool -> SelectedFile
CandidateFile Bool
matched [(Key, Value)]
scalars (Maybe Value
hashes Maybe Value -> Maybe Value -> Maybe Value
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Value -> Maybe Value
forall a. a -> Maybe a
Just Value
value) Bool
active
HashField Key
key Value
value
| Bool
active
, Just (Object Object
fields) <- Maybe Value
hashes
, Bool -> Bool
not (Key -> Object -> Bool
forall a. Key -> KeyMap a -> Bool
KeyMap.member Key
key Object
fields) ->
Bool -> [(Key, Value)] -> Maybe Value -> Bool -> SelectedFile
CandidateFile Bool
matched [(Key, Value)]
scalars (Value -> Maybe Value
forall a. a -> Maybe a
Just (Object -> Value
Object (Key -> Value -> Object -> Object
forall v. Key -> v -> KeyMap v -> KeyMap v
KeyMap.insert Key
key Value
value Object
fields))) Bool
active
| Bool
otherwise -> SelectedFile
current
finishSelected :: SelectedFile -> Maybe Value
finishSelected :: SelectedFile -> Maybe Value
finishSelected (CandidateFile Bool
True [(Key, Value)]
fields Maybe Value
hashes Bool
_) =
Value -> Maybe Value
forall a. a -> Maybe a
Just (Object -> Value
Object ([(Key, Value)] -> Object
forall v. [(Key, v)] -> KeyMap v
KeyMap.fromList (Maybe (Key, Value) -> [(Key, Value)]
forall a. Maybe a -> [a]
maybeToList ((,) Key
"hashes" (Value -> (Key, Value)) -> Maybe Value -> Maybe (Key, Value)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Value
hashes) [(Key, Value)] -> [(Key, Value)] -> [(Key, Value)]
forall a. Semigroup a => a -> a -> a
<> [(Key, Value)]
fields)))
finishSelected SelectedFile
_ = Maybe Value
forall a. Maybe a
Nothing