@@ -3,6 +3,7 @@ module Data.Schematic.Validation where
33import Control.Monad
44import Control.Monad.Validation
55import Data.Aeson
6+import Data.Aeson.Internal
67import Data.Aeson.Types
78import Data.Foldable
89import Data.Functor.Identity
@@ -17,6 +18,7 @@ import Data.Traversable
1718import Data.Union
1819import Data.Vector as V
1920import Data.Vinyl
21+import Data.Vinyl.TypeLevel
2022import Prelude as P
2123import Text.Regex.TDFA
2224
@@ -37,7 +39,7 @@ instance (TopLevel a, SingI a, FromJSON (JsonRepr a))
3739
3840isValid :: ParseResult a -> Bool
3941isValid (Valid _) = True
40−isValid _ = False
42+isValid _ = False
4143
4244isDecodingError :: ParseResult a -> Bool
4345isDecodingError (DecodingError _) = True
@@ -48,11 +50,11 @@ isValidationError (ValidationError _) = True
4850isValidationError _ = False
4951
5052validateTextConstraint
51− :: JSONPath
53+ :: JSONPathText
5254 -> Text
5355 -> Sing (tcs :: TextConstraint)
5456 -> Validation ()
55−validateTextConstraint (JSONPath path) t = \case
57+validateTextConstraint (JSONPathText path) t = \case
5658 STEq n -> do
5759 let
5860 nlen = withKnownNat n $ natVal n
@@ -105,11 +107,11 @@ validateTextConstraint (JSONPath path) t = \case
105107 unless (matching ss) warn
106108
107109validateNumberConstraint
108− :: JSONPath
110+ :: JSONPathText
109111 -> Scientific
110112 -> Sing (tcs :: NumberConstraint)
111113 -> Validation ()
112−validateNumberConstraint (JSONPath path) num = \case
114+validateNumberConstraint (JSONPathText path) num = \case
113115 SNEq n -> do
114116 let
115117 nlen = withKnownNat n $ natVal n
@@ -147,11 +149,11 @@ validateNumberConstraint (JSONPath path) num = \case
147149 unless predicate warn
148150
149151validateArrayConstraint
150− :: JSONPath
152+ :: JSONPathText
151153 -> V.Vector a
152154 -> Sing (tcs :: ArrayConstraint)
153155 -> Validation ()
154−validateArrayConstraint (JSONPath path) v = \case
156+validateArrayConstraint (JSONPathText path) v = \case
155157 SAEq n -> do
156158 let
157159 nlen = withKnownNat n $ natVal n
@@ -159,10 +161,38 @@ validateArrayConstraint (JSONPath path) v = \case
159161 errMsg = "length should be == " <> T.pack (show nlen)
160162 warn = vWarning $ mmSingleton path (pure errMsg)
161163 unless predicate warn
164+ SAGt n -> do
165+ let
166+ nlen = withKnownNat n $ natVal n
167+ predicate = fromIntegral (V.length v) > nlen
168+ errMsg = "length should be > " <> T.pack (show nlen)
169+ warn = vWarning $ mmSingleton path (pure errMsg)
170+ unless predicate warn
171+ SAGe n -> do
172+ let
173+ nlen = withKnownNat n $ natVal n
174+ predicate = fromIntegral (V.length v) >= nlen
175+ errMsg = "length should be >= " <> T.pack (show nlen)
176+ warn = vWarning $ mmSingleton path (pure errMsg)
177+ unless predicate warn
178+ SALt n -> do
179+ let
180+ nlen = withKnownNat n $ natVal n
181+ predicate = fromIntegral (V.length v) < nlen
182+ errMsg = "length should be < " <> T.pack (show nlen)
183+ warn = vWarning $ mmSingleton path (pure errMsg)
184+ unless predicate warn
185+ SALe n -> do
186+ let
187+ nlen = withKnownNat n $ natVal n
188+ predicate = fromIntegral (V.length v) <= nlen
189+ errMsg = "length should be <= " <> T.pack (show nlen)
190+ warn = vWarning $ mmSingleton path (pure errMsg)
191+ unless predicate warn
162192
163193validateJsonRepr
164194 :: Sing schema
165− -> [DemotedPathSegment]
195+ -> JSONPath
166196 -> JsonRepr schema
167197 -> Validation ()
168198validateJsonRepr sschema dpath jr = case jr of
@@ -196,7 +226,7 @@ validateJsonRepr sschema dpath jr = case jr of
196226 process cs
197227 process acs
198228 for_ (V.indexed v) $ \(ix, jr') -> do
199− let newPath = dpath <> pure (DIx $ fromIntegral ix)
229+ let newPath = dpath <> pure (Index $ fromIntegral ix)
200230 validateJsonRepr s newPath jr'
201231 ReprOptional d -> case sschema of
202232 SSchemaOptional ss -> case d of
@@ -208,17 +238,49 @@ validateJsonRepr sschema dpath jr = case jr of
208238 go :: Rec FieldRepr (ts :: [(Symbol, Schema)] ) -> Validation ()
209239 go RNil = pure ()
210240 go (f@(FieldRepr d) :& ftl) = do
211− let newPath = dpath <> [DKey (knownFieldName f)]
241+ let newPath = dpath <> [Key (knownFieldName f)]
212242 validateJsonRepr (knownFieldSchema f) newPath d
213243 go ftl
214− ReprUnion ru -> case sschema of
215− SSchemaUnion su -> validateUnion su ru
216− where
217− validateUnion :: Sing us -> Union JsonRepr us -> Validation ()
218− validateUnion ss r = case (ss,r) of
219− (SCons s _, This v) -> validateJsonRepr s dpath v
220− (SCons _ stl, That r') -> validateUnion stl r'
221− (SNil,_) -> fail "Invalid union. Please report this as a bug"
244+ ReprUnion _ -> pure () -- FIXME
245+ -- case sschema of
246+ -- SSchemaUnion ss -> case ss of
247+ -- SCons s stl -> case umatch' s u of
248+ -- Nothing -> case urestrict u of
249+ -- Nothing ->
250+ -- fail "impossible to produce subUnion, please report this as a bug"
251+ -- Just x -> do
252+ -- let
253+ -- JSONPathText path = demotedPathToText dpath
254+ -- case stl of
255+ -- SNil -> void $ vWarning $ mmSingleton path
256+ -- $ pure "union handling error, please report this as bug"
257+ -- SCons s' stl' ->
258+ -- validateJsonRepr (SSchemaUnion (SCons s' stl')) dpath
259+ -- $ toUnion (SCons s' stl') x
260+ -- Just x -> validateJsonRepr s dpath x
261+
262+-- subUnion
263+-- :: Sing (s ': stl)
264+-- -> ( USubset stl (s ': stl) (RImage stl (s ': stl))
265+-- => Union f (s ': stl)
266+-- -> Maybe (Union f stl) )
267+-- subUnion (SCons s stl) = urestrict
268+
269+-- withUSubset
270+-- :: Sing (s ': stl)
271+-- -> (USubset stl (s ': stl) (RImage stl (s ': stl)) => Maybe (Union f stl))
272+-- -> Maybe (Union f stl)
273+-- withUSubset (SCons s stl) r = r
274+
275+toUnion
276+ :: USubset s' (s ': ss) (RImage s' (s ': ss))
277+ => Sing (s ': ss)
278+ -> Union JsonRepr s'
279+ -> JsonRepr ('SchemaUnion (s ': ss))
280+toUnion _ = ReprUnion . urelax
281+
282+umatch' :: UElem a as i => Sing a -> Union f as -> Maybe (f a)
283+umatch' _ u = umatch u
222284
223285parseAndValidateJson
224286 :: forall schema