@@ -19,8 +19,9 @@ import Data.Bifunctor
1919import Data.Bits hiding (And )
2020import Data.ByteString qualified as BS
2121import Data.ByteString.Lazy qualified as BSL
22+ import Data.Either (lefts , rights )
2223import Data.Function ((&) )
23- import Data.Functor ((<&>) , ($>) )
24+ import Data.Functor ((<&>) )
2425import Data.Functor.Identity
2526import Data.IntSet qualified as IS
2627import Data.List.NonEmpty qualified as NE
@@ -662,7 +663,7 @@ flattenGroup cddl nodes =
662663data Filter
663664 = NoFilter
664665 | Filter { mapFilter :: Rule , arrayFilter :: Rule }
665- deriving Show
666+ deriving ( Show )
666667
667668-- | A tree of possible expansions of a rule matching the size of a container to
668669-- validate. This tree contains filters at each node, such that we can
@@ -694,6 +695,14 @@ mergeTrees (a : as) = foldl' go a as
694695 go (Branch xs) b = Branch $ fmap (flip go b) xs
695696 go (FilterBranch f x) b = FilterBranch f $ go x b
696697
698+ -- | Merge two trees by adding them as choices at the top-level using the
699+ -- `Branch` constructor.
700+ mergeTopBranch :: ExpansionTree' a -> ExpansionTree' a -> ExpansionTree' a
701+ mergeTopBranch (Branch t1) (Branch t2) = Branch $ t1 <> t2
702+ mergeTopBranch (Branch t1) t2 = Branch (t1 <> [t2])
703+ mergeTopBranch t1 (Branch t2) = Branch (t1 : t2)
704+ mergeTopBranch t1 t2 = Branch [t1, t2]
705+
697706-- | Clamp a tree to contain only expressions with a fixed number of elements.
698707clampTree :: Int -> ExpansionTree -> ExpansionTree
699708clampTree sz a = maybe (Branch [] ) id (go a)
@@ -831,31 +840,31 @@ validateExpandedList ::
831840validateExpandedList terms rules = go rules
832841 where
833842 go :: ExpansionTree -> m (Rule -> CDDLResult )
834- go (Leaf choice) = do
843+ go (Leaf choice) = do
835844 res <- validateListWithExpandedRules terms choice
836845 case res of
837846 [] -> pure Valid
838847 _ -> case last res of
839848 (_, CBORTermResult _ (Valid _)) -> pure Valid
840849 _ -> pure $ \ r -> ListExpansionFail r rules (Leaf res)
841- go (FilterBranch f x) = validateTerm (NE. head terms) (arrayFilter f) >>= \ case
842- (CBORTermResult _ (Valid _)) -> go x
843- -- In this case we insert a leaf since we haven't actually validated the
844- -- subnodes.
845- err -> pure $ \ r -> ListExpansionFail r rules $ FilterBranch f $ Leaf [(r, err)]
850+ go (FilterBranch f x) =
851+ validateTerm (NE. head terms) (arrayFilter f) >>= \ case
852+ (CBORTermResult _ (Valid _)) -> go x
853+ -- In this case we insert a leaf since we haven't actually validated the
854+ -- subnodes.
855+ err -> pure $ \ r -> ListExpansionFail r rules $ FilterBranch f $ Leaf [(r, err)]
846856 go (Branch xs) = goBranch xs
847857
848858 goBranch [] = pure $ \ r -> ListExpansionFail r rules $ Branch []
849- goBranch (x: xs) = go x <&> ($ dummyRule) >>= \ case
850- Valid _ -> pure Valid
851- ListExpansionFail _ _ errors -> prependBranchErrors errors <$> goBranch xs
859+ goBranch (x : xs) =
860+ go x <&> ($ dummyRule) >>= \ case
861+ Valid _ -> pure Valid
862+ ListExpansionFail _ _ errors -> prependBranchErrors errors <$> goBranch xs
852863
853864 prependBranchErrors errors res = case res dummyRule of
854- Valid _ -> Valid
865+ Valid _ -> Valid
855866 ListExpansionFail _ _ errors2 -> \ r ->
856- ListExpansionFail r rules $ errors <> errors2
857-
858-
867+ ListExpansionFail r rules $ mergeTopBranch errors errors2
859868
860869validateList ::
861870 MonadReader CDDL m => [Term ] -> Rule -> m CDDLResult
@@ -866,7 +875,7 @@ validateList terms rule =
866875 Array rules ->
867876 case terms of
868877 [] -> ifM (and <$> mapM isOptional rules) (pure Valid ) (pure InvalidRule )
869- t: ts ->
878+ t : ts ->
870879 ask >>= \ cddl ->
871880 let sequencesOfRules =
872881 runReader (expandRules (length terms) $ flattenGroup cddl rules) cddl
@@ -877,6 +886,29 @@ validateList terms rule =
877886--------------------------------------------------------------------------------
878887-- Maps
879888
889+ -- | Does the map comtain a key matching this rule?
890+ --
891+ -- If so, return the matching term. Otherwise, return the list of all the terms
892+ -- that failed to match
893+ containsMatchingKey ::
894+ forall m .
895+ MonadReader CDDL m =>
896+ NE. NonEmpty (Term , Term ) ->
897+ Rule ->
898+ m (Either [ANonMatchedItem ] AMatchedItem )
899+ containsMatchingKey terms rule = do
900+ let tryKey (k, v) = do
901+ result <- validateTerm k rule
902+ case result of
903+ CBORTermResult _ (Valid _) -> pure $ Right (AMatchedItem k v rule)
904+ CBORTermResult _ res -> pure $ Left (ANonMatchedItem k v [Left (rule, res)])
905+
906+ results <- traverse tryKey (NE. toList terms)
907+ case rights results of
908+ (m: _) -> pure $ Right m
909+ [] -> pure $ Left $ lefts results
910+
911+
880912validateMapWithExpandedRules ::
881913 forall m .
882914 MonadReader CDDL m =>
@@ -916,25 +948,34 @@ validateMapWithExpandedRules =
916948validateExpandedMap ::
917949 forall m .
918950 MonadReader CDDL m =>
919- [ (Term , Term )] ->
920- [[ Rule ]] ->
951+ NE. NonEmpty (Term , Term ) ->
952+ ExpansionTree ->
921953 m (Rule -> CDDLResult )
922954validateExpandedMap terms rules = go rules
923955 where
924- go :: [[Rule ]] -> m (Rule -> CDDLResult )
925- go [] = pure $ \ r -> MapExpansionFail r rules []
926- go (choice : choices) = do
927- res <- validateMapWithExpandedRules terms choice
956+ go :: ExpansionTree -> m (Rule -> CDDLResult )
957+ go (Leaf choice) = do
958+ res <- validateMapWithExpandedRules (NE. toList terms) choice
928959 case res of
929960 (_, Nothing ) -> pure Valid
930- (matches, Just notMatched) ->
931- go choices
932- >>= ( \ case
933- Valid _ -> pure Valid
934- MapExpansionFail _ _ errors ->
935- pure $ \ r -> MapExpansionFail r rules ((matches, notMatched) : errors)
936- )
937- . ($ dummyRule)
961+ (matches, Just notMatched) -> pure $ \ r ->
962+ MapExpansionFail r rules [(matches, notMatched)]
963+ go (FilterBranch f x) =
964+ containsMatchingKey terms (mapFilter f) >>= \ case
965+ Right _ -> go x
966+ Left errs -> pure $ \ r -> MapExpansionFail r rules $ ([] , ) <$> errs
967+ go (Branch xs) = goBranch xs
968+
969+ goBranch [] = pure $ \ r -> MapExpansionFail r rules []
970+ goBranch (x : xs) =
971+ go x <&> ($ dummyRule) >>= \ case
972+ Valid _ -> pure Valid
973+ MapExpansionFail _ _ errors -> prependBranchErrors errors <$> goBranch xs
974+
975+ prependBranchErrors errors res = case res dummyRule of
976+ Valid _ -> Valid
977+ MapExpansionFail _ _ errors2 -> \ r ->
978+ MapExpansionFail r rules $ errors <> errors2
938979
939980validateMap ::
940981 MonadReader CDDL m =>
@@ -946,11 +987,11 @@ validateMap terms rule =
946987 Map rules ->
947988 case terms of
948989 [] -> ifM (and <$> mapM isOptional rules) (pure Valid ) (pure InvalidRule )
949- _ ->
990+ x : xs ->
950991 ask >>= \ cddl ->
951992 let sequencesOfRules =
952993 runReader (expandRules (length terms) $ flattenGroup cddl rules) cddl
953- in validateExpandedMap terms sequencesOfRules
994+ in validateExpandedMap (x NE. :| xs) sequencesOfRules
954995 Choice opts -> validateChoice (validateMap terms) opts
955996 _ -> pure UnapplicableRule
956997
0 commit comments