1module Data.Schematic.Validation where
4import Control.Monad.Validation
6import Data.Functor.Identity
8import Data.Schematic.Path
9import Data.Schematic.Schema
11import Data.Singletons.Prelude
12import Data.Singletons.TypeLits
14import Data.Traversable
16import Data.Vector as V
18import Data.Vinyl.TypeLevel
23type Validation a = ValidationT ErrorMap Identity a
25type ErrorMap = MonoidMap Text [Text]
29 | DecodingError Text -- static
30 | ValidationError ErrorMap -- runtime
31 deriving (Show, Eq, Functor, Foldable, Traversable)
33isValid :: ParseResult a -> Bool
34isValid (Valid _) = True
37isDecodingError :: ParseResult a -> Bool
38isDecodingError (DecodingError _) = True
39isDecodingError _ = False
41isValidationError :: ParseResult a -> Bool
42isValidationError (ValidationError _) = True
43isValidationError _ = False
48 -> Sing (tcs :: TextConstraint)
50validateTextConstraint (JSONPath path) t = \case
53 nlen = withKnownNat n $ natVal n
54 predicate = nlen == (fromIntegral $ T.length t)
55 errMsg = "length of " <> path <> " should be == " <> T.pack (show nlen)
56 warn = vWarning $ mmSingleton path (pure errMsg)
60 nlen = withKnownNat n $ natVal n
61 predicate = nlen < (fromIntegral $ T.length t)
62 errMsg = "length of " <> path <> " should be < " <> T.pack (show nlen)
63 warn = vWarning $ mmSingleton path (pure errMsg)
67 nlen = withKnownNat n $ natVal n
68 predicate = nlen <= (fromIntegral $ T.length t)
69 errMsg = "length of " <> path <> " should be <= " <> T.pack (show nlen)
70 warn = vWarning $ mmSingleton path (pure errMsg)
74 nlen = withKnownNat n $ natVal n
75 predicate = nlen > (fromIntegral $ T.length t)
76 errMsg = "length of " <> path <> " should be > " <> T.pack (show nlen)
77 warn = vWarning $ mmSingleton path (pure errMsg)
81 nlen = withKnownNat n $ natVal n
82 predicate = nlen >= (fromIntegral $ T.length t)
83 errMsg = "length of " <> path <> " should be >= " <> T.pack (show nlen)
84 warn = vWarning $ mmSingleton path (pure errMsg)
88 regex = withKnownSymbol r $ fromSing r
89 predicate = matchTest (makeRegex (T.unpack regex) :: Regex) (T.unpack t)
90 errMsg = path <> " must match " <> regex
91 warn = vWarning $ mmSingleton path (pure errMsg)
95 matching :: Sing (s :: [Symbol]) -> Bool
97 matching (SCons s@SSym fs) = T.pack (symbolVal s) == t || matching fs
98 errMsg = path <> " must be one of " <> T.pack (show (fromSing ss))
99 warn = vWarning $ mmSingleton path (pure errMsg)
100 unless (matching ss) warn
102validateNumberConstraint
105 -> Sing (tcs :: NumberConstraint)
107validateNumberConstraint (JSONPath path) num = \case
110 nlen = withKnownNat n $ natVal n
111 predicate = fromIntegral nlen == num
112 errMsg = path <> " should be == " <> T.pack (show nlen)
113 warn = vWarning $ mmSingleton path (pure errMsg)
114 unless predicate warn
117 nlen = withKnownNat n $ natVal n
118 predicate = num > fromIntegral nlen
119 errMsg = path <> " should be > " <> T.pack (show nlen)
120 warn = vWarning $ mmSingleton path (pure errMsg)
121 unless predicate warn
124 nlen = withKnownNat n $ natVal n
125 predicate = num >= fromIntegral nlen
126 errMsg = path <> " should be >= " <> T.pack (show nlen)
127 warn = vWarning $ mmSingleton path (pure errMsg)
128 unless predicate warn
131 nlen = withKnownNat n $ natVal n
132 predicate = fromIntegral nlen < num
133 errMsg = path <> " should be < " <> T.pack (show nlen)
134 warn = vWarning $ mmSingleton path (pure errMsg)
135 unless predicate warn
138 nlen = withKnownNat n $ natVal n
139 predicate = fromIntegral nlen <= num
140 errMsg = path <> " should be <= " <> T.pack (show nlen)
141 warn = vWarning $ mmSingleton path (pure errMsg)
142 unless predicate warn
144validateArrayConstraint
147 -> Sing (tcs :: ArrayConstraint)
149validateArrayConstraint (JSONPath path) v = \case
152 nlen = withKnownNat n $ natVal n
153 predicate = nlen == fromIntegral (V.length v)
154 errMsg = "length of " <> path <> " should be == " <> T.pack (show nlen)
155 warn = vWarning $ mmSingleton path (pure errMsg)
156 unless predicate warn
160 -> [DemotedPathSegment]
163validateJsonRepr sschema dpath jr = case jr of
164 ReprText t -> case sschema of
165 SSchemaText scs -> do
167 process :: Sing (cs :: [TextConstraint]) -> Validation ()
168 process SNil = pure ()
169 process (SCons c cs) = do
170 validateTextConstraint (demotedPathToText dpath) t c
173 ReprNumber n -> case sschema of
174 SSchemaNumber scs -> do
176 process :: Sing (cs :: [NumberConstraint]) -> Validation ()
177 process SNil = pure ()
178 process (SCons c cs) = do
179 validateNumberConstraint (demotedPathToText dpath) n c
183 ReprBoolean _ -> pure ()
184 ReprArray v -> case sschema of
185 SSchemaArray acs s -> do
187 process :: Sing (cs :: [ArrayConstraint]) -> Validation ()
188 process SNil = pure ()
189 process (SCons c cs) = do
190 validateArrayConstraint (demotedPathToText dpath) v c
193 for_ (V.indexed v) $ \(ix, jr') -> do
194 let newPath = dpath <> pure (DIx $ fromIntegral ix)
195 validateJsonRepr s newPath jr'
196 ReprOptional d -> case sschema of
197 SSchemaOptional ss -> case d of
198 Just x -> validateJsonRepr ss dpath x
200 ReprObject fs -> case sschema of
201 SSchemaObject _ -> go fs
203 go :: Rec FieldRepr (ts :: [(Symbol, Schema)] ) -> Validation ()
205 go (f@(FieldRepr d) :& ftl) = do
206 let newPath = dpath <> [DKey (knownFieldName f)]
207 validateJsonRepr (knownFieldSchema f) newPath d
209 ReprUnion _ -> pure () -- FIXME
211 -- SSchemaUnion ss -> case ss of
212 -- SCons s stl -> case umatch' s u of
213 -- Nothing -> case urestrict u of
215 -- fail "impossible to produce subUnion, please report this as a bug"
218 -- JSONPath path = demotedPathToText dpath
220 -- SNil -> void $ vWarning $ mmSingleton path
221 -- $ pure "union handling error, please report this as bug"
223 -- validateJsonRepr (SSchemaUnion (SCons s' stl')) dpath
224 -- $ toUnion (SCons s' stl') x
225 -- Just x -> validateJsonRepr s dpath x
229-- -> ( USubset stl (s ': stl) (RImage stl (s ': stl))
230-- => Union f (s ': stl)
231-- -> Maybe (Union f stl) )
232-- subUnion (SCons s stl) = urestrict
236-- -> (USubset stl (s ': stl) (RImage stl (s ': stl)) => Maybe (Union f stl))
237-- -> Maybe (Union f stl)
238-- withUSubset (SCons s stl) r = r
241 :: USubset s' (s ': ss) (RImage s' (s ': ss))
244 -> JsonRepr ('SchemaUnion (s ': ss))
245toUnion _ = ReprUnion . urelax
247umatch' :: UElem a as i => Sing a -> Union f as -> Maybe (f a)
248umatch' _ u = umatch u
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list