@@ -19,8 +19,9 @@ import Data.Bifunctor
19
19
import Data.Bits hiding (And )
20
20
import Data.ByteString qualified as BS
21
21
import Data.ByteString.Lazy qualified as BSL
22
+ import Data.Either (lefts , rights )
22
23
import Data.Function ((&) )
23
- import Data.Functor ((<&>) , ($>) )
24
+ import Data.Functor ((<&>) )
24
25
import Data.Functor.Identity
25
26
import Data.IntSet qualified as IS
26
27
import Data.List.NonEmpty qualified as NE
@@ -662,7 +663,7 @@ flattenGroup cddl nodes =
662
663
data Filter
663
664
= NoFilter
664
665
| Filter { mapFilter :: Rule , arrayFilter :: Rule }
665
- deriving Show
666
+ deriving ( Show )
666
667
667
668
-- | A tree of possible expansions of a rule matching the size of a container to
668
669
-- validate. This tree contains filters at each node, such that we can
@@ -694,6 +695,14 @@ mergeTrees (a : as) = foldl' go a as
694
695
go (Branch xs) b = Branch $ fmap (flip go b) xs
695
696
go (FilterBranch f x) b = FilterBranch f $ go x b
696
697
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
+
697
706
-- | Clamp a tree to contain only expressions with a fixed number of elements.
698
707
clampTree :: Int -> ExpansionTree -> ExpansionTree
699
708
clampTree sz a = maybe (Branch [] ) id (go a)
@@ -831,31 +840,31 @@ validateExpandedList ::
831
840
validateExpandedList terms rules = go rules
832
841
where
833
842
go :: ExpansionTree -> m (Rule -> CDDLResult )
834
- go (Leaf choice) = do
843
+ go (Leaf choice) = do
835
844
res <- validateListWithExpandedRules terms choice
836
845
case res of
837
846
[] -> pure Valid
838
847
_ -> case last res of
839
848
(_, CBORTermResult _ (Valid _)) -> pure Valid
840
849
_ -> 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)]
846
856
go (Branch xs) = goBranch xs
847
857
848
858
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
852
863
853
864
prependBranchErrors errors res = case res dummyRule of
854
- Valid _ -> Valid
865
+ Valid _ -> Valid
855
866
ListExpansionFail _ _ errors2 -> \ r ->
856
- ListExpansionFail r rules $ errors <> errors2
857
-
858
-
867
+ ListExpansionFail r rules $ mergeTopBranch errors errors2
859
868
860
869
validateList ::
861
870
MonadReader CDDL m => [Term ] -> Rule -> m CDDLResult
@@ -866,7 +875,7 @@ validateList terms rule =
866
875
Array rules ->
867
876
case terms of
868
877
[] -> ifM (and <$> mapM isOptional rules) (pure Valid ) (pure InvalidRule )
869
- t: ts ->
878
+ t : ts ->
870
879
ask >>= \ cddl ->
871
880
let sequencesOfRules =
872
881
runReader (expandRules (length terms) $ flattenGroup cddl rules) cddl
@@ -877,6 +886,29 @@ validateList terms rule =
877
886
--------------------------------------------------------------------------------
878
887
-- Maps
879
888
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
+
880
912
validateMapWithExpandedRules ::
881
913
forall m .
882
914
MonadReader CDDL m =>
@@ -916,25 +948,34 @@ validateMapWithExpandedRules =
916
948
validateExpandedMap ::
917
949
forall m .
918
950
MonadReader CDDL m =>
919
- [ (Term , Term )] ->
920
- [[ Rule ]] ->
951
+ NE. NonEmpty (Term , Term ) ->
952
+ ExpansionTree ->
921
953
m (Rule -> CDDLResult )
922
954
validateExpandedMap terms rules = go rules
923
955
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
928
959
case res of
929
960
(_, 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
938
979
939
980
validateMap ::
940
981
MonadReader CDDL m =>
@@ -946,11 +987,11 @@ validateMap terms rule =
946
987
Map rules ->
947
988
case terms of
948
989
[] -> ifM (and <$> mapM isOptional rules) (pure Valid ) (pure InvalidRule )
949
- _ ->
990
+ x : xs ->
950
991
ask >>= \ cddl ->
951
992
let sequencesOfRules =
952
993
runReader (expandRules (length terms) $ flattenGroup cddl rules) cddl
953
- in validateExpandedMap terms sequencesOfRules
994
+ in validateExpandedMap (x NE. :| xs) sequencesOfRules
954
995
Choice opts -> validateChoice (validateMap terms) opts
955
996
_ -> pure UnapplicableRule
956
997
0 commit comments