1module Data.Schematic.Validation where
4import Control.Monad.Validation
6import Data.Functor.Identity
8import Data.Schematic.Path
9import Data.Schematic.Schema
10import Data.Schematic.Utils ()
12import Data.Singletons.Prelude
13import Data.Singletons.TypeLits
15import Data.Traversable
17import Data.Vector as V
19import Data.Vinyl.TypeLevel
24type Validation a = ValidationT ErrorMap Identity a
26type ErrorMap = MonoidMap Text [Text]
30 | DecodingError Text -- static
31 | ValidationError ErrorMap -- runtime
32 deriving (Show, Eq, Functor, Foldable, Traversable)
34isValid :: ParseResult a -> Bool
35isValid (Valid _) = True
38isDecodingError :: ParseResult a -> Bool
39isDecodingError (DecodingError _) = True
40isDecodingError _ = False
42isValidationError :: ParseResult a -> Bool
43isValidationError (ValidationError _) = True
44isValidationError _ = False
49 -> Sing (tcs :: TextConstraint)
51validateTextConstraint (JSONPath path) t = \case
54 nlen = withKnownNat n $ natVal n
55 predicate = nlen == (fromIntegral $ T.length t)
56 errMsg = "length of " <> path <> " should be == " <> T.pack (show nlen)
57 warn = vWarning $ mmSingleton path (pure errMsg)
61 nlen = withKnownNat n $ natVal n
62 predicate = nlen < (fromIntegral $ T.length t)
63 errMsg = "length of " <> path <> " should be < " <> T.pack (show nlen)
64 warn = vWarning $ mmSingleton path (pure errMsg)
68 nlen = withKnownNat n $ natVal n
69 predicate = nlen <= (fromIntegral $ T.length t)
70 errMsg = "length of " <> path <> " should be <= " <> T.pack (show nlen)
71 warn = vWarning $ mmSingleton path (pure errMsg)
75 nlen = withKnownNat n $ natVal n
76 predicate = nlen > (fromIntegral $ T.length t)
77 errMsg = "length of " <> path <> " should be > " <> T.pack (show nlen)
78 warn = vWarning $ mmSingleton path (pure errMsg)
82 nlen = withKnownNat n $ natVal n
83 predicate = nlen >= (fromIntegral $ T.length t)
84 errMsg = "length of " <> path <> " should be >= " <> T.pack (show nlen)
85 warn = vWarning $ mmSingleton path (pure errMsg)
89 regex = withKnownSymbol r $ fromSing r
90 predicate = matchTest (makeRegex (T.unpack regex) :: Regex) (T.unpack t)
91 errMsg = path <> " must match " <> regex
92 warn = vWarning $ mmSingleton path (pure errMsg)
96 matching :: Sing (s :: [Symbol]) -> Bool
98 matching (SCons s@SSym fs) = T.pack (symbolVal s) == t || matching fs
99 errMsg = path <> " must be one of " <> T.pack (show (fromSing ss))
100 warn = vWarning $ mmSingleton path (pure errMsg)
101 unless (matching ss) warn
103validateNumberConstraint
106 -> Sing (tcs :: NumberConstraint)
108validateNumberConstraint (JSONPath path) num = \case
111 nlen = withKnownNat n $ natVal n
112 predicate = fromIntegral nlen == num
113 errMsg = path <> " should be == " <> T.pack (show nlen)
114 warn = vWarning $ mmSingleton path (pure errMsg)
115 unless predicate warn
118 nlen = withKnownNat n $ natVal n
119 predicate = num > fromIntegral nlen
120 errMsg = path <> " should be > " <> T.pack (show nlen)
121 warn = vWarning $ mmSingleton path (pure errMsg)
122 unless predicate warn
125 nlen = withKnownNat n $ natVal n
126 predicate = num >= fromIntegral nlen
127 errMsg = path <> " should be >= " <> T.pack (show nlen)
128 warn = vWarning $ mmSingleton path (pure errMsg)
129 unless predicate warn
132 nlen = withKnownNat n $ natVal n
133 predicate = fromIntegral nlen < num
134 errMsg = path <> " should be < " <> T.pack (show nlen)
135 warn = vWarning $ mmSingleton path (pure errMsg)
136 unless predicate warn
139 nlen = withKnownNat n $ natVal n
140 predicate = fromIntegral nlen <= num
141 errMsg = path <> " should be <= " <> T.pack (show nlen)
142 warn = vWarning $ mmSingleton path (pure errMsg)
143 unless predicate warn
145validateArrayConstraint
148 -> Sing (tcs :: ArrayConstraint)
150validateArrayConstraint (JSONPath path) v = \case
153 nlen = withKnownNat n $ natVal n
154 predicate = nlen == fromIntegral (V.length v)
155 errMsg = "length of " <> path <> " should be == " <> T.pack (show nlen)
156 warn = vWarning $ mmSingleton path (pure errMsg)
157 unless predicate warn
161 -> [DemotedPathSegment]
164validateJsonRepr sschema dpath jr = case jr of
165 ReprText t -> case sschema of
166 SSchemaText scs -> do
168 process :: Sing (cs :: [TextConstraint]) -> Validation ()
169 process SNil = pure ()
170 process (SCons c cs) = do
171 validateTextConstraint (demotedPathToText dpath) t c
174 ReprNumber n -> case sschema of
175 SSchemaNumber scs -> do
177 process :: Sing (cs :: [NumberConstraint]) -> Validation ()
178 process SNil = pure ()
179 process (SCons c cs) = do
180 validateNumberConstraint (demotedPathToText dpath) n c
184 ReprBoolean _ -> pure ()
185 ReprArray v -> case sschema of
186 SSchemaArray acs s -> do
188 process :: Sing (cs :: [ArrayConstraint]) -> Validation ()
189 process SNil = pure ()
190 process (SCons c cs) = do
191 validateArrayConstraint (demotedPathToText dpath) v c
194 for_ (V.indexed v) $ \(ix, jr') -> do
195 let newPath = dpath <> pure (DIx $ fromIntegral ix)
196 validateJsonRepr s newPath jr'
197 ReprOptional d -> case sschema of
198 SSchemaOptional ss -> case d of
199 Just x -> validateJsonRepr ss dpath x
201 ReprObject fs -> case sschema of
202 SSchemaObject _ -> go fs
204 go :: Rec FieldRepr (ts :: [(Symbol, Schema)] ) -> Validation ()
206 go (f@(FieldRepr d) :& ftl) = do
207 let newPath = dpath <> [DKey (knownFieldName f)]
208 validateJsonRepr (knownFieldSchema f) newPath d
210 ReprUnion u -> pure ()
212 -- SSchemaUnion ss -> case ss of
213 -- SCons s stl -> case umatch' s u of
214 -- Nothing -> case urestrict u of
216 -- fail "impossible to produce subUnion, please report this as a bug"
219 -- JSONPath path = demotedPathToText dpath
221 -- SNil -> void $ vWarning $ mmSingleton path
222 -- $ pure "union handling error, please report this as bug"
224 -- validateJsonRepr (SSchemaUnion (SCons s' stl')) dpath
225 -- $ toUnion (SCons s' stl') x
226 -- Just x -> validateJsonRepr s dpath x
230-- -> ( USubset stl (s ': stl) (RImage stl (s ': stl))
231-- => Union f (s ': stl)
232-- -> Maybe (Union f stl) )
233-- subUnion (SCons s stl) = urestrict
237-- -> (USubset stl (s ': stl) (RImage stl (s ': stl)) => Maybe (Union f stl))
238-- -> Maybe (Union f stl)
239-- withUSubset (SCons s stl) r = r
242 :: USubset s' (s ': ss) (RImage s' (s ': ss))
245 -> JsonRepr ('SchemaUnion (s ': ss))
246toUnion _ = ReprUnion . urelax
248umatch' :: UElem a as i => Sing a -> Union f as -> Maybe (f a)
249umatch' _ 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