cuddle 1.6.0.0 → 1.7.0.0
raw patch · 36 files changed
+871/−466 lines, 36 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Codec.CBOR.Cuddle.CBOR.Gen: instance Codec.CBOR.Cuddle.IndexMappable.IndexMappable Codec.CBOR.Cuddle.CDDL.CTree.CTree Codec.CBOR.Cuddle.CDDL.CBORGenerator.GenPhase Codec.CBOR.Cuddle.CBOR.Gen.GenSimple
- Codec.CBOR.Cuddle.CBOR.Validator: data ValidatorStage
- Codec.CBOR.Cuddle.CBOR.Validator.Trace: data ValidatorStage
- Codec.CBOR.Cuddle.CBOR.Validator.Trace: data ValidatorStageSimple
- Codec.CBOR.Cuddle.CBOR.Validator.Trace: instance Codec.CBOR.Cuddle.IndexMappable.IndexMappable Codec.CBOR.Cuddle.CDDL.CTree.CTree Codec.CBOR.Cuddle.CBOR.Validator.Trace.ValidatorStage Codec.CBOR.Cuddle.CBOR.Validator.Trace.ValidatorStageSimple
- Codec.CBOR.Cuddle.CBOR.Validator.Trace: instance Codec.CBOR.Cuddle.IndexMappable.IndexMappable Codec.CBOR.Cuddle.CDDL.CTree.CTree Codec.CBOR.Cuddle.CDDL.Resolve.MonoReferenced Codec.CBOR.Cuddle.CBOR.Validator.Trace.ValidatorStage
- Codec.CBOR.Cuddle.CBOR.Validator.Trace: instance Codec.CBOR.Cuddle.IndexMappable.IndexMappable Codec.CBOR.Cuddle.CDDL.CTree.CTreeRoot Codec.CBOR.Cuddle.CBOR.Validator.Trace.ValidatorStage Codec.CBOR.Cuddle.CBOR.Validator.Trace.ValidatorStageSimple
- Codec.CBOR.Cuddle.CBOR.Validator.Trace: instance Codec.CBOR.Cuddle.IndexMappable.IndexMappable Codec.CBOR.Cuddle.CDDL.CTree.CTreeRoot Codec.CBOR.Cuddle.CDDL.Resolve.MonoReferenced Codec.CBOR.Cuddle.CBOR.Validator.Trace.ValidatorStage
- Codec.CBOR.Cuddle.CBOR.Validator.Trace: instance GHC.Classes.Eq (Codec.CBOR.Cuddle.CDDL.CTree.Node Codec.CBOR.Cuddle.CBOR.Validator.Trace.ValidatorStageSimple)
- Codec.CBOR.Cuddle.CBOR.Validator.Trace: instance GHC.Classes.Eq (Codec.CBOR.Cuddle.CDDL.XTerm Codec.CBOR.Cuddle.CBOR.Validator.Trace.ValidatorStage)
- Codec.CBOR.Cuddle.CBOR.Validator.Trace: instance GHC.Show.Show (Codec.CBOR.Cuddle.CDDL.CTree.Node Codec.CBOR.Cuddle.CBOR.Validator.Trace.ValidatorStageSimple)
- Codec.CBOR.Cuddle.CBOR.Validator.Trace: instance GHC.Show.Show (Codec.CBOR.Cuddle.CDDL.XTerm Codec.CBOR.Cuddle.CBOR.Validator.Trace.ValidatorStage)
- Codec.CBOR.Cuddle.CBOR.Validator.Trace: instance Prettyprinter.Internal.Pretty (Codec.CBOR.Cuddle.CDDL.CTree.CTree Codec.CBOR.Cuddle.CBOR.Validator.Trace.ValidatorStageSimple)
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: CBORGen :: ReaderT GenEnv AntiGen a -> CBORGen a
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: CBORValidator :: (Term -> CustomValidatorResult) -> CBORValidator
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: CustomValidatorFailure :: Text -> CustomValidatorResult
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: CustomValidatorSuccess :: CustomValidatorResult
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: G :: [WrappedTerm] -> WrappedTerm
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: GenEnv :: CTreeRoot GenPhase -> Bool -> GenEnv
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: P :: Term -> Term -> WrappedTerm
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: S :: Term -> WrappedTerm
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: [geRoot] :: GenEnv -> CTreeRoot GenPhase
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: [geTwiddle] :: GenEnv -> Bool
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: class HasGenerator a
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: class HasValidator a
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: data CustomValidatorResult
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: data GenEnv
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: data GenPhase
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: data WrappedTerm
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: data family XXCTree i
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: generatorL :: HasGenerator a => Lens' a (Maybe (CBORGen WrappedTerm))
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: instance Control.Monad.Reader.Class.MonadReader Codec.CBOR.Cuddle.CDDL.CBORGenerator.GenEnv Codec.CBOR.Cuddle.CDDL.CBORGenerator.CBORGen
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: instance GHC.Base.Applicative Codec.CBOR.Cuddle.CDDL.CBORGenerator.CBORGen
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: instance GHC.Base.Functor Codec.CBOR.Cuddle.CDDL.CBORGenerator.CBORGen
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: instance GHC.Base.Monad Codec.CBOR.Cuddle.CDDL.CBORGenerator.CBORGen
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: instance GHC.Classes.Eq Codec.CBOR.Cuddle.CDDL.CBORGenerator.CustomValidatorResult
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: instance GHC.Classes.Eq Codec.CBOR.Cuddle.CDDL.CBORGenerator.WrappedTerm
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: instance GHC.Classes.Ord Codec.CBOR.Cuddle.CDDL.CBORGenerator.WrappedTerm
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: instance GHC.Generics.Generic Codec.CBOR.Cuddle.CDDL.CBORGenerator.CustomValidatorResult
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: instance GHC.Generics.Generic Codec.CBOR.Cuddle.CDDL.CBORGenerator.GenEnv
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: instance GHC.Show.Show Codec.CBOR.Cuddle.CDDL.CBORGenerator.CustomValidatorResult
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: instance GHC.Show.Show Codec.CBOR.Cuddle.CDDL.CBORGenerator.WrappedTerm
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: instance Test.QuickCheck.GenT.MonadGen Codec.CBOR.Cuddle.CDDL.CBORGenerator.CBORGen
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: liftAntiGen :: AntiGen a -> CBORGen a
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: lookupCddl :: Name -> CBORGen (Maybe (CTree GenPhase))
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: newtype CBORGen a
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: newtype CBORValidator
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: runCBORGen :: GenEnv -> CBORGen a -> AntiGen a
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: validatorL :: HasValidator a => Lens' a (Maybe CBORValidator)
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: withAntiGen :: (AntiGen a -> AntiGen b) -> CBORGen a -> CBORGen b
- Codec.CBOR.Cuddle.CDDL.CBORGenerator: withTwiddle :: Bool -> CBORGen a -> CBORGen a
- Codec.CBOR.Cuddle.CDDL.Resolve: instance Codec.CBOR.Cuddle.IndexMappable.IndexMappable Codec.CBOR.Cuddle.CDDL.CTree.CTree Codec.CBOR.Cuddle.CDDL.Resolve.MonoReferenced Codec.CBOR.Cuddle.CDDL.CBORGenerator.GenPhase
- Codec.CBOR.Cuddle.CDDL.Resolve: instance Codec.CBOR.Cuddle.IndexMappable.IndexMappable Codec.CBOR.Cuddle.CDDL.CTree.CTreeRoot Codec.CBOR.Cuddle.CDDL.Resolve.MonoReferenced Codec.CBOR.Cuddle.CDDL.CBORGenerator.GenPhase
- Codec.CBOR.Cuddle.Comments: Comment :: Text -> Comment
- Codec.CBOR.Cuddle.Comments: infixr 0 //-
- Codec.CBOR.Cuddle.Comments: newtype Comment
- Codec.CBOR.Cuddle.Huddle: instance Codec.CBOR.Cuddle.CDDL.CBORGenerator.HasGenerator (Codec.CBOR.Cuddle.CDDL.XRule Codec.CBOR.Cuddle.Huddle.HuddleStage)
- Codec.CBOR.Cuddle.Huddle: instance Codec.CBOR.Cuddle.CDDL.CBORGenerator.HasGenerator Codec.CBOR.Cuddle.Huddle.Rule
- Codec.CBOR.Cuddle.Huddle: instance Codec.CBOR.Cuddle.CDDL.CBORGenerator.HasValidator (Codec.CBOR.Cuddle.CDDL.XRule Codec.CBOR.Cuddle.Huddle.HuddleStage)
- Codec.CBOR.Cuddle.Huddle: instance Codec.CBOR.Cuddle.CDDL.CBORGenerator.HasValidator Codec.CBOR.Cuddle.Huddle.Rule
- Codec.CBOR.Cuddle.Huddle: instance Codec.CBOR.Cuddle.Huddle.IsCborable Codec.CBOR.Cuddle.Huddle.GRef
- Codec.CBOR.Cuddle.Huddle: instance Codec.CBOR.Cuddle.Huddle.IsChoosable Codec.CBOR.Cuddle.Huddle.GRef Codec.CBOR.Cuddle.Huddle.Type2
- Codec.CBOR.Cuddle.Huddle: instance Codec.CBOR.Cuddle.Huddle.IsComparable Codec.CBOR.Cuddle.Huddle.GRef
- Codec.CBOR.Cuddle.Huddle: instance Codec.CBOR.Cuddle.Huddle.IsConstrainable Codec.CBOR.Cuddle.Huddle.GRef Codec.CBOR.Cuddle.Huddle.CGRefType
- Codec.CBOR.Cuddle.Huddle: instance Codec.CBOR.Cuddle.Huddle.IsType0 Codec.CBOR.Cuddle.Huddle.GRef
- Codec.CBOR.Cuddle.Huddle: instance GHC.Show.Show Codec.CBOR.Cuddle.Huddle.GRef
- Codec.CBOR.Cuddle.Huddle: withAntiGen :: HasGenerator a => (CTreeRoot GenPhase -> AntiGen WrappedTerm) -> a -> a
- Codec.CBOR.Cuddle.Huddle: withGenerator :: HasGenerator a => (CTreeRoot GenPhase -> Gen WrappedTerm) -> a -> a
+ Codec.CBOR.Cuddle.CBOR.Gen: generateFromGRef :: HasCallStack => GRef -> CBORGen RuleTerm
+ Codec.CBOR.Cuddle.CBOR.Gen: instance Codec.CBOR.Cuddle.IndexMappable.IndexMappable Codec.CBOR.Cuddle.CDDL.CTree.CTree Codec.CBOR.Cuddle.CDDL.Custom.Generator.GenPhase Codec.CBOR.Cuddle.CBOR.Gen.GenSimple
+ Codec.CBOR.Cuddle.CBOR.Validator: data ValidatorPhase
+ Codec.CBOR.Cuddle.CBOR.Validator: validateFromGRef :: HasCallStack => GRef -> Term -> Validator ()
+ Codec.CBOR.Cuddle.CBOR.Validator: validateFromName :: HasCallStack => Name -> Term -> Validator ()
+ Codec.CBOR.Cuddle.CBOR.Validator.Trace: data ValidatorPhaseSimple
+ Codec.CBOR.Cuddle.CBOR.Validator.Trace: instance Codec.CBOR.Cuddle.IndexMappable.IndexMappable Codec.CBOR.Cuddle.CDDL.CTree.CTree Codec.CBOR.Cuddle.CDDL.Custom.Validator.ValidatorPhase Codec.CBOR.Cuddle.CBOR.Validator.Trace.ValidatorPhaseSimple
+ Codec.CBOR.Cuddle.CBOR.Validator.Trace: instance Codec.CBOR.Cuddle.IndexMappable.IndexMappable Codec.CBOR.Cuddle.CDDL.CTree.CTreeRoot Codec.CBOR.Cuddle.CDDL.Custom.Validator.ValidatorPhase Codec.CBOR.Cuddle.CBOR.Validator.Trace.ValidatorPhaseSimple
+ Codec.CBOR.Cuddle.CBOR.Validator.Trace: instance GHC.Classes.Eq (Codec.CBOR.Cuddle.CDDL.CTree.Node Codec.CBOR.Cuddle.CBOR.Validator.Trace.ValidatorPhaseSimple)
+ Codec.CBOR.Cuddle.CBOR.Validator.Trace: instance GHC.Show.Show (Codec.CBOR.Cuddle.CDDL.CTree.Node Codec.CBOR.Cuddle.CBOR.Validator.Trace.ValidatorPhaseSimple)
+ Codec.CBOR.Cuddle.CBOR.Validator.Trace: instance Prettyprinter.Internal.Pretty (Codec.CBOR.Cuddle.CDDL.CTree.XXCTree Codec.CBOR.Cuddle.CBOR.Validator.Trace.ValidatorPhaseSimple)
+ Codec.CBOR.Cuddle.CDDL: GRef :: Text -> GRef
+ Codec.CBOR.Cuddle.CDDL: instance GHC.Show.Show Codec.CBOR.Cuddle.CDDL.GRef
+ Codec.CBOR.Cuddle.CDDL: newtype GRef
+ Codec.CBOR.Cuddle.CDDL.Custom.Core: GroupTerm :: [RuleTerm] -> RuleTerm
+ Codec.CBOR.Cuddle.CDDL.Custom.Core: PairTerm :: Term -> Term -> RuleTerm
+ Codec.CBOR.Cuddle.CDDL.Custom.Core: SingleTerm :: Term -> RuleTerm
+ Codec.CBOR.Cuddle.CDDL.Custom.Core: class MonadCddl (m :: Type -> Type) where {
+ Codec.CBOR.Cuddle.CDDL.Custom.Core: data RuleTerm
+ Codec.CBOR.Cuddle.CDDL.Custom.Core: instance GHC.Classes.Eq Codec.CBOR.Cuddle.CDDL.Custom.Core.RuleTerm
+ Codec.CBOR.Cuddle.CDDL.Custom.Core: instance GHC.Classes.Ord Codec.CBOR.Cuddle.CDDL.Custom.Core.RuleTerm
+ Codec.CBOR.Cuddle.CDDL.Custom.Core: instance GHC.Show.Show Codec.CBOR.Cuddle.CDDL.Custom.Core.RuleTerm
+ Codec.CBOR.Cuddle.CDDL.Custom.Core: lookupCddl :: MonadCddl m => Name -> m (Maybe (CTree (Phase m)))
+ Codec.CBOR.Cuddle.CDDL.Custom.Core: lookupGRef :: MonadCddl m => GRef -> m (Maybe (CTree (Phase m)))
+ Codec.CBOR.Cuddle.CDDL.Custom.Core: type Phase (m :: Type -> Type);
+ Codec.CBOR.Cuddle.CDDL.Custom.Core: }
+ Codec.CBOR.Cuddle.CDDL.Custom.Generator: GenConfig :: CTreeRoot GenPhase -> !Bool -> GenConfig
+ Codec.CBOR.Cuddle.CDDL.Custom.Generator: GenEnv :: GenConfig -> Map Name (CTree GenPhase) -> GenEnv
+ Codec.CBOR.Cuddle.CDDL.Custom.Generator: [gcRoot] :: GenConfig -> CTreeRoot GenPhase
+ Codec.CBOR.Cuddle.CDDL.Custom.Generator: [gcTwiddle] :: GenConfig -> !Bool
+ Codec.CBOR.Cuddle.CDDL.Custom.Generator: [geConfig] :: GenEnv -> GenConfig
+ Codec.CBOR.Cuddle.CDDL.Custom.Generator: [geLocal] :: GenEnv -> Map Name (CTree GenPhase)
+ Codec.CBOR.Cuddle.CDDL.Custom.Generator: class HasGenerator a
+ Codec.CBOR.Cuddle.CDDL.Custom.Generator: data CBORGen a
+ Codec.CBOR.Cuddle.CDDL.Custom.Generator: data GenConfig
+ Codec.CBOR.Cuddle.CDDL.Custom.Generator: data GenEnv
+ Codec.CBOR.Cuddle.CDDL.Custom.Generator: data GenPhase
+ Codec.CBOR.Cuddle.CDDL.Custom.Generator: data family XXCTree i
+ Codec.CBOR.Cuddle.CDDL.Custom.Generator: disableTwiddle :: CBORGen a -> CBORGen a
+ Codec.CBOR.Cuddle.CDDL.Custom.Generator: enableTwiddle :: CBORGen a -> CBORGen a
+ Codec.CBOR.Cuddle.CDDL.Custom.Generator: generatorL :: HasGenerator a => Lens' a (Maybe (CBORGen RuleTerm))
+ Codec.CBOR.Cuddle.CDDL.Custom.Generator: instance Codec.CBOR.Cuddle.CDDL.Custom.Core.MonadCddl Codec.CBOR.Cuddle.CDDL.Custom.Generator.CBORGen
+ Codec.CBOR.Cuddle.CDDL.Custom.Generator: instance Control.Monad.Reader.Class.MonadReader Codec.CBOR.Cuddle.CDDL.Custom.Generator.GenEnv Codec.CBOR.Cuddle.CDDL.Custom.Generator.CBORGen
+ Codec.CBOR.Cuddle.CDDL.Custom.Generator: instance GHC.Base.Applicative Codec.CBOR.Cuddle.CDDL.Custom.Generator.CBORGen
+ Codec.CBOR.Cuddle.CDDL.Custom.Generator: instance GHC.Base.Functor Codec.CBOR.Cuddle.CDDL.Custom.Generator.CBORGen
+ Codec.CBOR.Cuddle.CDDL.Custom.Generator: instance GHC.Base.Monad Codec.CBOR.Cuddle.CDDL.Custom.Generator.CBORGen
+ Codec.CBOR.Cuddle.CDDL.Custom.Generator: instance GHC.Generics.Generic Codec.CBOR.Cuddle.CDDL.Custom.Generator.GenConfig
+ Codec.CBOR.Cuddle.CDDL.Custom.Generator: instance GHC.Generics.Generic Codec.CBOR.Cuddle.CDDL.Custom.Generator.GenEnv
+ Codec.CBOR.Cuddle.CDDL.Custom.Generator: instance Test.QuickCheck.GenT.MonadGen Codec.CBOR.Cuddle.CDDL.Custom.Generator.CBORGen
+ Codec.CBOR.Cuddle.CDDL.Custom.Generator: liftAntiGen :: AntiGen a -> CBORGen a
+ Codec.CBOR.Cuddle.CDDL.Custom.Generator: runCBORGen :: GenConfig -> CBORGen a -> AntiGen a
+ Codec.CBOR.Cuddle.CDDL.Custom.Generator: withAntiGen :: (AntiGen a -> AntiGen b) -> CBORGen a -> CBORGen b
+ Codec.CBOR.Cuddle.CDDL.Custom.Generator: withLocalGenBindings :: Map Name (CTree GenPhase) -> CBORGen a -> CBORGen a
+ Codec.CBOR.Cuddle.CDDL.Custom.Validator: CustomValidatorFailure :: Text -> CustomValidatorResult
+ Codec.CBOR.Cuddle.CDDL.Custom.Validator: CustomValidatorSuccess :: CustomValidatorResult
+ Codec.CBOR.Cuddle.CDDL.Custom.Validator: ValidateEnv :: CTreeRoot ValidatorPhase -> Map Name (CTree ValidatorPhase) -> ValidateEnv
+ Codec.CBOR.Cuddle.CDDL.Custom.Validator: [veLocal] :: ValidateEnv -> Map Name (CTree ValidatorPhase)
+ Codec.CBOR.Cuddle.CDDL.Custom.Validator: [veRoot] :: ValidateEnv -> CTreeRoot ValidatorPhase
+ Codec.CBOR.Cuddle.CDDL.Custom.Validator: class HasValidator a
+ Codec.CBOR.Cuddle.CDDL.Custom.Validator: data CustomValidatorResult
+ Codec.CBOR.Cuddle.CDDL.Custom.Validator: data ValidateEnv
+ Codec.CBOR.Cuddle.CDDL.Custom.Validator: data Validator a
+ Codec.CBOR.Cuddle.CDDL.Custom.Validator: data ValidatorPhase
+ Codec.CBOR.Cuddle.CDDL.Custom.Validator: data family XXCTree i
+ Codec.CBOR.Cuddle.CDDL.Custom.Validator: instance Codec.CBOR.Cuddle.CDDL.Custom.Core.MonadCddl Codec.CBOR.Cuddle.CDDL.Custom.Validator.Validator
+ Codec.CBOR.Cuddle.CDDL.Custom.Validator: instance Control.Monad.Fail.MonadFail Codec.CBOR.Cuddle.CDDL.Custom.Validator.Validator
+ Codec.CBOR.Cuddle.CDDL.Custom.Validator: instance Control.Monad.Reader.Class.MonadReader Codec.CBOR.Cuddle.CDDL.Custom.Validator.ValidateEnv Codec.CBOR.Cuddle.CDDL.Custom.Validator.Validator
+ Codec.CBOR.Cuddle.CDDL.Custom.Validator: instance GHC.Base.Applicative Codec.CBOR.Cuddle.CDDL.Custom.Validator.Validator
+ Codec.CBOR.Cuddle.CDDL.Custom.Validator: instance GHC.Base.Functor Codec.CBOR.Cuddle.CDDL.Custom.Validator.Validator
+ Codec.CBOR.Cuddle.CDDL.Custom.Validator: instance GHC.Base.Monad Codec.CBOR.Cuddle.CDDL.Custom.Validator.Validator
+ Codec.CBOR.Cuddle.CDDL.Custom.Validator: instance GHC.Classes.Eq Codec.CBOR.Cuddle.CDDL.Custom.Validator.CustomValidatorResult
+ Codec.CBOR.Cuddle.CDDL.Custom.Validator: instance GHC.Generics.Generic Codec.CBOR.Cuddle.CDDL.Custom.Validator.CustomValidatorResult
+ Codec.CBOR.Cuddle.CDDL.Custom.Validator: instance GHC.Show.Show Codec.CBOR.Cuddle.CDDL.Custom.Validator.CustomValidatorResult
+ Codec.CBOR.Cuddle.CDDL.Custom.Validator: runValidator :: Validator () -> CTreeRoot ValidatorPhase -> CustomValidatorResult
+ Codec.CBOR.Cuddle.CDDL.Custom.Validator: type TermValidator = RuleTerm -> Validator ()
+ Codec.CBOR.Cuddle.CDDL.Custom.Validator: validatorL :: HasValidator a => Lens' a (Maybe TermValidator)
+ Codec.CBOR.Cuddle.CDDL.Custom.Validator: withLocalValidateBindings :: Map Name (CTree ValidatorPhase) -> Validator a -> Validator a
+ Codec.CBOR.Cuddle.CDDL.Resolve: instance Codec.CBOR.Cuddle.IndexMappable.IndexMappable Codec.CBOR.Cuddle.CDDL.CTree.CTree Codec.CBOR.Cuddle.CDDL.Resolve.MonoReferenced Codec.CBOR.Cuddle.CDDL.Custom.Generator.GenPhase
+ Codec.CBOR.Cuddle.CDDL.Resolve: instance Codec.CBOR.Cuddle.IndexMappable.IndexMappable Codec.CBOR.Cuddle.CDDL.CTree.CTree Codec.CBOR.Cuddle.CDDL.Resolve.MonoReferenced Codec.CBOR.Cuddle.CDDL.Custom.Validator.ValidatorPhase
+ Codec.CBOR.Cuddle.CDDL.Resolve: instance Codec.CBOR.Cuddle.IndexMappable.IndexMappable Codec.CBOR.Cuddle.CDDL.CTree.CTreeRoot Codec.CBOR.Cuddle.CDDL.Resolve.MonoReferenced Codec.CBOR.Cuddle.CDDL.Custom.Generator.GenPhase
+ Codec.CBOR.Cuddle.CDDL.Resolve: instance Codec.CBOR.Cuddle.IndexMappable.IndexMappable Codec.CBOR.Cuddle.CDDL.CTree.CTreeRoot Codec.CBOR.Cuddle.CDDL.Resolve.MonoReferenced Codec.CBOR.Cuddle.CDDL.Custom.Validator.ValidatorPhase
+ Codec.CBOR.Cuddle.CDDL.Resolve: instance GHC.Show.Show (Codec.CBOR.Cuddle.CDDL.CTree.XXCTree Codec.CBOR.Cuddle.CDDL.Resolve.DistReferencedNoGen)
+ Codec.CBOR.Cuddle.CDDL.Resolve: instance Prettyprinter.Internal.Pretty (Codec.CBOR.Cuddle.CDDL.CTree.XXCTree Codec.CBOR.Cuddle.CDDL.Resolve.DistReferencedNoGen)
+ Codec.CBOR.Cuddle.CDDL.Resolve: instance Prettyprinter.Internal.Pretty (Codec.CBOR.Cuddle.CDDL.CTree.XXCTree i) => Prettyprinter.Internal.Pretty (Codec.CBOR.Cuddle.CDDL.Resolve.DistRef i)
+ Codec.CBOR.Cuddle.Comments: appendComment :: HasComment a => a -> Comment -> a
+ Codec.CBOR.Cuddle.Comments: commentLine :: Text -> Comment
+ Codec.CBOR.Cuddle.Comments: data Comment
+ Codec.CBOR.Cuddle.Comments: infixl 1 //-
+ Codec.CBOR.Cuddle.Comments: toComment :: Text -> Comment
+ Codec.CBOR.Cuddle.Huddle: instance Codec.CBOR.Cuddle.CDDL.Custom.Generator.HasGenerator (Codec.CBOR.Cuddle.CDDL.XRule Codec.CBOR.Cuddle.Huddle.HuddleStage)
+ Codec.CBOR.Cuddle.Huddle: instance Codec.CBOR.Cuddle.CDDL.Custom.Generator.HasGenerator Codec.CBOR.Cuddle.Huddle.Rule
+ Codec.CBOR.Cuddle.Huddle: instance Codec.CBOR.Cuddle.CDDL.Custom.Validator.HasValidator (Codec.CBOR.Cuddle.CDDL.XRule Codec.CBOR.Cuddle.Huddle.HuddleStage)
+ Codec.CBOR.Cuddle.Huddle: instance Codec.CBOR.Cuddle.CDDL.Custom.Validator.HasValidator Codec.CBOR.Cuddle.Huddle.Rule
+ Codec.CBOR.Cuddle.Huddle: instance Codec.CBOR.Cuddle.Huddle.IsCborable Codec.CBOR.Cuddle.CDDL.GRef
+ Codec.CBOR.Cuddle.Huddle: instance Codec.CBOR.Cuddle.Huddle.IsChoosable Codec.CBOR.Cuddle.CDDL.GRef Codec.CBOR.Cuddle.Huddle.Type2
+ Codec.CBOR.Cuddle.Huddle: instance Codec.CBOR.Cuddle.Huddle.IsComparable Codec.CBOR.Cuddle.CDDL.GRef
+ Codec.CBOR.Cuddle.Huddle: instance Codec.CBOR.Cuddle.Huddle.IsConstrainable Codec.CBOR.Cuddle.CDDL.GRef Codec.CBOR.Cuddle.Huddle.CGRefType
+ Codec.CBOR.Cuddle.Huddle: instance Codec.CBOR.Cuddle.Huddle.IsType0 Codec.CBOR.Cuddle.CDDL.GRef
+ Codec.CBOR.Cuddle.Pretty: instance Prettyprinter.Internal.Pretty (Codec.CBOR.Cuddle.CDDL.CTree.XXCTree p) => Prettyprinter.Internal.Pretty (Codec.CBOR.Cuddle.CDDL.CTree.CTree p)
- Codec.CBOR.Cuddle.CBOR.Validator: validateCBOR :: HasCallStack => ByteString -> Name -> CTreeRoot ValidatorStage -> Evidenced ValidationTrace
+ Codec.CBOR.Cuddle.CBOR.Validator: validateCBOR :: HasCallStack => ByteString -> Name -> CTreeRoot ValidatorPhase -> Evidenced ValidationTrace
- Codec.CBOR.Cuddle.CBOR.Validator.Trace: ControlInfo :: CtlOp -> CTree ValidatorStageSimple -> ControlInfo
+ Codec.CBOR.Cuddle.CBOR.Validator.Trace: ControlInfo :: CtlOp -> CTree ValidatorPhaseSimple -> ControlInfo
- Codec.CBOR.Cuddle.CBOR.Validator.Trace: [ListValidationConsume] :: forall (v :: Validity). CTree ValidatorStageSimple -> ValidationTrace 'IsValid -> ListValidationTrace v -> ListValidationTrace v
+ Codec.CBOR.Cuddle.CBOR.Validator.Trace: [ListValidationConsume] :: forall (v :: Validity). CTree ValidatorPhaseSimple -> ValidationTrace 'IsValid -> ListValidationTrace v -> ListValidationTrace v
- Codec.CBOR.Cuddle.CBOR.Validator.Trace: [ListValidationLeftoverTerms] :: NonEmpty Term -> Maybe (CTree ValidatorStageSimple, ValidationTrace 'IsInvalid) -> ListValidationTrace 'IsInvalid
+ Codec.CBOR.Cuddle.CBOR.Validator.Trace: [ListValidationLeftoverTerms] :: NonEmpty Term -> Maybe (CTree ValidatorPhaseSimple, ValidationTrace 'IsInvalid) -> ListValidationTrace 'IsInvalid
- Codec.CBOR.Cuddle.CBOR.Validator.Trace: [ListValidationMissingRequired] :: CTree ValidatorStageSimple -> ValidationTrace 'IsInvalid -> ListValidationTrace 'IsInvalid
+ Codec.CBOR.Cuddle.CBOR.Validator.Trace: [ListValidationMissingRequired] :: CTree ValidatorPhaseSimple -> ValidationTrace 'IsInvalid -> ListValidationTrace 'IsInvalid
- Codec.CBOR.Cuddle.CBOR.Validator.Trace: [ListValidationUnappliedRule] :: CTree ValidatorStageSimple -> ListValidationTrace 'IsInvalid
+ Codec.CBOR.Cuddle.CBOR.Validator.Trace: [ListValidationUnappliedRule] :: CTree ValidatorPhaseSimple -> ListValidationTrace 'IsInvalid
- Codec.CBOR.Cuddle.CBOR.Validator.Trace: [MapValidationConsume] :: forall (v :: Validity). CTree ValidatorStageSimple -> ValidationTrace 'IsValid -> ValidationTrace 'IsValid -> MapValidationTrace v -> MapValidationTrace v
+ Codec.CBOR.Cuddle.CBOR.Validator.Trace: [MapValidationConsume] :: forall (v :: Validity). CTree ValidatorPhaseSimple -> ValidationTrace 'IsValid -> ValidationTrace 'IsValid -> MapValidationTrace v -> MapValidationTrace v
- Codec.CBOR.Cuddle.CBOR.Validator.Trace: [MapValidationInvalidValue] :: CTree ValidatorStageSimple -> ValidationTrace 'IsValid -> ValidationTrace 'IsInvalid -> MapValidationTrace 'IsInvalid
+ Codec.CBOR.Cuddle.CBOR.Validator.Trace: [MapValidationInvalidValue] :: CTree ValidatorPhaseSimple -> ValidationTrace 'IsValid -> ValidationTrace 'IsInvalid -> MapValidationTrace 'IsInvalid
- Codec.CBOR.Cuddle.CBOR.Validator.Trace: [MapValidationLeftoverKVs] :: (Term, Term) -> Maybe (CTree ValidatorStageSimple, MapValidationTrace 'IsInvalid) -> MapValidationTrace 'IsInvalid
+ Codec.CBOR.Cuddle.CBOR.Validator.Trace: [MapValidationLeftoverKVs] :: (Term, Term) -> Maybe (CTree ValidatorPhaseSimple, MapValidationTrace 'IsInvalid) -> MapValidationTrace 'IsInvalid
- Codec.CBOR.Cuddle.CBOR.Validator.Trace: [MapValidationUnappliedRules] :: NonEmpty (CTree ValidatorStageSimple) -> MapValidationTrace 'IsInvalid
+ Codec.CBOR.Cuddle.CBOR.Validator.Trace: [MapValidationUnappliedRules] :: NonEmpty (CTree ValidatorPhaseSimple) -> MapValidationTrace 'IsInvalid
- Codec.CBOR.Cuddle.CBOR.Validator.Trace: [TerminalRule] :: CTree ValidatorStageSimple -> ValidationTrace 'IsValid
+ Codec.CBOR.Cuddle.CBOR.Validator.Trace: [TerminalRule] :: CTree ValidatorPhaseSimple -> ValidationTrace 'IsValid
- Codec.CBOR.Cuddle.CBOR.Validator.Trace: [UnapplicableRule] :: CTree ValidatorStageSimple -> ValidationTrace 'IsInvalid
+ Codec.CBOR.Cuddle.CBOR.Validator.Trace: [UnapplicableRule] :: CTree ValidatorPhaseSimple -> ValidationTrace 'IsInvalid
- Codec.CBOR.Cuddle.CBOR.Validator.Trace: [UnsatisfiedControl] :: CtlOp -> CTree ValidatorStageSimple -> ValidationTrace 'IsInvalid
+ Codec.CBOR.Cuddle.CBOR.Validator.Trace: [UnsatisfiedControl] :: CtlOp -> CTree ValidatorPhaseSimple -> ValidationTrace 'IsInvalid
- Codec.CBOR.Cuddle.CBOR.Validator.Trace: [ciRule] :: ControlInfo -> CTree ValidatorStageSimple
+ Codec.CBOR.Cuddle.CBOR.Validator.Trace: [ciRule] :: ControlInfo -> CTree ValidatorPhaseSimple
- Codec.CBOR.Cuddle.CBOR.Validator.Trace: showSimple :: (IndexMappable a ValidatorStage ValidatorStageSimple, Show (a ValidatorStageSimple)) => a ValidatorStage -> String
+ Codec.CBOR.Cuddle.CBOR.Validator.Trace: showSimple :: (IndexMappable a ValidatorPhase ValidatorPhaseSimple, Show (a ValidatorPhaseSimple)) => a ValidatorPhase -> String
- Codec.CBOR.Cuddle.Huddle: withCBORGen :: HasGenerator a => CBORGen WrappedTerm -> a -> a
+ Codec.CBOR.Cuddle.Huddle: withCBORGen :: HasGenerator a => CBORGen RuleTerm -> a -> a
- Codec.CBOR.Cuddle.Huddle: withValidator :: HasValidator a => (Term -> CustomValidatorResult) -> a -> a
+ Codec.CBOR.Cuddle.Huddle: withValidator :: HasValidator a => TermValidator -> a -> a
Files
- CHANGELOG.md +29/−0
- bin/Main.hs +48/−22
- cuddle.cabal +4/−2
- golden/pretty/rule_comment_appends_to_existing.txt +3/−0
- golden/pretty/rule_comment_chained.txt +3/−0
- golden/pretty/rule_comment_empty.txt +1/−0
- golden/pretty/rule_comment_multi_rule.txt +8/−0
- golden/pretty/rule_comment_multiline.txt +3/−0
- golden/pretty/rule_comment_rule.txt +2/−0
- golden/pretty/term_comment_appends_to_existing.txt +3/−0
- golden/pretty/term_comment_array_entries.txt +5/−0
- golden/pretty/term_comment_chained.txt +3/−0
- golden/pretty/term_comment_empty.txt +1/−0
- golden/pretty/term_comment_multiline.txt +3/−0
- golden/pretty/term_comment_rule.txt +2/−0
- src/Codec/CBOR/Cuddle/CBOR/Gen.hs +75/−64
- src/Codec/CBOR/Cuddle/CBOR/Validator.hs +123/−80
- src/Codec/CBOR/Cuddle/CBOR/Validator/Trace.hs +29/−74
- src/Codec/CBOR/Cuddle/CDDL.hs +5/−0
- src/Codec/CBOR/Cuddle/CDDL/CBORGenerator.hs +0/−92
- src/Codec/CBOR/Cuddle/CDDL/CTreePhase.hs +5/−2
- src/Codec/CBOR/Cuddle/CDDL/Custom/Core.hs +25/−0
- src/Codec/CBOR/Cuddle/CDDL/Custom/Generator.hs +103/−0
- src/Codec/CBOR/Cuddle/CDDL/Custom/Validator.hs +76/−0
- src/Codec/CBOR/Cuddle/CDDL/Resolve.hs +57/−24
- src/Codec/CBOR/Cuddle/Comments.hs +26/−9
- src/Codec/CBOR/Cuddle/Huddle.hs +18/−42
- src/Codec/CBOR/Cuddle/IndexMappable.hs +2/−2
- src/Codec/CBOR/Cuddle/Parser.hs +6/−3
- src/Codec/CBOR/Cuddle/Parser/Lexer.hs +2/−2
- src/Codec/CBOR/Cuddle/Pretty.hs +30/−4
- test/Test/Codec/CBOR/Cuddle/CDDL/Examples/Huddle.hs +44/−3
- test/Test/Codec/CBOR/Cuddle/CDDL/Gen.hs +2/−2
- test/Test/Codec/CBOR/Cuddle/CDDL/GeneratorSpec.hs +32/−16
- test/Test/Codec/CBOR/Cuddle/CDDL/Pretty/Golden.hs +77/−9
- test/Test/Codec/CBOR/Cuddle/CDDL/Validator.hs +16/−14
CHANGELOG.md view
@@ -1,5 +1,34 @@ # Changelog for `cuddle` +## 1.7.0.0++* Rename `WrappedTerm` to `RuleTerm`+* Rename `RuleTerm` constructors:+ * `S` -> `SingleTerm`+ * `G` -> `GroupTerm`+ * `P` -> `PairTerm`+* Split `Codec.CBOR.Cuddle.CDDL.CBORGenerator` into:+ * `Codec.CBOR.Cuddle.CDDL.Custom.Generator`+ * `Codec.CBOR.Cuddle.CDDL.Custom.Validator`+ * `Codec.CBOR.Cuddle.CDDL.Custom.Core`+* Fix `--no-twiddle` argument+* Add autocompletion hints+* Add footer, improve output format failure message+* Make `(//-)` prefix each comment line with a leading space and change its fixity from `infixr 0` to `infixl 1`+* Hide the `Comment` constructor; use `toComment` or `commentLine` smart constructors instead+* Add `appendComment` for raw comment concatenation in parser combinators+* Export `GRef` constructor+* Custom generators and validators on generic rules can now refer to their+ generic argument: looking up a `GRef` resolves to the type bound at the+ enclosing rule+* Add `generateFromGRef`+* Add `validateFromName` and `validateFromGRef`+* Move `GRef` to `Codec.CBOR.Cuddle.CDDL`+* Add `MonadCddl`+* `runCBORValidator` now takes `CTreeRoot ValidatorPhase` instead of `ValidateEnv`+* Split `GenEnv` into a user-supplied `GenConfig` and a runtime `GenEnv`. `runCBORGen` now takes a `GenConfig`.+* Rename `ValidatorStage` to `ValidatorPhase`+ ## 1.6.0.0 * Remove `example` executable
bin/Main.hs view
@@ -15,8 +15,8 @@ prettyValidationTrace, ) import Codec.CBOR.Cuddle.CDDL (CDDL, Name (..), fromRules, sortCDDL)-import Codec.CBOR.Cuddle.CDDL.CBORGenerator (GenEnv (..), runCBORGen) import Codec.CBOR.Cuddle.CDDL.CTree (CTreeRoot)+import Codec.CBOR.Cuddle.CDDL.Custom.Generator (GenConfig (..), runCBORGen) import Codec.CBOR.Cuddle.CDDL.Postlude (appendPostlude) import Codec.CBOR.Cuddle.CDDL.Resolve ( fullResolveCDDL,@@ -50,6 +50,7 @@ PageWidth (..), defaultLayoutOptions, layoutPretty,+ vsep, ) import Prettyprinter.Render.Terminal qualified as Ansi import System.Exit (exitFailure, exitSuccess)@@ -102,7 +103,12 @@ pCBOROutputFormat = eitherReader $ \k -> case Map.lookup k outputFormatOptions of Just x -> Right x- Nothing -> Left k+ Nothing ->+ Left $+ unlines+ [ "invalid value: " <> k+ , "expecting one of: " <> unwords (Map.keys outputFormatOptions)+ ] data GenOpts = GenOpts { outputFormat :: CBOROutputFormat@@ -131,6 +137,7 @@ ( long "out-file" <> short 'o' <> help "Write to"+ <> action "file" ) ) <*> switch@@ -152,13 +159,14 @@ <*> switch ( long "negative" <> short 'n'- <> help "Generate a negative example"- )- <*> option- (not <$> auto)- ( long "no-twiddle"- <> help "Do not generate indefinite encodings"+ <> help "Generate a negative (zapped) example" )+ <*> ( not+ <$> switch+ ( long "no-twiddle"+ <> help "Do not generate indefinite encodings"+ )+ ) <*> argument str (metavar "RULE" <> help "Name of the CDDL rule to generate a CBOR term for")@@ -212,7 +220,7 @@ ( metavar "RULE" <> help "Name of the CDDL rule to validate this file with" )- <*> argument str (metavar "CBOR_FILE")+ <*> argument str (metavar "CBOR_FILE" <> action "file") data CBORInputFormat = FromHex@@ -234,7 +242,12 @@ pCBORInputFormat :: ReadM CBORInputFormat pCBORInputFormat = eitherReader $ \k -> case Map.lookup k inputFormatOptions of Just x -> Right x- Nothing -> Left k+ Nothing ->+ Left $+ unlines+ [ "invalid value: " <> k+ , "expecting one of: " <> unwords (Map.keys inputFormatOptions)+ ] pFormatCBOROpts :: Parser FormatCBOROpts pFormatCBOROpts =@@ -258,6 +271,7 @@ ( long "out-file" <> short 'o' <> help "Write to"+ <> action "file" ) ) @@ -267,31 +281,34 @@ ( command "format" ( info- (Format <$> pFormatOpts <*> argument str (metavar "CDDL_FILE") <**> helper)+ (Format <$> pFormatOpts <*> argument str (metavar "CDDL_FILE" <> action "file") <**> helper) (progDesc "Format the provided CDDL file") ) <> command "validate" ( info- (Validate <$> pValidateOpts <*> argument str (metavar "CDDL_FILE") <**> helper)+ (Validate <$> pValidateOpts <*> argument str (metavar "CDDL_FILE" <> action "file") <**> helper) (progDesc "Validate the provided CDDL file") ) <> command "gen" ( info- (GenerateCBOR <$> pGenOpts <*> argument str (metavar "CDDL_FILE") <**> helper)+ (GenerateCBOR <$> pGenOpts <*> argument str (metavar "CDDL_FILE" <> action "file") <**> helper) (progDesc "Generate a CBOR term matching the schema") ) <> command "validate-cbor" ( info- (ValidateCBOR <$> pValidateCBOROpts <*> argument str (metavar "CDDL_FILE") <**> helper)+ ( ValidateCBOR+ <$> pValidateCBOROpts+ <*> argument str (metavar "CDDL_FILE" <> action "file") <**> helper+ ) (progDesc "Validate a CBOR file against a schema") ) <> command "format-cbor" ( info- (FormatCBOR <$> pFormatCBOROpts <*> argument str (metavar "CBOR_FILE") <**> helper)+ (FormatCBOR <$> pFormatCBOROpts <*> argument str (metavar "CBOR_FILE" <> action "file") <**> helper) (progDesc "Output a CBOR binary in diagnostic formatting") ) )@@ -304,7 +321,16 @@ (pCommand <**> helper <**> simpleVersioner (showVersion version)) ( fullDesc <> progDesc "Manipulate CDDL files"- <> header "cuddle"+ <> header "cuddle - a CDDL tool for validating, formatting, and generating CBOR"+ <> footerDoc+ ( Just $+ vsep+ [ "To enable shell completions, add the appropriate line to your shell config:"+ , " Bash: source <(cuddle --bash-completion-script cuddle)"+ , " Zsh: source <(cuddle --zsh-completion-script cuddle)"+ , " Fish: cuddle --fish-completion-script cuddle | source"+ ]+ ) ) run options @@ -372,12 +398,12 @@ zapN | goNegative = 1 | otherwise = 0- env =- GenEnv- { geRoot = mapIndex mt- , geTwiddle = goTwiddle+ cfg =+ GenConfig+ { gcRoot = mapIndex mt+ , gcTwiddle = goTwiddle }- term = runGen seed goSize . zapAntiGen zapN . runCBORGen env $ generateFromName (Name itemName)+ term = runGen seed goSize . zapAntiGen zapN . runCBORGen cfg $ generateFromName (Name itemName) formatted = formatTerm term outputFormat case outputTo of Just outputPath -> BS.writeFile outputPath formatted@@ -417,7 +443,7 @@ IO (Either (ParseErrorBundle T.Text e) a) parseFromFile p file = runParser p file <$> T.readFile file -runValidateCBOR :: BS.ByteString -> Name -> CTreeRoot ValidatorStage -> TraceOptions -> IO ()+runValidateCBOR :: BS.ByteString -> Name -> CTreeRoot ValidatorPhase -> TraceOptions -> IO () runValidateCBOR bs rule cddl traceOpts = case validateCBOR bs rule cddl of Evidenced validity trc -> do
cuddle.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.4 name: cuddle-version: 1.6.0.0+version: 1.7.0.0 synopsis: CDDL Generator and test utilities description: Cuddle is a library for generating and manipulating [CDDL](https://datatracker.ietf.org/doc/html/rfc8610).@@ -42,10 +42,12 @@ Codec.CBOR.Cuddle.CBOR.Validator Codec.CBOR.Cuddle.CBOR.Validator.Trace Codec.CBOR.Cuddle.CDDL- Codec.CBOR.Cuddle.CDDL.CBORGenerator Codec.CBOR.Cuddle.CDDL.CTree Codec.CBOR.Cuddle.CDDL.CTreePhase Codec.CBOR.Cuddle.CDDL.CtlOp+ Codec.CBOR.Cuddle.CDDL.Custom.Core+ Codec.CBOR.Cuddle.CDDL.Custom.Generator+ Codec.CBOR.Cuddle.CDDL.Custom.Validator Codec.CBOR.Cuddle.CDDL.Postlude Codec.CBOR.Cuddle.CDDL.Resolve Codec.CBOR.Cuddle.Comments
+ golden/pretty/rule_comment_appends_to_existing.txt view
@@ -0,0 +1,3 @@+;existing+; trailing+a = true
+ golden/pretty/rule_comment_chained.txt view
@@ -0,0 +1,3 @@+; first+; second+a = true
+ golden/pretty/rule_comment_empty.txt view
@@ -0,0 +1,1 @@+a = true
+ golden/pretty/rule_comment_multi_rule.txt view
@@ -0,0 +1,8 @@+; the listening port+port = uint++; the host name+host = text++; TLS only+secure = true
+ golden/pretty/rule_comment_multiline.txt view
@@ -0,0 +1,3 @@+; line one+; line two+a = true
+ golden/pretty/rule_comment_rule.txt view
@@ -0,0 +1,2 @@+; trailing+a = true
+ golden/pretty/term_comment_appends_to_existing.txt view
@@ -0,0 +1,3 @@+;existing+a =+ true ; trailing
+ golden/pretty/term_comment_array_entries.txt view
@@ -0,0 +1,5 @@+triple =+ [ uint ; first element+ , text ; second element+ , true ; third element+ ]
+ golden/pretty/term_comment_chained.txt view
@@ -0,0 +1,3 @@+a =+ true ; first+ ; second
+ golden/pretty/term_comment_empty.txt view
@@ -0,0 +1,1 @@+a = true
+ golden/pretty/term_comment_multiline.txt view
@@ -0,0 +1,3 @@+a =+ true ; line one+ ; line two
+ golden/pretty/term_comment_rule.txt view
@@ -0,0 +1,2 @@+a =+ true ; trailing
src/Codec/CBOR/Cuddle/CBOR/Gen.hs view
@@ -16,6 +16,7 @@ -- | Generate example CBOR given a CDDL specification module Codec.CBOR.Cuddle.CBOR.Gen ( generateFromName,+ generateFromGRef, GenPhase, GenSimple, XXCTree (..),@@ -24,23 +25,13 @@ #if MIN_VERSION_random(1,3,0) #endif import Codec.CBOR.Cuddle.CDDL (+ GRef (..), Name (..), OccurrenceIndicator (..), RangeBound (..), Value (..), ValueVariant (..), )-import Codec.CBOR.Cuddle.CDDL.CBORGenerator (- CBORGen (..),- GenEnv (..),- GenPhase,- WrappedTerm (..),- XXCTree (..),- liftAntiGen,- lookupCddl,- withAntiGen,- withTwiddle,- ) import Codec.CBOR.Cuddle.CDDL.CTree ( CTree (..), PTerm (..),@@ -50,6 +41,16 @@ ) import Codec.CBOR.Cuddle.CDDL.CTree qualified as CTree import Codec.CBOR.Cuddle.CDDL.CtlOp qualified as CtlOp+import Codec.CBOR.Cuddle.CDDL.Custom.Core (MonadCddl (..), RuleTerm (..))+import Codec.CBOR.Cuddle.CDDL.Custom.Generator (+ CBORGen,+ GenConfig (..),+ GenEnv (..),+ GenPhase,+ disableTwiddle,+ liftAntiGen,+ withAntiGen,+ ) import Codec.CBOR.Cuddle.CDDL.Resolve (XXCTree (..)) import Codec.CBOR.Cuddle.IndexMappable (IndexMappable (..)) import Codec.CBOR.Term (Term (..))@@ -160,28 +161,28 @@ twiddleString :: Text -> CBORGen Term twiddleString t = do- twiddle <- asks geTwiddle+ twiddle <- asks (gcTwiddle . geConfig) if twiddle then ($ t) <$> elements [TString, TStringI . TL.fromStrict] else pure $ TString t twiddleList :: [Term] -> CBORGen Term twiddleList t = do- twiddle <- asks geTwiddle+ twiddle <- asks (gcTwiddle . geConfig) if twiddle then ($ t) <$> elements [TList, TListI] else pure $ TList t twiddleBytes :: ByteString -> CBORGen Term twiddleBytes t = do- twiddle <- asks geTwiddle+ twiddle <- asks (gcTwiddle . geConfig) if twiddle then ($ t) <$> elements [TBytes, TBytesI . LBS.fromStrict] else pure $ TBytes t twiddleMap :: [(Term, Term)] -> CBORGen Term twiddleMap t = do- twiddle <- asks geTwiddle+ twiddle <- asks (gcTwiddle . geConfig) if twiddle then ($ t) <$> elements [TMap, TMapI] else pure $ TMap t@@ -284,18 +285,18 @@ -- | Recursively flatten wrapped list. That is, expand any groups out to their -- individual entries.-flattenWrappedList :: [WrappedTerm] -> [WrappedTerm]+flattenWrappedList :: [RuleTerm] -> [RuleTerm] flattenWrappedList [] = []-flattenWrappedList (G xxs : xs) =+flattenWrappedList (GroupTerm xxs : xs) = flattenWrappedList xxs <> flattenWrappedList xs flattenWrappedList (y : xs) = y : flattenWrappedList xs -- | Convert a list of wrapped terms to a list of terms. If any 'PairTerm's are -- present, we just take their "value" part.-singleTermList :: [WrappedTerm] -> Maybe [Term]+singleTermList :: [RuleTerm] -> Maybe [Term] singleTermList [] = Just []-singleTermList (S x : xs) = (x :) <$> singleTermList xs-singleTermList (P _ y : xs) = (y :) <$> singleTermList xs+singleTermList (SingleTerm x : xs) = (x :) <$> singleTermList xs+singleTermList (PairTerm _ y : xs) = (y :) <$> singleTermList xs singleTermList _ = Nothing showSimple :: CTree GenPhase -> String@@ -309,11 +310,11 @@ -- Generator functions -------------------------------------------------------------------------------- -genSized :: HasCallStack => Word64 -> CTree GenPhase -> CBORGen WrappedTerm+genSized :: HasCallStack => Word64 -> CTree GenPhase -> CBORGen RuleTerm genSized s target = annotateTerm target $ case target of- CTree.Postlude PTText -> fmap S . twiddleString =<< genNBytesText (fromIntegral s)- CTree.Postlude PTBytes -> fmap S . twiddleBytes =<< genNBytes (fromIntegral s)- CTree.Postlude PTUInt -> S . TInteger <$> choose (0, 256 ^ s - 1)+ CTree.Postlude PTText -> fmap SingleTerm . twiddleString =<< genNBytesText (fromIntegral s)+ CTree.Postlude PTBytes -> fmap SingleTerm . twiddleBytes =<< genNBytes (fromIntegral s)+ CTree.Postlude PTUInt -> SingleTerm . TInteger <$> choose (0, 256 ^ s - 1) _ -> error "Cannot apply size operator to target " range :: Enum a => RangeBound -> a -> a -> (a, a)@@ -351,16 +352,16 @@ CTree.CTreeE (GenRef n) -> annotate (unName n) CTree.CTreeE (GenGenerator _ _) -> annotate "custom_generator" -genForCTree :: HasCallStack => CTree GenPhase -> CBORGen WrappedTerm+genForCTree :: HasCallStack => CTree GenPhase -> CBORGen RuleTerm genForCTree node = annotateTerm node $ case node of- CTree.Literal v -> S <$> valueToTerm v- CTree.Postlude pt -> S <$> genPostlude pt+ CTree.Literal v -> SingleTerm <$> valueToTerm v+ CTree.Postlude pt -> SingleTerm <$> genPostlude pt CTree.Map nodes -> genMap nodes CTree.Array nodes -> genArray nodes CTree.Choice (NE.toList -> nodes) -> do ix <- choose (0, length nodes - 1) genForCTree $ nodes !! ix- CTree.Group nodes -> G <$> traverse genForCTree nodes+ CTree.Group nodes -> GroupTerm <$> traverse genForCTree nodes CTree.KV key value _cut -> genKV key value CTree.Occur item occurs -> applyOccurenceIndicator occurs (genForCTree item)@@ -374,7 +375,7 @@ -- | Generate a map from a list of nodes genMap ::- HasCallStack => [CTree GenPhase] -> CBORGen WrappedTerm+ HasCallStack => [CTree GenPhase] -> CBORGen RuleTerm genMap nodes = do let elemsNeeded KV {} = 1@@ -386,7 +387,7 @@ Int -> Map.Map Term a -> CTree GenPhase -> CTree GenPhase -> CBORGen (Maybe (Term, Term)) tryGenKV nTries m kNode vNode = go nTries where- unS (S x) = x+ unS (SingleTerm x) = x unS x = error $ "Expected single, got " <> show x go !n | n > 0 = do@@ -446,11 +447,11 @@ node -> error $ "Unexpected node: " <> showSimple node mItems <- genNodes 0 Map.empty $ sortOn (Down . elemsNeeded) nodes case mItems of- Just items -> S <$> twiddleMap (Map.toList items)+ Just items -> SingleTerm <$> twiddleMap (Map.toList items) Nothing -> error "Failed to generate unique keys for map after max retries" -- | Generate an array from a list of nodes-genArray :: HasCallStack => [CTree GenPhase] -> CBORGen WrappedTerm+genArray :: HasCallStack => [CTree GenPhase] -> CBORGen RuleTerm genArray nodes = do items <- singleTermList . flattenWrappedList@@ -459,16 +460,16 @@ [0 :: Int ..] nodes case items of- Just ts -> S <$> twiddleList ts+ Just ts -> SingleTerm <$> twiddleList ts Nothing -> error "Something weird happened which shouldn't be possible" -- | Generate a key-value pair-genKV :: HasCallStack => CTree GenPhase -> CTree GenPhase -> CBORGen WrappedTerm+genKV :: HasCallStack => CTree GenPhase -> CTree GenPhase -> CBORGen RuleTerm genKV key value = do kg <- withAntiGen (withAnnotation "key") $ genForCTree key vg <- withAntiGen (withAnnotation "value") $ genForCTree value case (kg, vg) of- (S k, S v) -> pure $ P k v+ (SingleTerm k, SingleTerm v) -> pure $ PairTerm k v _ -> error $ "Non single-term generated outside of group context: "@@ -482,24 +483,24 @@ CTree GenPhase -> CTree GenPhase -> RangeBound ->- CBORGen WrappedTerm+ CBORGen RuleTerm genRange from to bounds = do term1 <- withAntiGen dropNegativeGen $ genForCTree from term2 <- withAntiGen dropNegativeGen $ genForCTree to case (term1, term2) of- (S (TInt a), S (TInt b))- | a <= b -> genBetween (range bounds a b) <&> S . TInt- (S (TInt a), S (TInteger b))+ (SingleTerm (TInt a), SingleTerm (TInt b))+ | a <= b -> genBetween (range bounds a b) <&> SingleTerm . TInt+ (SingleTerm (TInt a), SingleTerm (TInteger b)) | fromIntegral a <= b ->- genBetween (range bounds (fromIntegral a) b) <&> S . TInteger- (S (TInteger a), S (TInteger b))- | a <= b -> genBetween (range bounds a b) <&> S . TInteger- (S (THalf a), S (THalf b))- | a <= b -> choose (range bounds a b) <&> S . THalf- (S (TFloat a), S (TFloat b))- | a <= b -> choose (range bounds a b) <&> S . TFloat- (S (TDouble a), S (TDouble b))- | a <= b -> choose (range bounds a b) <&> S . TDouble+ genBetween (range bounds (fromIntegral a) b) <&> SingleTerm . TInteger+ (SingleTerm (TInteger a), SingleTerm (TInteger b))+ | a <= b -> genBetween (range bounds a b) <&> SingleTerm . TInteger+ (SingleTerm (THalf a), SingleTerm (THalf b))+ | a <= b -> choose (range bounds a b) <&> SingleTerm . THalf+ (SingleTerm (TFloat a), SingleTerm (TFloat b))+ | a <= b -> choose (range bounds a b) <&> SingleTerm . TFloat+ (SingleTerm (TDouble a), SingleTerm (TDouble b))+ | a <= b -> choose (range bounds a b) <&> SingleTerm . TDouble (a, b) -> error $ "invalid range (a = " <> show a <> ", b = " <> show b <> ")" -- | Generate a value with a control operator applied@@ -508,18 +509,18 @@ CtlOp.CtlOp -> CTree GenPhase -> CTree GenPhase ->- CBORGen WrappedTerm+ CBORGen RuleTerm genControl op target controller = annotateTerm target $ do resolvedController <- case controller of CTreeE (GenRef n) -> withAntiGen dropNegativeGen $ resolveRef n x -> pure x case (op, resolvedController) of (CtlOp.Le, CTree.Literal (Value (VUInt n) _)) -> case target of- CTree.Postlude PTUInt -> S . TInteger <$> choose (0, fromIntegral n)+ CTree.Postlude PTUInt -> SingleTerm . TInteger <$> choose (0, fromIntegral n) _ -> error "Cannot apply le operator to target" (CtlOp.Le, _) -> error $ "Invalid controller for .le operator: " <> showSimple controller (CtlOp.Lt, CTree.Literal (Value (VUInt n) _)) -> case target of- CTree.Postlude PTUInt -> S . TInteger <$> choose (0, fromIntegral n - 1)+ CTree.Postlude PTUInt -> SingleTerm . TInteger <$> choose (0, fromIntegral n - 1) _ -> error "Cannot apply lt operator to target" (CtlOp.Lt, _) -> error $ "Invalid controller for .lt operator: " <> showSimple controller (CtlOp.Size, CTree.Literal (Value (VUInt s) _)) -> do@@ -544,12 +545,12 @@ (CtlOp.Cbor, _) -> do enc <- genForCTree controller case enc of- S x -> fmap S . twiddleBytes $ CBOR.toStrictByteString (CBOR.encodeTerm x)+ SingleTerm x -> fmap SingleTerm . twiddleBytes $ CBOR.toStrictByteString (CBOR.encodeTerm x) _ -> error "Controller does not correspond to a single term" (c, _) -> error $ "Controller not yet implemented: " <> show c -- | Generate a value from an enum-genEnum :: HasCallStack => CTree GenPhase -> CBORGen WrappedTerm+genEnum :: HasCallStack => CTree GenPhase -> CBORGen RuleTerm genEnum tree = case tree of CTree.Group trees -> do ix <- choose (0, length trees - 1)@@ -557,7 +558,7 @@ _ -> error "Attempt to form an enum from something other than a group" -- | Generate a tagged value-genTag :: HasCallStack => Word64 -> CTree GenPhase -> CBORGen WrappedTerm+genTag :: HasCallStack => Word64 -> CTree GenPhase -> CBORGen RuleTerm genTag t node = do omitTag <- liftAntiGen $ faultyBool False if omitTag@@ -568,13 +569,13 @@ n | n == 2 || n == 3 -> -- TODO remove this once `cborg` can decode indefinite bytes in bignums- withTwiddle False $ genForCTree node+ disableTwiddle $ genForCTree node _ -> genForCTree node case enc of- S x -> pure $ S $ TTagged tag x+ SingleTerm x -> pure $ SingleTerm $ TTagged tag x _ -> error "Tag controller does not correspond to a single term" -genForNode :: HasCallStack => Name -> CBORGen WrappedTerm+genForNode :: HasCallStack => Name -> CBORGen RuleTerm genForNode = genForCTree <=< resolveRef -- | Take a reference and resolve it to the relevant Tree, following multiple@@ -603,13 +604,23 @@ Nothing -> error $ "Unbound reference: " <> show n Just val -> genForCTree val >>= \case- S x -> pure x+ SingleTerm x -> pure x _ -> error $ "Tried to generate a top-level term for " <> show n <> ", but it does not correspond to a single term." +-- | Generate a 'RuleTerm' for the type bound to the given generic+-- parameter at the enclosing rule. Use this from inside a custom generator+-- attached to a generic rule.+generateFromGRef :: HasCallStack => GRef -> CBORGen RuleTerm+generateFromGRef ref = do+ mRule <- lookupGRef ref+ case mRule of+ Nothing -> error $ "Unbound generic reference: " <> show ref+ Just val -> genForCTree val+ sizeBiasedBool :: MonadGen m => m Bool sizeBiasedBool = sized $ \sz -> (> 1) <$> choose (0, sz) @@ -626,23 +637,23 @@ -- | Apply an occurence indicator to a group entry applyOccurenceIndicator :: OccurrenceIndicator ->- CBORGen WrappedTerm ->- CBORGen WrappedTerm+ CBORGen RuleTerm ->+ CBORGen RuleTerm applyOccurenceIndicator OIOptional oldGen = sizeBiasedBool >>= \case- False -> pure $ G mempty+ False -> pure $ GroupTerm mempty True -> oldGen applyOccurenceIndicator OIZeroOrMore oldGen =- G <$> listOfScaled oldGen+ GroupTerm <$> listOfScaled oldGen applyOccurenceIndicator OIOneOrMore oldGen =- withAntiGen (\g -> G <$> listOfScaled1 g) oldGen+ withAntiGen (fmap GroupTerm . listOfScaled1) oldGen applyOccurenceIndicator (OIBounded mlb mub) oldGen = sized $ \sz -> do let lb = fromMaybe 0 mlb ub = fromMaybe (lb + fromIntegral sz) mub i <- fromIntegral <$> genBetween (lb, ub)- G <$> vectorOf i (scale (`div` (i + 1)) oldGen)+ GroupTerm <$> vectorOf i (scale (`div` (i + 1)) oldGen) valueToTerm :: Value -> CBORGen Term valueToTerm (Value x _) = valueVariantToTerm x
src/Codec/CBOR/Cuddle/CBOR/Validator.hs view
@@ -5,7 +5,9 @@ module Codec.CBOR.Cuddle.CBOR.Validator ( validateCBOR,- ValidatorStage,+ validateFromName,+ validateFromGRef,+ ValidatorPhase, ) where import Codec.CBOR.Cuddle.CBOR.Validator.Trace (@@ -16,7 +18,6 @@ MapValidationTrace (..), SValidity (..), ValidationTrace (..),- ValidatorStage, XXCTree (..), evidence, isValid,@@ -24,12 +25,21 @@ showSimple, ) import Codec.CBOR.Cuddle.CDDL hiding (CDDL, Group, Rule)-import Codec.CBOR.Cuddle.CDDL.CBORGenerator (CBORValidator (..), CustomValidatorResult (..)) import Codec.CBOR.Cuddle.CDDL.CTree import Codec.CBOR.Cuddle.CDDL.CtlOp+import Codec.CBOR.Cuddle.CDDL.Custom.Core (MonadCddl (..), RuleTerm (..))+import Codec.CBOR.Cuddle.CDDL.Custom.Validator (+ CustomValidatorResult (..),+ TermValidator,+ ValidateEnv (..),+ Validator,+ ValidatorPhase,+ runValidator,+ ) import Codec.CBOR.Cuddle.IndexMappable (IndexMappable (..)) import Codec.CBOR.Read import Codec.CBOR.Term+import Control.Monad.Reader (asks) import Data.Bifunctor (Bifunctor (..)) import Data.Bits hiding (And) import Data.ByteString qualified as BS@@ -56,7 +66,7 @@ HasCallStack => BS.ByteString -> Name ->- CTreeRoot ValidatorStage ->+ CTreeRoot ValidatorPhase -> Evidenced ValidationTrace validateCBOR bs rule cddl@(CTreeRoot tree) = case deserialiseFromBytes decodeTerm (BSL.fromStrict bs) of@@ -65,21 +75,50 @@ | BSL.null rest -> validateTerm cddl term (tree Map.! rule) | otherwise -> error $ "Leftover bytes in CBOR: " <> show rest +-- | Validate a CBOR 'Term' against a top-level rule from inside a custom+-- validator.+validateFromName ::+ HasCallStack => Name -> Term -> Validator ()+validateFromName n term = do+ mRule <- lookupCddl n+ case mRule of+ Nothing -> fail $ "Unbound name: " <> show n+ Just rule -> validateAgainst term rule++-- | Validate a CBOR 'Term' against the type bound to the given generic+-- parameter at the enclosing rule. Use this from inside a custom validator+-- attached to a generic rule.+validateFromGRef ::+ HasCallStack => GRef -> Term -> Validator ()+validateFromGRef ref term = do+ mRule <- lookupGRef ref+ case mRule of+ Nothing -> fail $ "Unbound generic reference: " <> show ref+ Just rule -> validateAgainst term rule++validateAgainst :: Term -> CTree ValidatorPhase -> Validator ()+validateAgainst term rule = do+ cddl <- asks veRoot+ let res = validateTerm cddl term rule+ if isValid res+ then pure ()+ else fail $ "Validation failed for term: " <> show term+ -------------------------------------------------------------------------------- -- Terms -- | Core function that validates a CBOR term to a particular rule of the CDDL -- spec validateTerm ::- CTreeRoot ValidatorStage ->+ CTreeRoot ValidatorPhase -> Term ->- CTree ValidatorStage ->+ CTree ValidatorPhase -> Evidenced ValidationTrace validateTerm cddl term rule | CTreeE (VRuleRef n) <- rule = dereferenceAndValidate cddl n (validateTerm cddl term) | CTreeE (VValidator v _) <- rule =- runCustomValidator term v+ runCustomValidator cddl (SingleTerm term) v | otherwise = case term of TInt i -> validateInteger cddl (fromIntegral i) rule@@ -100,18 +139,22 @@ TFloat h -> validateFloat cddl h rule TDouble d -> validateDouble cddl d rule -terminal :: CTree ValidatorStage -> Evidenced ValidationTrace+terminal :: CTree ValidatorPhase -> Evidenced ValidationTrace terminal = evidence . TerminalRule . mapIndex -- | Run a custom validator on a term. This is used by type-specific validators -- when they encounter a 'VValidator' node after dereferencing a rule reference.-runCustomValidator :: Term -> CBORValidator -> Evidenced ValidationTrace-runCustomValidator term (CBORValidator validator) =- case validator term of+runCustomValidator ::+ CTreeRoot ValidatorPhase ->+ RuleTerm ->+ TermValidator ->+ Evidenced ValidationTrace+runCustomValidator cddl term validator =+ case runValidator (validator term) cddl of CustomValidatorSuccess -> evidence CustomSuccess CustomValidatorFailure err -> evidence $ CustomFailure err -unapplicable :: CTree ValidatorStage -> Evidenced ValidationTrace+unapplicable :: CTree ValidatorPhase -> Evidenced ValidationTrace unapplicable = evidence . UnapplicableRule . mapIndex --------------------------------------------------------------------------------@@ -130,14 +173,14 @@ -- Ints, so we convert everything to Integer. validateInteger :: HasCallStack =>- CTreeRoot ValidatorStage ->+ CTreeRoot ValidatorPhase -> Integer ->- CTree ValidatorStage ->+ CTree ValidatorPhase -> Evidenced ValidationTrace validateInteger cddl i rule = case rule of CTreeE (VRuleRef n) -> dereferenceAndValidate cddl n $ validateInteger cddl i- CTreeE (VValidator v _) -> runCustomValidator (TInteger i) v+ CTreeE (VValidator v _) -> runCustomValidator cddl (SingleTerm $ TInteger i) v -- echo "C24101" | xxd -r -p - example.cbor -- echo "foo = int" > a.cddl -- cddl a.cddl validate example.cbor@@ -229,10 +272,10 @@ -- | Controls for an Integer controlInteger :: HasCallStack =>- CTreeRoot ValidatorStage ->+ CTreeRoot ValidatorPhase -> Integer -> CtlOp ->- CTree ValidatorStage ->+ CTree ValidatorPhase -> Bool controlInteger cddl i op (CTreeE (VRuleRef n)) = controlInteger cddl i op $ dereference cddl n@@ -302,12 +345,12 @@ -- | Validating a `Float16` validateHalf :: HasCallStack =>- CTreeRoot ValidatorStage ->+ CTreeRoot ValidatorPhase -> Float ->- CTree ValidatorStage ->+ CTree ValidatorPhase -> Evidenced ValidationTrace validateHalf cddl f (CTreeE (VRuleRef n)) = dereferenceAndValidate cddl n $ validateHalf cddl f-validateHalf _ f (CTreeE (VValidator v _)) = runCustomValidator (THalf f) v+validateHalf cddl f (CTreeE (VValidator v _)) = runCustomValidator cddl (SingleTerm $ THalf f) v validateHalf cddl f rule = case rule of -- a = any@@ -332,10 +375,10 @@ -- | Controls for `Float16` controlHalf :: HasCallStack =>- CTreeRoot ValidatorStage ->+ CTreeRoot ValidatorPhase -> Float -> CtlOp ->- CTree ValidatorStage ->+ CTree ValidatorPhase -> Bool controlHalf cddl f op (CTreeE (VRuleRef n)) = controlHalf cddl f op $ dereference cddl n@@ -352,13 +395,13 @@ -- | Validating a `Float32` validateFloat :: HasCallStack =>- CTreeRoot ValidatorStage ->+ CTreeRoot ValidatorPhase -> Float ->- CTree ValidatorStage ->+ CTree ValidatorPhase -> Evidenced ValidationTrace validateFloat cddl f (CTreeE (VRuleRef n)) = dereferenceAndValidate cddl n $ validateFloat cddl f-validateFloat _ f (CTreeE (VValidator v _)) = runCustomValidator (TFloat f) v+validateFloat cddl f (CTreeE (VValidator v _)) = runCustomValidator cddl (SingleTerm $ TFloat f) v validateFloat cddl f rule = case rule of -- a = any@@ -392,10 +435,10 @@ -- | Controls for `Float32` controlFloat :: HasCallStack =>- CTreeRoot ValidatorStage ->+ CTreeRoot ValidatorPhase -> Float -> CtlOp ->- CTree ValidatorStage ->+ CTree ValidatorPhase -> Bool controlFloat cddl f op (CTreeE (VRuleRef n)) = controlFloat cddl f op $ dereference cddl n@@ -414,13 +457,13 @@ -- | Validating a `Float64` validateDouble :: HasCallStack =>- CTreeRoot ValidatorStage ->+ CTreeRoot ValidatorPhase -> Double ->- CTree ValidatorStage ->+ CTree ValidatorPhase -> Evidenced ValidationTrace validateDouble cddl f (CTreeE (VRuleRef n)) = dereferenceAndValidate cddl n $ validateDouble cddl f-validateDouble _ f (CTreeE (VValidator v _)) = runCustomValidator (TDouble f) v+validateDouble cddl f (CTreeE (VValidator v _)) = runCustomValidator cddl (SingleTerm $ TDouble f) v validateDouble cddl f rule = case rule of -- a = any@@ -458,10 +501,10 @@ -- | Controls for `Float64` controlDouble :: HasCallStack =>- CTreeRoot ValidatorStage ->+ CTreeRoot ValidatorPhase -> Double -> CtlOp ->- CTree ValidatorStage ->+ CTree ValidatorPhase -> Bool controlDouble cddl f op (CTreeE (VRuleRef n)) = controlDouble cddl f op $ dereference cddl n@@ -484,13 +527,13 @@ -- | Validating a boolean validateBool ::- CTreeRoot ValidatorStage ->+ CTreeRoot ValidatorPhase -> Bool ->- CTree ValidatorStage ->+ CTree ValidatorPhase -> Evidenced ValidationTrace validateBool cddl b (CTreeE (VRuleRef n)) = dereferenceAndValidate cddl n $ validateBool cddl b-validateBool _ b (CTreeE (VValidator v _)) = runCustomValidator (TBool b) v+validateBool cddl b (CTreeE (VValidator v _)) = runCustomValidator cddl (SingleTerm $ TBool b) v validateBool cddl b rule = case rule of -- a = any@@ -508,10 +551,10 @@ -- | Controls for `Bool` controlBool :: HasCallStack =>- CTreeRoot ValidatorStage ->+ CTreeRoot ValidatorPhase -> Bool -> CtlOp ->- CTree ValidatorStage ->+ CTree ValidatorPhase -> Bool controlBool cddl b op (CTreeE (VRuleRef n)) = controlBool cddl b op $ dereference cddl n@@ -530,13 +573,13 @@ -- | Validating a `TSimple`. It is unclear if this is used for anything else than `undefined`. validateSimple ::- CTreeRoot ValidatorStage ->+ CTreeRoot ValidatorPhase -> Word8 ->- CTree ValidatorStage ->+ CTree ValidatorPhase -> Evidenced ValidationTrace validateSimple cddl i (CTreeE (VRuleRef n)) = dereferenceAndValidate cddl n $ validateSimple cddl i-validateSimple _ i (CTreeE (VValidator v _)) = runCustomValidator (TSimple i) v+validateSimple cddl i (CTreeE (VValidator v _)) = runCustomValidator cddl (SingleTerm $ TSimple i) v validateSimple cddl 23 rule = case rule of -- a = any@@ -552,10 +595,10 @@ -- Null/nil -- | Validating nil-validateNull :: CTreeRoot ValidatorStage -> CTree ValidatorStage -> Evidenced ValidationTrace+validateNull :: CTreeRoot ValidatorPhase -> CTree ValidatorPhase -> Evidenced ValidationTrace validateNull cddl (CTreeE (VRuleRef n)) = dereferenceAndValidate cddl n $ validateNull cddl-validateNull _ (CTreeE (VValidator v _)) = runCustomValidator TNull v+validateNull cddl (CTreeE (VValidator v _)) = runCustomValidator cddl (SingleTerm TNull) v validateNull cddl rule = case rule of -- a = any@@ -570,10 +613,10 @@ -- | Validating a byte sequence validateBytes ::- CTreeRoot ValidatorStage -> BS.ByteString -> CTree ValidatorStage -> Evidenced ValidationTrace+ CTreeRoot ValidatorPhase -> BS.ByteString -> CTree ValidatorPhase -> Evidenced ValidationTrace validateBytes cddl bs (CTreeE (VRuleRef n)) = dereferenceAndValidate cddl n $ validateBytes cddl bs-validateBytes _ bs (CTreeE (VValidator v _)) = runCustomValidator (TBytes bs) v+validateBytes cddl bs (CTreeE (VValidator v _)) = runCustomValidator cddl (SingleTerm $ TBytes bs) v validateBytes cddl bs rule = case rule of -- a = any@@ -591,10 +634,10 @@ -- | Controls for byte strings controlBytes :: HasCallStack =>- CTreeRoot ValidatorStage ->+ CTreeRoot ValidatorPhase -> BS.ByteString -> CtlOp ->- CTree ValidatorStage ->+ CTree ValidatorPhase -> Bool controlBytes cddl bs op (CTreeE (VRuleRef n)) = controlBytes cddl bs op $ dereference cddl n@@ -653,13 +696,13 @@ -- | Validating text strings validateText ::- CTreeRoot ValidatorStage ->+ CTreeRoot ValidatorPhase -> T.Text ->- CTree ValidatorStage ->+ CTree ValidatorPhase -> Evidenced ValidationTrace validateText cddl txt (CTreeE (VRuleRef n)) = dereferenceAndValidate cddl n $ validateText cddl txt-validateText _ txt (CTreeE (VValidator v _)) = runCustomValidator (TString txt) v+validateText cddl txt (CTreeE (VValidator v _)) = runCustomValidator cddl (SingleTerm $ TString txt) v validateText cddl txt rule = case rule of -- a = any@@ -677,10 +720,10 @@ -- | Controls for text strings controlText :: HasCallStack =>- CTreeRoot ValidatorStage ->+ CTreeRoot ValidatorPhase -> T.Text -> CtlOp ->- CTree ValidatorStage ->+ CTree ValidatorPhase -> Bool controlText cddl bs op (CTreeE (VRuleRef n)) = controlText cddl bs op $ dereference cddl n@@ -715,10 +758,10 @@ -- | Validating a `TTagged` validateTagged ::- CTreeRoot ValidatorStage -> Word64 -> Term -> CTree ValidatorStage -> Evidenced ValidationTrace+ CTreeRoot ValidatorPhase -> Word64 -> Term -> CTree ValidatorPhase -> Evidenced ValidationTrace validateTagged cddl tag term (CTreeE (VRuleRef n)) = dereferenceAndValidate cddl n $ validateTagged cddl tag term-validateTagged _ tag term (CTreeE (VValidator v _)) = runCustomValidator (TTagged tag term) v+validateTagged cddl tag term (CTreeE (VValidator v _)) = runCustomValidator cddl (SingleTerm $ TTagged tag term) v validateTagged cddl tag term rule = case rule of Postlude PTAny -> terminal rule@@ -766,13 +809,13 @@ clampedPred x = pred x validateList ::- CTreeRoot ValidatorStage ->+ CTreeRoot ValidatorPhase -> [Term] ->- CTree ValidatorStage ->+ CTree ValidatorPhase -> Evidenced ValidationTrace validateList cddl terms (CTreeE (VRuleRef n)) = dereferenceAndValidate cddl n $ validateList cddl terms-validateList _ terms (CTreeE (VValidator v _)) = runCustomValidator (TList terms) v+validateList cddl terms (CTreeE (VValidator v _)) = runCustomValidator cddl (SingleTerm $ TList terms) v validateList cddl terms rule = case rule of Postlude PTAny -> terminal rule@@ -797,10 +840,10 @@ _ -> unapplicable rule where validate ::- ([CTree ValidatorStage] -> [Term] -> Evidenced ListValidationTrace) ->- [CTree ValidatorStage] ->+ ([CTree ValidatorPhase] -> [Term] -> Evidenced ListValidationTrace) ->+ [CTree ValidatorPhase] -> [Term] ->- [CTree ValidatorStage] ->+ [CTree ValidatorPhase] -> (Evidenced ListValidationTrace, [Term]) validate f skipped tss [] = (f skipped tss, tss) validate f skipped [] (r : rs)@@ -852,13 +895,13 @@ validateMap :: HasCallStack =>- CTreeRoot ValidatorStage ->+ CTreeRoot ValidatorPhase -> [(Term, Term)] ->- CTree ValidatorStage ->+ CTree ValidatorPhase -> Evidenced ValidationTrace validateMap cddl terms (CTreeE (VRuleRef n)) = dereferenceAndValidate cddl n $ validateMap cddl terms-validateMap _ terms (CTreeE (VValidator v _)) = runCustomValidator (TMap terms) v+validateMap cddl terms (CTreeE (VValidator v _)) = runCustomValidator cddl (SingleTerm $ TMap terms) v validateMap cddl terms rule = case rule of Postlude PTAny -> terminal rule@@ -867,7 +910,7 @@ _ -> unapplicable rule where validate ::- [CTree ValidatorStage] -> [(Term, Term)] -> [CTree ValidatorStage] -> Evidenced MapValidationTrace+ [CTree ValidatorPhase] -> [(Term, Term)] -> [CTree ValidatorPhase] -> Evidenced MapValidationTrace validate _ [] [] = evidence MapValidationDone validate exhausted (kv : _) [] = let@@ -930,12 +973,12 @@ -- Choices validateChoice ::- (CTree ValidatorStage -> Evidenced ValidationTrace) ->- NE.NonEmpty (CTree ValidatorStage) ->+ (CTree ValidatorPhase -> Evidenced ValidationTrace) ->+ NE.NonEmpty (CTree ValidatorPhase) -> Evidenced ValidationTrace validateChoice v = go 0 where- go :: Int -> NE.NonEmpty (CTree ValidatorStage) -> Evidenced ValidationTrace+ go :: Int -> NE.NonEmpty (CTree ValidatorPhase) -> Evidenced ValidationTrace go i (choice NE.:| xs) = do case v choice of Evidenced SValid trc -> evidence $ ChoiceBranch i trc@@ -948,9 +991,9 @@ -- | Validate both rules ctrlAnd ::- (CTree ValidatorStage -> Evidenced ValidationTrace) ->- CTree ValidatorStage ->- CTree ValidatorStage ->+ (CTree ValidatorPhase -> Evidenced ValidationTrace) ->+ CTree ValidatorPhase ->+ CTree ValidatorPhase -> Evidenced ValidationTrace ctrlAnd v tgt ctrl = case v tgt of@@ -959,11 +1002,11 @@ -- | Dispatch to the appropriate control ctrlDispatch ::- (CTree ValidatorStage -> Evidenced ValidationTrace) ->+ (CTree ValidatorPhase -> Evidenced ValidationTrace) -> CtlOp ->- CTree ValidatorStage ->- CTree ValidatorStage ->- (CtlOp -> CTree ValidatorStage -> Bool) ->+ CTree ValidatorPhase ->+ CTree ValidatorPhase ->+ (CtlOp -> CTree ValidatorPhase -> Bool) -> Evidenced ValidationTrace ctrlDispatch v And tgt ctrl _ = ctrlAnd v tgt ctrl ctrlDispatch v Within tgt ctrl _ = ctrlAnd v tgt ctrl@@ -979,7 +1022,7 @@ -------------------------------------------------------------------------------- -- Bits control -getIndicesOfChoice :: CTreeRoot ValidatorStage -> NE.NonEmpty (CTree ValidatorStage) -> [Word64]+getIndicesOfChoice :: CTreeRoot ValidatorPhase -> NE.NonEmpty (CTree ValidatorPhase) -> [Word64] getIndicesOfChoice cddl = concatMap go where go = \case@@ -1000,7 +1043,7 @@ <> showSimple somethingElse getIndicesOfRange ::- CTreeRoot ValidatorStage -> CTree ValidatorStage -> CTree ValidatorStage -> RangeBound -> [Word64]+ CTreeRoot ValidatorPhase -> CTree ValidatorPhase -> CTree ValidatorPhase -> RangeBound -> [Word64] getIndicesOfRange cddl (CTreeE (VRuleRef n)) tt incl = dereference cddl n & \ff -> getIndicesOfRange cddl ff tt incl getIndicesOfRange cddl ff (CTreeE (VRuleRef n)) incl =@@ -1015,7 +1058,7 @@ rng = [ff' .. tt'] (lo, hi) -> error $ "Malformed range in .bits: (" <> showSimple lo <> ", " <> showSimple hi <> ")" -getIndicesOfEnum :: CTreeRoot ValidatorStage -> CTree ValidatorStage -> [Word64]+getIndicesOfEnum :: CTreeRoot ValidatorPhase -> CTree ValidatorPhase -> [Word64] getIndicesOfEnum cddl (CTreeE (VRuleRef n)) = getIndicesOfEnum cddl $ dereference cddl n getIndicesOfEnum cddl g = case g of@@ -1023,18 +1066,18 @@ somethingElse -> error $ "Malformed enum in .bits: " <> showSimple somethingElse dereference ::- CTreeRoot ValidatorStage ->+ CTreeRoot ValidatorPhase -> Name ->- CTree ValidatorStage+ CTree ValidatorPhase dereference (CTreeRoot m) n = case Map.lookup n m of Just r -> r Nothing -> error $ "Nonexistent rule referenced: " <> T.unpack (unName n) dereferenceAndValidate ::- CTreeRoot ValidatorStage ->+ CTreeRoot ValidatorPhase -> Name ->- (CTree ValidatorStage -> Evidenced ValidationTrace) ->+ (CTree ValidatorPhase -> Evidenced ValidationTrace) -> Evidenced ValidationTrace dereferenceAndValidate cddl n f = mapTrace (ReferenceRule n) . f $ dereference cddl n
src/Codec/CBOR/Cuddle/CBOR/Validator/Trace.hs view
@@ -10,8 +10,7 @@ {-# LANGUAGE UndecidableInstances #-} module Codec.CBOR.Cuddle.CBOR.Validator.Trace (- ValidatorStage,- ValidatorStageSimple,+ ValidatorPhaseSimple, XXCTree (..), SValidity (..), Validity (..),@@ -34,11 +33,11 @@ foldEvidenced, ) where -import Codec.CBOR.Cuddle.CDDL (Name (..), OccurrenceIndicator (..), RangeBound (..), XTerm)-import Codec.CBOR.Cuddle.CDDL.CBORGenerator (CBORValidator)+import Codec.CBOR.Cuddle.CDDL (Name (..)) import Codec.CBOR.Cuddle.CDDL.CTree (CTree (..), CTreeRoot (..), Node, XXCTree, foldCTree) import Codec.CBOR.Cuddle.CDDL.CtlOp (CtlOp)-import Codec.CBOR.Cuddle.CDDL.Resolve (MonoReferenced, XXCTree (..))+import Codec.CBOR.Cuddle.CDDL.Custom.Validator (ValidatorPhase)+import Codec.CBOR.Cuddle.CDDL.Resolve (XXCTree (..)) import Codec.CBOR.Cuddle.IndexMappable (IndexMappable (..)) import Codec.CBOR.Term (Term) import Data.Foldable (Foldable (..))@@ -54,14 +53,9 @@ Pretty (..), annotate, defaultLayoutOptions,- encloseSep,- group, hang, indent, layoutPretty,- list,- punctuate,- tupled, vsep, (<+>), )@@ -69,73 +63,34 @@ import Prettyprinter.Render.Terminal qualified as Ansi ----------------------------------------------------------------------------------- ValidatorStage--type data ValidatorStage--data instance XTerm ValidatorStage = ValidatorXTerm- deriving (Show, Eq)--data instance XXCTree ValidatorStage- = VRuleRef Name- | VValidator CBORValidator (CTree ValidatorStage)--instance IndexMappable CTreeRoot MonoReferenced ValidatorStage where- mapIndex (CTreeRoot m) = CTreeRoot $ mapIndex <$> m+-- ValidatorPhase -instance IndexMappable CTree MonoReferenced ValidatorStage where- mapIndex = foldCTree mapExt mapIndex- where- mapExt (MRuleRef n) = CTreeE $ VRuleRef n- mapExt (MGenerator _ x) = mapIndex x- mapExt (MValidator v x) = CTreeE . VValidator v $ mapIndex x+type data ValidatorPhaseSimple -type data ValidatorStageSimple+newtype instance XXCTree ValidatorPhaseSimple = VRuleRefSimple Name -newtype instance XXCTree ValidatorStageSimple = VRuleRefSimple Name+instance Pretty (XXCTree ValidatorPhaseSimple) where+ pretty (VRuleRefSimple n) = pretty n -instance IndexMappable CTreeRoot ValidatorStage ValidatorStageSimple where+instance IndexMappable CTreeRoot ValidatorPhase ValidatorPhaseSimple where mapIndex (CTreeRoot m) = CTreeRoot $ mapIndex <$> m -instance IndexMappable CTree ValidatorStage ValidatorStageSimple where+instance IndexMappable CTree ValidatorPhase ValidatorPhaseSimple where mapIndex = foldCTree mapExt mapIndex where mapExt (VRuleRef n) = CTreeE $ VRuleRefSimple n mapExt (VValidator _ x) = mapIndex x -instance Pretty (CTree ValidatorStageSimple) where- pretty = \case- Literal v -> pretty v- Postlude v -> pretty v- Range lo hi ClOpen -> pretty lo <+> "..." <+> pretty hi- Range lo hi Closed -> pretty lo <+> ".." <+> pretty hi- KV k v _ -> pretty k <+> "==>" <+> pretty v- CTreeE (VRuleRefSimple (Name n)) -> pretty n- Occur v oi ->- case oi of- OIOptional -> "?" <+> pretty v- OIZeroOrMore -> "*" <+> pretty v- OIOneOrMore -> "+" <+> pretty v- OIBounded lo hi -> foldMap pretty lo <> "*" <> foldMap pretty hi <+> pretty v- Map m -> encloseSep "{" "}" "," $ pretty <$> m- Array e -> list $ pretty <$> e- Choice c -> group . vsep . punctuate "//" $ pretty <$> toList c- Group g -> tupled $ pretty <$> g- Control op tgt ctl -> pretty tgt <+> pretty op <+> pretty ctl- Enum e -> "&" <> pretty e- Unwrap x -> "~" <> pretty x- Tag t x -> "#6." <> pretty t <> "(" <> pretty x <> ")"- showSimple ::- ( IndexMappable a ValidatorStage ValidatorStageSimple- , Show (a ValidatorStageSimple)+ ( IndexMappable a ValidatorPhase ValidatorPhaseSimple+ , Show (a ValidatorPhaseSimple) ) =>- a ValidatorStage -> String-showSimple = show . mapIndex @_ @_ @ValidatorStageSimple+ a ValidatorPhase -> String+showSimple = show . mapIndex @_ @_ @ValidatorPhaseSimple -deriving instance Eq (Node ValidatorStageSimple)+deriving instance Eq (Node ValidatorPhaseSimple) -deriving instance Show (Node ValidatorStageSimple)+deriving instance Show (Node ValidatorPhaseSimple) -------------------------------------------------------------------------------- -- Validation result@@ -161,7 +116,7 @@ data ControlInfo = ControlInfo { ciOp :: CtlOp- , ciRule :: CTree ValidatorStageSimple+ , ciRule :: CTree ValidatorPhaseSimple } deriving (Show) @@ -169,13 +124,13 @@ pretty ControlInfo {..} = pretty ciOp <+> pretty ciRule data ValidationTrace (v :: Validity) where- UnapplicableRule :: CTree ValidatorStageSimple -> ValidationTrace IsInvalid- TerminalRule :: CTree ValidatorStageSimple -> ValidationTrace IsValid+ UnapplicableRule :: CTree ValidatorPhaseSimple -> ValidationTrace IsInvalid+ TerminalRule :: CTree ValidatorPhaseSimple -> ValidationTrace IsValid ControlTrace :: ControlInfo -> ValidationTrace IsValid -> ValidationTrace IsValid ReferenceRule :: Name -> ValidationTrace v -> ValidationTrace v CustomFailure :: Text -> ValidationTrace IsInvalid CustomSuccess :: ValidationTrace IsValid- UnsatisfiedControl :: CtlOp -> CTree ValidatorStageSimple -> ValidationTrace IsInvalid+ UnsatisfiedControl :: CtlOp -> CTree ValidatorPhaseSimple -> ValidationTrace IsInvalid ChoiceBranch :: Int -> ValidationTrace IsValid -> ValidationTrace IsValid ListTrace :: ListValidationTrace v -> ValidationTrace v MapTrace :: MapValidationTrace v -> ValidationTrace v@@ -188,18 +143,18 @@ ListValidationDone :: ListValidationTrace IsValid ListValidationLeftoverTerms :: NonEmpty Term ->- Maybe (CTree ValidatorStageSimple, ValidationTrace IsInvalid) ->+ Maybe (CTree ValidatorPhaseSimple, ValidationTrace IsInvalid) -> ListValidationTrace IsInvalid ListValidationUnappliedRule ::- CTree ValidatorStageSimple ->+ CTree ValidatorPhaseSimple -> ListValidationTrace IsInvalid ListValidationConsume ::- CTree ValidatorStageSimple ->+ CTree ValidatorPhaseSimple -> ValidationTrace IsValid -> ListValidationTrace v -> ListValidationTrace v ListValidationMissingRequired ::- CTree ValidatorStageSimple ->+ CTree ValidatorPhaseSimple -> ValidationTrace IsInvalid -> ListValidationTrace IsInvalid ListValidationConsumeGroup ::@@ -218,16 +173,16 @@ MapValidationDone :: MapValidationTrace IsValid MapValidationLeftoverKVs :: (Term, Term) ->- Maybe (CTree ValidatorStageSimple, MapValidationTrace IsInvalid) ->+ Maybe (CTree ValidatorPhaseSimple, MapValidationTrace IsInvalid) -> MapValidationTrace IsInvalid- MapValidationUnappliedRules :: NonEmpty (CTree ValidatorStageSimple) -> MapValidationTrace IsInvalid+ MapValidationUnappliedRules :: NonEmpty (CTree ValidatorPhaseSimple) -> MapValidationTrace IsInvalid MapValidationInvalidValue ::- CTree ValidatorStageSimple ->+ CTree ValidatorPhaseSimple -> ValidationTrace IsValid -> ValidationTrace IsInvalid -> MapValidationTrace IsInvalid MapValidationConsume ::- CTree ValidatorStageSimple ->+ CTree ValidatorPhaseSimple -> ValidationTrace IsValid -> ValidationTrace IsValid -> MapValidationTrace v ->
src/Codec/CBOR/Cuddle/CDDL.hs view
@@ -39,6 +39,7 @@ unwrap, compareRuleName, HasName (..),+ GRef (..), -- Extension ForAllExtensions, XCddl,@@ -160,6 +161,10 @@ deriving (Generic) deriving (Eq, Ord, Show) deriving newtype (Semigroup, Monoid)++-- | A reference to a generic parameter inside the body of a generic rule.+newtype GRef = GRef T.Text+ deriving (Show) deriving anyclass instance ToExpr Name
− src/Codec/CBOR/Cuddle/CDDL/CBORGenerator.hs
@@ -1,92 +0,0 @@-{-# LANGUAGE TypeData #-}-{-# LANGUAGE TypeFamilies #-}--module Codec.CBOR.Cuddle.CDDL.CBORGenerator (- CBORGen (..),- GenEnv (..),- HasGenerator (..),- WrappedTerm (..),- CBORValidator (..),- HasValidator (..),- GenPhase,- XXCTree (..),- CustomValidatorResult (..),- liftAntiGen,- runCBORGen,- lookupCddl,- withAntiGen,- withTwiddle,-) where--import Codec.CBOR.Cuddle.CDDL (Name)-import Codec.CBOR.Cuddle.CDDL.CTree (CTree, CTreeRoot (..), XXCTree)-import Codec.CBOR.Term (Term)-import Control.Monad.Reader (MonadReader (..), ReaderT (..), asks, mapReaderT)-import Data.Map.Strict qualified as Map-import Data.Text (Text)-import GHC.Generics (Generic)-import Optics.Core (Lens')-import Test.AntiGen (AntiGen)-import Test.QuickCheck.GenT (MonadGen (..))--type data GenPhase--data GenEnv = GenEnv- { geRoot :: CTreeRoot GenPhase- , geTwiddle :: Bool- }- deriving (Generic)--newtype CBORGen a = CBORGen (ReaderT GenEnv AntiGen a)- deriving (Functor, Applicative, Monad, MonadReader GenEnv)--instance MonadGen CBORGen where- liftGen g = CBORGen $ ReaderT $ \_ -> liftGen g- variant n (CBORGen m) = CBORGen $ mapReaderT (variant n) m- sized f = CBORGen . ReaderT $ \env -> sized $ \n ->- let CBORGen m = f n in runReaderT m env- resize n (CBORGen m) = CBORGen $ mapReaderT (resize n) m- choose rng = CBORGen . ReaderT $ \_ -> choose rng--liftAntiGen :: AntiGen a -> CBORGen a-liftAntiGen m = CBORGen . ReaderT $ const m--runCBORGen :: GenEnv -> CBORGen a -> AntiGen a-runCBORGen env (CBORGen m) = runReaderT m env--lookupCddl :: Name -> CBORGen (Maybe (CTree GenPhase))-lookupCddl n = do- CTreeRoot root <- asks geRoot- pure $ Map.lookup n root--withAntiGen :: (AntiGen a -> AntiGen b) -> CBORGen a -> CBORGen b-withAntiGen f (CBORGen m) = CBORGen $ ReaderT $ \env -> f (runReaderT m env)--withTwiddle :: Bool -> CBORGen a -> CBORGen a-withTwiddle t = local (\x -> x {geTwiddle = t})--data instance XXCTree GenPhase- = GenRef Name- | GenGenerator (CBORGen WrappedTerm) (CTree GenPhase)--data WrappedTerm- = -- | Single term- S Term- | -- | Pair term- P Term Term- | -- | Group term- G [WrappedTerm]- deriving (Eq, Ord, Show)--class HasGenerator a where- generatorL :: Lens' a (Maybe (CBORGen WrappedTerm))--class HasValidator a where- validatorL :: Lens' a (Maybe CBORValidator)--data CustomValidatorResult- = CustomValidatorSuccess- | CustomValidatorFailure Text- deriving (Generic, Show, Eq)--newtype CBORValidator = CBORValidator (Term -> CustomValidatorResult)
src/Codec/CBOR/Cuddle/CDDL/CTreePhase.hs view
@@ -12,7 +12,9 @@ ) where import Codec.CBOR.Cuddle.CDDL (XCddl, XRule, XTerm, XXTopLevel, XXType2)-import Codec.CBOR.Cuddle.CDDL.CBORGenerator (CBORGen, CBORValidator, WrappedTerm)+import Codec.CBOR.Cuddle.CDDL.Custom.Core (RuleTerm)+import Codec.CBOR.Cuddle.CDDL.Custom.Generator (CBORGen)+import Codec.CBOR.Cuddle.CDDL.Custom.Validator (TermValidator) import Data.Default.Class (Default) import Data.Hashable (Hashable) import GHC.Generics (Generic)@@ -29,7 +31,8 @@ data instance XCddl CTreePhase = CTreeXCddl deriving (Generic, Show, Eq, Ord) -data instance XRule CTreePhase = CTreeXRule (Maybe (CBORGen WrappedTerm)) (Maybe CBORValidator)+data instance XRule CTreePhase+ = CTreeXRule (Maybe (CBORGen RuleTerm)) (Maybe TermValidator) deriving (Generic) data instance XXType2 CTreePhase
+ src/Codec/CBOR/Cuddle/CDDL/Custom/Core.hs view
@@ -0,0 +1,25 @@+{-# LANGUAGE TypeFamilies #-}++module Codec.CBOR.Cuddle.CDDL.Custom.Core (MonadCddl (..), RuleTerm (..)) where++import Codec.CBOR.Cuddle.CDDL (GRef, Name)+import Codec.CBOR.Cuddle.CDDL.CTree (CTree)+import Codec.CBOR.Term (Term)+import Data.Kind (Type)++class MonadCddl m where+ type Phase m :: Type++ -- | Look up a top-level rule by name.+ lookupCddl :: Name -> m (Maybe (CTree (Phase m)))++ -- | Look up the rule bound to a generic parameter at the enclosing rule.+ -- Returns 'Nothing' outside of a custom generator/validator that was+ -- attached to a generic rule.+ lookupGRef :: GRef -> m (Maybe (CTree (Phase m)))++data RuleTerm+ = SingleTerm Term+ | PairTerm Term Term+ | GroupTerm [RuleTerm]+ deriving (Eq, Ord, Show)
+ src/Codec/CBOR/Cuddle/CDDL/Custom/Generator.hs view
@@ -0,0 +1,103 @@+{-# LANGUAGE TypeData #-}+{-# LANGUAGE TypeFamilies #-}++module Codec.CBOR.Cuddle.CDDL.Custom.Generator (+ GenPhase,+ CBORGen,+ XXCTree (..),+ HasGenerator (..),+ GenConfig (..),+ GenEnv (..),+ liftAntiGen,+ runCBORGen,+ withAntiGen,+ withLocalGenBindings,+ disableTwiddle,+ enableTwiddle,+) where++import Codec.CBOR.Cuddle.CDDL (GRef (..), Name (..))+import Codec.CBOR.Cuddle.CDDL.CTree (CTree, CTreeRoot (..), XXCTree)+import Codec.CBOR.Cuddle.CDDL.Custom.Core (MonadCddl (..), RuleTerm)+import Control.Monad.Reader (MonadReader (..), ReaderT (..), asks, mapReaderT)+import Data.Map.Strict (Map)+import Data.Map.Strict qualified as Map+import GHC.Generics (Generic)+import Optics.Lens (Lens')+import Test.AntiGen (AntiGen)+import Test.QuickCheck.GenT (MonadGen (..))++type data GenPhase++-- | User-supplied configuration for the generator monad. Set once at the+-- top level when calling 'runCBORGen'.+data GenConfig = GenConfig+ { gcRoot :: CTreeRoot GenPhase+ , gcTwiddle :: !Bool+ }+ deriving (Generic)++-- | Runtime environment for the generator monad: the user-supplied+-- 'GenConfig' plus the bindings active at the current point.+data GenEnv = GenEnv+ { geConfig :: GenConfig+ , geLocal :: Map Name (CTree GenPhase)+ }+ deriving (Generic)++newtype CBORGen a = CBORGen (ReaderT GenEnv AntiGen a)+ deriving (Functor, Applicative, Monad, MonadReader GenEnv)++instance MonadGen CBORGen where+ liftGen g = CBORGen $ ReaderT $ \_ -> liftGen g+ variant n (CBORGen m) = CBORGen $ mapReaderT (variant n) m+ sized f = CBORGen . ReaderT $ \env -> sized $ \n ->+ let CBORGen m = f n in runReaderT m env+ resize n (CBORGen m) = CBORGen $ mapReaderT (resize n) m+ choose rng = CBORGen . ReaderT $ \_ -> choose rng++liftAntiGen :: AntiGen a -> CBORGen a+liftAntiGen m = CBORGen . ReaderT $ const m++runCBORGen :: GenConfig -> CBORGen a -> AntiGen a+runCBORGen cfg (CBORGen m) =+ runReaderT m GenEnv {geConfig = cfg, geLocal = Map.empty}++instance MonadCddl CBORGen where+ type Phase CBORGen = GenPhase++ lookupCddl n = do+ CTreeRoot root <- asks (gcRoot . geConfig)+ pure $ Map.lookup n root++ lookupGRef (GRef t) = do+ binds <- asks geLocal+ pure $ Map.lookup (Name t) binds++withAntiGen :: (AntiGen a -> AntiGen b) -> CBORGen a -> CBORGen b+withAntiGen f (CBORGen m) = CBORGen $ ReaderT $ \env -> f (runReaderT m env)++withTwiddle :: Bool -> CBORGen a -> CBORGen a+withTwiddle t =+ local (\env -> env {geConfig = (geConfig env) {gcTwiddle = t}})++disableTwiddle :: CBORGen a -> CBORGen a+disableTwiddle = withTwiddle False++enableTwiddle :: CBORGen a -> CBORGen a+enableTwiddle = withTwiddle True++-- | Run an action with the given local generic bindings installed.+-- Used to wrap custom generators attached to generic rules so that+-- 'lookupGRef' resolves to the type bound at the enclosing rule.+withLocalGenBindings ::+ Map Name (CTree GenPhase) -> CBORGen a -> CBORGen a+withLocalGenBindings binds =+ local (\env -> env {geLocal = binds `Map.union` geLocal env})++data instance XXCTree GenPhase+ = GenRef Name+ | GenGenerator (CBORGen RuleTerm) (CTree GenPhase)++class HasGenerator a where+ generatorL :: Lens' a (Maybe (CBORGen RuleTerm))
+ src/Codec/CBOR/Cuddle/CDDL/Custom/Validator.hs view
@@ -0,0 +1,76 @@+{-# LANGUAGE TypeData #-}+{-# LANGUAGE TypeFamilies #-}++module Codec.CBOR.Cuddle.CDDL.Custom.Validator (+ TermValidator,+ ValidatorPhase,+ Validator,+ CustomValidatorResult (..),+ XXCTree (..),+ HasValidator (..),+ ValidateEnv (..),+ withLocalValidateBindings,+ runValidator,+) where++import Codec.CBOR.Cuddle.CDDL (GRef (..), Name (..))+import Codec.CBOR.Cuddle.CDDL.CTree (CTree, CTreeRoot (..))+import Codec.CBOR.Cuddle.CDDL.Custom.Core (MonadCddl (..), RuleTerm)+import Codec.CBOR.Cuddle.CDDL.Custom.Generator (XXCTree)+import Control.Monad.Reader (MonadReader (..), ReaderT (..), asks)+import Data.Map.Strict (Map)+import Data.Map.Strict qualified as Map+import Data.Text (Text)+import Data.Text qualified as T+import GHC.Generics (Generic)+import Optics.Lens (Lens')++type data ValidatorPhase++data instance XXCTree ValidatorPhase+ = VRuleRef Name+ | VValidator TermValidator (CTree ValidatorPhase)++class HasValidator a where+ validatorL :: Lens' a (Maybe TermValidator)++data CustomValidatorResult+ = CustomValidatorSuccess+ | CustomValidatorFailure Text+ deriving (Generic, Show, Eq)++data ValidateEnv = ValidateEnv+ { veRoot :: CTreeRoot ValidatorPhase+ , veLocal :: Map Name (CTree ValidatorPhase)+ }++newtype Validator a = Validator (ReaderT ValidateEnv (Either Text) a)+ deriving (Functor, Applicative, Monad, MonadReader ValidateEnv)++type TermValidator = RuleTerm -> Validator ()++instance MonadCddl Validator where+ type Phase Validator = ValidatorPhase++ lookupCddl n = do+ CTreeRoot root <- asks veRoot+ pure $ Map.lookup n root++ lookupGRef (GRef t) = do+ binds <- asks veLocal+ pure $ Map.lookup (Name t) binds++instance MonadFail Validator where+ fail msg = Validator . ReaderT $ \_ -> Left $ T.pack msg++-- | Run an action with the given local generic bindings installed.+withLocalValidateBindings ::+ Map Name (CTree ValidatorPhase) -> Validator a -> Validator a+withLocalValidateBindings binds =+ local (\env -> env {veLocal = binds `Map.union` veLocal env})++runValidator ::+ Validator () -> CTreeRoot ValidatorPhase -> CustomValidatorResult+runValidator (Validator m) cddl =+ either CustomValidatorFailure (const CustomValidatorSuccess) $+ runReaderT m ValidateEnv {veRoot = cddl, veLocal = Map.empty}
src/Codec/CBOR/Cuddle/CDDL/Resolve.hs view
@@ -65,20 +65,28 @@ #if __GLASGOW_HASKELL__ < 910 import Data.List (foldl') #endif-import Codec.CBOR.Cuddle.CDDL.CBORGenerator (+import Codec.CBOR.Cuddle.CDDL.CTreePhase (CTreePhase, XRule (..))+import Codec.CBOR.Cuddle.CDDL.Custom.Core (RuleTerm)+import Codec.CBOR.Cuddle.CDDL.Custom.Generator ( CBORGen,- CBORValidator, GenPhase,- WrappedTerm, XXCTree (..),+ withLocalGenBindings, )-import Codec.CBOR.Cuddle.CDDL.CTreePhase (CTreePhase, XRule (..))+import Codec.CBOR.Cuddle.CDDL.Custom.Validator (+ TermValidator,+ ValidatorPhase,+ XXCTree (..),+ withLocalValidateBindings,+ ) import Codec.CBOR.Cuddle.IndexMappable (IndexMappable (..)) import Data.List.NonEmpty qualified as NE import Data.Map.Strict qualified as Map import Data.Text qualified as T import GHC.Generics (Generic) import Optics.Core+import Prettyprinter (Pretty (..), encloseSep, layoutCompact)+import Prettyprinter.Render.Text (renderStrict) data ProvidedParameters a = ProvidedParameters { parameters :: [Name]@@ -97,8 +105,8 @@ data CDDLMapEntry = CDDLMapEntry { cmeProvidedParameters :: ProvidedParameters (TypeOrGroup CTreePhase)- , cmeCustomGenerator :: Maybe (CBORGen WrappedTerm)- , cmeCustomValidator :: Maybe CBORValidator+ , cmeCustomGenerator :: Maybe (CBORGen RuleTerm)+ , cmeCustomValidator :: Maybe TermValidator } deriving (Generic) @@ -159,8 +167,8 @@ data instance XXCTree OrReferenced = -- | Reference to another node with possible generic arguments supplied OrRef Name [CTree OrReferenced]- | OGenerator (CBORGen WrappedTerm) (CTree OrReferenced)- | OValidator CBORValidator (CTree OrReferenced)+ | OGenerator (CBORGen RuleTerm) (CTree OrReferenced)+ | OValidator TermValidator (CTree OrReferenced) type data OrReferencedSimple @@ -170,7 +178,7 @@ instance IndexMappable CTree OrReferenced OrReferencedSimple where mapIndex = foldCTree mapExt mapIndex where- mapExt (OrRef n xs) = CTreeE . DGOrRef n $ mapIndex <$> xs+ mapExt (OrRef n xs) = CTreeE $ DGOrRef n (mapIndex <$> xs) mapExt (OGenerator _ x) = mapIndex x mapExt (OValidator _ x) = mapIndex x @@ -178,12 +186,22 @@ mapIndex = foldCTree mapExt mapIndex where mapExt (MRuleRef n) = CTreeE $ GenRef n- mapExt (MGenerator g x) = CTreeE . GenGenerator g $ mapIndex x+ mapExt (MGenerator g x) = CTreeE $ GenGenerator g (mapIndex x) mapExt (MValidator _ x) = mapIndex x instance IndexMappable CTreeRoot MonoReferenced GenPhase where mapIndex (CTreeRoot m) = CTreeRoot $ mapIndex <$> m +instance IndexMappable CTree MonoReferenced ValidatorPhase where+ mapIndex = foldCTree mapExt mapIndex+ where+ mapExt (MRuleRef n) = CTreeE $ VRuleRef n+ mapExt (MGenerator _ x) = mapIndex x+ mapExt (MValidator v x) = CTreeE $ VValidator v (mapIndex x)++instance IndexMappable CTreeRoot MonoReferenced ValidatorPhase where+ mapIndex (CTreeRoot m) = CTreeRoot $ mapIndex <$> m+ -- | Build a CTree incorporating references. -- -- This translation cannot fail.@@ -192,9 +210,7 @@ where toCTreeRule :: CDDLMapEntry -> ProvidedParameters (CTree OrReferenced) toCTreeRule CDDLMapEntry {..} =- fmap- (applyValidator . applyGenerator . toCTreeTOG)- cmeProvidedParameters+ applyValidator . applyGenerator . toCTreeTOG <$> cmeProvidedParameters where applyGenerator = case cmeCustomGenerator of Just g -> CTreeE . OGenerator g@@ -392,15 +408,21 @@ instance Hashable (CTree.Node i) => Hashable (DistRef i) +instance Pretty (XXCTree i) => Pretty (DistRef i) where+ pretty (GenericRef n) = pretty n+ pretty (RuleRef rule []) = pretty rule+ pretty (RuleRef rule args) = pretty rule <> encloseSep "<" ">" "," (pretty <$> args)+ data instance XXCTree DistReferenced = DRef (DistRef DistReferenced)- | DGenerator (CBORGen WrappedTerm) (CTree DistReferenced)- | DValidator CBORValidator (CTree DistReferenced)+ | DGenerator (CBORGen RuleTerm) (CTree DistReferenced)+ | DValidator TermValidator (CTree DistReferenced) type data DistReferencedNoGen newtype instance XXCTree DistReferencedNoGen = DHRef (DistRef DistReferencedNoGen)- deriving (Eq, Hashable)+ deriving (Eq, Hashable, Show)+ deriving newtype (Pretty) resolveRef :: BindingEnv OrReferenced OrReferenced ->@@ -449,8 +471,8 @@ data instance XXCTree MonoReferenced = MRuleRef Name- | MGenerator (CBORGen WrappedTerm) (CTree MonoReferenced)- | MValidator CBORValidator (CTree MonoReferenced)+ | MGenerator (CBORGen RuleTerm) (CTree MonoReferenced)+ | MValidator TermValidator (CTree MonoReferenced) type MonoEnv = BindingEnv DistReferenced MonoReferenced @@ -540,10 +562,11 @@ -- | Synthesize a monomorphic rule definition, returning the name synthMono :: Name -> [CTree DistReferenced] -> MonoM Name synthMono origName args =- let dropGenerator = fmap $ mapIndex @_ @_ @DistReferencedNoGen- fresh =- -- % is not a valid CBOR name, so this should avoid conflict- origName <> "%" <> Name (T.pack (show . hash $ dropGenerator args))+ let dropGenerator = fmap $ mapIndex @_ @DistReferenced @DistReferencedNoGen+ argsName = Name (T.intercalate "," $ renderStrict . layoutCompact . pretty <$> dropGenerator args)+ -- We use % to mark a monomorphised generic rule, '%' is not allowed in+ -- CDDL names, so there should be no conflicts+ fresh = "%" <> origName <> "<" <> argsName <> ">" in do -- Lookup the original name in the global bindings globalBinds <- ask @"global"@@ -573,8 +596,18 @@ case Map.lookup n localBinds of Just node -> pure node Nothing -> throwNR $ UnboundReference n-resolveGenericRef (DGenerator g x) = CTreeE . MGenerator g <$> resolveGenericCTree x-resolveGenericRef (DValidator v x) = CTreeE . MValidator v <$> resolveGenericCTree x+resolveGenericRef (DGenerator g x) = do+ binds <- ask @"local"+ body <- resolveGenericCTree x+ let bindsGen = mapIndex @CTree @MonoReferenced @GenPhase <$> binds+ g' = withLocalGenBindings bindsGen g+ pure . CTreeE $ MGenerator g' body+resolveGenericRef (DValidator v x) = do+ binds <- ask @"local"+ body <- resolveGenericCTree x+ let bindsVal = mapIndex @CTree @MonoReferenced @ValidatorPhase <$> binds+ v' = withLocalValidateBindings bindsVal . v+ pure . CTreeE $ MValidator v' body resolveGenericCTree :: CTree DistReferenced ->
src/Codec/CBOR/Cuddle/Comments.hs view
@@ -10,12 +10,15 @@ CollectComments (..), hasComment, (//-),+ appendComment, (<*!), (!*>), WithComment (..), (!$>),- Comment (..),+ Comment, unComment,+ toComment,+ commentLine, withComment, ) where @@ -31,14 +34,23 @@ import GHC.Generics (Generic (..), K1 (..), M1 (..), U1 (..), V1, (:*:) (..), (:+:) (..)) import Optics.Core (Lens', lens, view, (%~), (&), (.~), (^.)) -newtype Comment = Comment T.Text+newtype Comment = Comment [T.Text] deriving (Eq, Ord, Generic, Show) deriving newtype (Semigroup, Monoid) deriving anyclass (ToExpr, Hashable) unComment :: Comment -> [T.Text]-unComment (Comment c) = T.lines c+unComment (Comment c) = c +toComment :: T.Text -> Comment+toComment = Comment . T.lines++-- | Wrap a single line of text (possibly empty) as a one-line comment.+-- Unlike 'toComment', this does not split on newlines and preserves an empty+-- input as a single empty comment line.+commentLine :: T.Text -> Comment+commentLine t = Comment [t]+ instance Default Comment where def = mempty class HasComment a where@@ -126,19 +138,24 @@ -- arr [0, 1] //- "This is an array with two values" -- ``` (//-) :: HasComment a => a -> Comment -> a-x //- c = x & commentL %~ (<> c)+x //- c = x & commentL %~ (<> Comment ((" " <>) <$> unComment c)) -infixr 0 //-+infixl 1 //- +-- | Raw comment append without adding space or newline. Used by parser+-- combinators where the comment text is already formatted.+appendComment :: HasComment a => a -> Comment -> a+appendComment x c = x & commentL %~ (<> c)+ -- | This operator will parse the values from left to right and then append the -- parsed comment on the right to the parsed value on the left. (<*!) :: (HasComment a, Applicative m) => m a -> m Comment -> m a-(<*!) x c = (//-) <$> x <*> c+(<*!) x c = appendComment <$> x <*> c -- | This operator will parse the values from left to right and then append the -- parsed comment on the left to the parsed value on the right. (!*>) :: (HasComment a, Applicative m) => m Comment -> m a -> m a-(!*>) c x = flip (//-) <$> c <*> x+(!*>) c x = flip appendComment <$> c <*> x data WithComment a = WithComment { unWithComment :: Comment@@ -168,7 +185,7 @@ -- (\x -> LInt x "a") !$> WithComment "b" (1 :: Integer) == Literal (LInt 1) "a\nb" -- ``` (!$>) :: (HasComment b, Functor f) => (a -> b) -> f (WithComment a) -> f b-f !$> wc = fmap (\(WithComment c x) -> f x //- c) wc+f !$> wc = fmap (\(WithComment c x) -> appendComment (f x) c) wc instance HasComment a => HasComment (NonEmpty a) where commentL = lens (\(x :| _) -> x ^. commentL) (\(x :| xs) y -> (x & commentL .~ y) :| xs)@@ -177,4 +194,4 @@ commentL = lens id const instance IsString Comment where- fromString s = Comment $ T.pack s+ fromString = toComment . T.pack
src/Codec/CBOR/Cuddle/Huddle.hs view
@@ -91,8 +91,6 @@ callToDef, -- * Generators- withAntiGen,- withGenerator, withCBORGen, -- * Validators@@ -109,25 +107,22 @@ ) where -import Codec.CBOR.Cuddle.CDDL (CDDL, GenericParameter (..), HasName (..), Name (..), XRule)-import Codec.CBOR.Cuddle.CDDL qualified as C-import Codec.CBOR.Cuddle.CDDL.CBORGenerator (- CBORGen (..),- CBORValidator (..),- CustomValidatorResult,- GenEnv (..),- GenPhase,- HasGenerator (..),- HasValidator (..),- WrappedTerm,+import Codec.CBOR.Cuddle.CDDL (+ CDDL,+ GRef (..),+ GenericParameter (..),+ HasName (..),+ Name (..),+ XRule, )-import Codec.CBOR.Cuddle.CDDL.CTree (CTreeRoot)+import Codec.CBOR.Cuddle.CDDL qualified as C import Codec.CBOR.Cuddle.CDDL.CtlOp qualified as CtlOp-import Codec.CBOR.Cuddle.Comments (Comment (..), HasComment (..))+import Codec.CBOR.Cuddle.CDDL.Custom.Core (RuleTerm)+import Codec.CBOR.Cuddle.CDDL.Custom.Generator (CBORGen, HasGenerator (..))+import Codec.CBOR.Cuddle.CDDL.Custom.Validator (HasValidator (..), TermValidator)+import Codec.CBOR.Cuddle.Comments (Comment, HasComment (..)) import Codec.CBOR.Cuddle.Comments qualified as C-import Codec.CBOR.Term (Term) import Control.Monad (when)-import Control.Monad.Reader (ReaderT (..)) import Control.Monad.State (MonadState (get), State, execState, modify) import Data.ByteString (ByteString) import Data.ByteString.Base16 qualified as Base16@@ -148,9 +143,6 @@ import GHC.Generics (Generic) import Optics.Core (lens, view, (%), (%~), (&)) import Optics.Core qualified as L-import Test.AntiGen (AntiGen)-import Test.QuickCheck.Gen (Gen)-import Test.QuickCheck.GenT (MonadGen (liftGen)) import Prelude hiding ((/)) type data HuddleStage@@ -163,8 +155,8 @@ data instance C.XRule HuddleStage = HuddleXRule { hxrComment :: C.Comment- , hxrGenerator :: Maybe (CBORGen WrappedTerm)- , hxrValidator :: Maybe CBORValidator+ , hxrGenerator :: Maybe (CBORGen RuleTerm)+ , hxrValidator :: Maybe TermValidator } deriving (Generic) @@ -1005,9 +997,6 @@ -- Generics -------------------------------------------------------------------------------- -newtype GRef = GRef T.Text- deriving (Show)- freshName :: Int -> GRef freshName ix = GRef $@@ -1377,23 +1366,10 @@ C.GenericParameters $ fmap (\(GRef t) -> GenericParameter (C.Name t) $ HuddleXTerm mempty) (args gr) --- | Use a custom `QuickCheck` generator to generate the term. Will override--- the generator passed via `withAntiGen`-withGenerator :: HasGenerator a => (CTreeRoot GenPhase -> Gen WrappedTerm) -> a -> a-withGenerator f = L.set generatorL (Just . CBORGen . ReaderT $ \GenEnv {geRoot} -> liftGen $ f geRoot)-{-# DEPRECATED withGenerator "Use withCBORGen instead" #-}---- | Use a custom `AntiGen` generator to generate the term. Will override--- the custom generator passed via `withGenerator`. The advantage of using--- `AntiGen` generator is that it can also be used to generate negative examples.-withAntiGen :: HasGenerator a => (CTreeRoot GenPhase -> AntiGen WrappedTerm) -> a -> a-withAntiGen f = L.set generatorL (Just . CBORGen . ReaderT $ \GenEnv {geRoot} -> f geRoot)-{-# DEPRECATED withAntiGen "Use withCBORGen instead" #-}- -- | Use a custom `CBORGen` generator to generate the term. Will override -- the custom generator passed via `withGenerator`.-withCBORGen :: HasGenerator a => CBORGen WrappedTerm -> a -> a-withCBORGen gen = L.set generatorL (Just gen)+withCBORGen :: HasGenerator a => CBORGen RuleTerm -> a -> a+withCBORGen gen = L.set generatorL $ Just gen -withValidator :: HasValidator a => (Term -> CustomValidatorResult) -> a -> a-withValidator p = L.set validatorL . Just $ CBORValidator p+withValidator :: HasValidator a => TermValidator -> a -> a+withValidator p = L.set validatorL $ Just p
src/Codec/CBOR/Cuddle/IndexMappable.hs view
@@ -201,7 +201,7 @@ where mapIndex (GrpChoice gs e) = GrpChoice (mapIndex <$> gs) $ mapIndex e --- ParserStage -> PrettyStage+-- ParserStage ~ PrettyStage instance IndexMappable XCddl ParserStage PrettyStage where mapIndex (ParserXCddl c) = PrettyXCddl c@@ -277,7 +277,7 @@ instance IndexMappable XRule HuddleStage PrettyStage where mapIndex (HuddleXRule c _ _) = PrettyXRule c --- ParserStage -> ParserStage+-- ParserStage ~ ParserStage instance IndexMappable XCddl ParserStage ParserStage
src/Codec/CBOR/Cuddle/Parser.hs view
@@ -13,9 +13,9 @@ Comment, HasComment (..), WithComment (..),+ appendComment, withComment, (!*>),- (//-), (<*!), ) import Codec.CBOR.Cuddle.Parser.Lexer (@@ -75,7 +75,10 @@ initialRule <- pRule cddlTail <- many $ pTopLevel <* C.space eof- $> CDDL (initialRule //- fold initialRuleComment) cddlTail (ParserXXTopLevel <$> initialComments)+ $> CDDL+ (appendComment initialRule (fold initialRuleComment))+ cddlTail+ (ParserXXTopLevel <$> initialComments) pTopLevel :: Parser (TopLevel ParserStage) pTopLevel = try tlRule <|> tlComment@@ -83,7 +86,7 @@ tlRule = do mCmt <- optional pCommentBlock rule <- pRule- pure . TopLevelRule $ rule //- fold mCmt+ pure . TopLevelRule $ appendComment rule (fold mCmt) tlComment = XXTopLevel . ParserXXTopLevel <$> pCommentBlock pRule :: Parser (Rule ParserStage)
src/Codec/CBOR/Cuddle/Parser/Lexer.hs view
@@ -10,7 +10,7 @@ pCommentBlock, ) where -import Codec.CBOR.Cuddle.Comments (Comment (..))+import Codec.CBOR.Cuddle.Comments (Comment, commentLine) import Control.Applicative.Combinators.NonEmpty qualified as NE import Data.Foldable1 (Foldable1 (..)) import Data.Text (Text)@@ -35,7 +35,7 @@ pComment :: Parser Comment pComment =- Comment . (<> "\n") <$> label "comment" (char ';' *> takeWhileP Nothing validChar <* eol)+ commentLine <$> label "comment" (char ';' *> takeWhileP Nothing validChar <* eol) where validChar = charInRange '\x20' '\x7e' ||| charInRange '\x80' '\x10fffd'
src/Codec/CBOR/Cuddle/Pretty.hs view
@@ -4,6 +4,7 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TypeData #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE ViewPatterns #-} {-# OPTIONS_GHC -Wno-orphans #-} @@ -19,9 +20,10 @@ ) where import Codec.CBOR.Cuddle.CDDL-import Codec.CBOR.Cuddle.CDDL.CTree (PTerm (..))+import Codec.CBOR.Cuddle.CDDL.CTree (CTree, PTerm (..), XXCTree)+import Codec.CBOR.Cuddle.CDDL.CTree qualified as CT import Codec.CBOR.Cuddle.CDDL.CtlOp (CtlOp)-import Codec.CBOR.Cuddle.Comments (CollectComments (..), Comment (..), HasComment (..), unComment)+import Codec.CBOR.Cuddle.Comments (CollectComments (..), Comment, HasComment (..), unComment) import Codec.CBOR.Cuddle.Pretty.Columnar ( Cell (..), CellAlign (..),@@ -97,8 +99,9 @@ | otherwise = space <> prettyCommentNoBreak cmt instance Pretty Comment where- pretty (Comment "") = mempty- pretty c = prettyCommentNoBreak c <> hardline+ pretty c+ | c == mempty = mempty+ | otherwise = prettyCommentNoBreak c <> hardline type0Def :: Type0 PrettyStage -> Doc ann type0Def t = nest 2 $ line' <> pretty t@@ -279,3 +282,26 @@ renderCDDL :: LayoutOptions -> CDDL PrettyStage -> Text renderCDDL opts = PT.renderStrict . removeTrailingWhitespace . layoutPretty opts . pretty++instance Pretty (XXCTree p) => Pretty (CTree p) where+ pretty = \case+ CT.Literal v -> pretty v+ CT.Postlude v -> pretty v+ CT.Range lo hi ClOpen -> pretty lo <+> "..." <+> pretty hi+ CT.Range lo hi Closed -> pretty lo <+> ".." <+> pretty hi+ CT.KV k v _ -> pretty k <+> "==>" <+> pretty v+ CT.CTreeE x -> pretty x+ CT.Occur v oi ->+ case oi of+ OIOptional -> "?" <+> pretty v+ OIZeroOrMore -> "*" <+> pretty v+ OIOneOrMore -> "+" <+> pretty v+ OIBounded lo hi -> foldMap pretty lo <> "*" <> foldMap pretty hi <+> pretty v+ CT.Map m -> encloseSep "{" "}" "," $ pretty <$> m+ CT.Array e -> list $ pretty <$> e+ CT.Choice c -> group . vsep . punctuate "//" $ pretty <$> toList c+ CT.Group g -> tupled $ pretty <$> g+ CT.Control op tgt ctl -> pretty tgt <+> pretty op <+> pretty ctl+ CT.Enum e -> "&" <> pretty e+ CT.Unwrap x -> "~" <> pretty x+ CT.Tag t x -> "#6." <> pretty t <> "(" <> pretty x <> ")"
test/Test/Codec/CBOR/Cuddle/CDDL/Examples/Huddle.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedLists #-} {-# LANGUAGE OverloadedStrings #-} @@ -27,10 +28,13 @@ mapNestedValueExample, deeplyNestedRefExample, taggedUintExample,+ tagRangeExample, ) where +import Codec.CBOR.Cuddle.CBOR.Gen (generateFromGRef)+import Codec.CBOR.Cuddle.CBOR.Validator (validateFromGRef) import Codec.CBOR.Cuddle.CDDL (Name)-import Codec.CBOR.Cuddle.CDDL.CBORGenerator (WrappedTerm (..))+import Codec.CBOR.Cuddle.CDDL.Custom.Core (RuleTerm (..)) import Codec.CBOR.Cuddle.Huddle ( CanQuantify (..), Huddle,@@ -40,12 +44,14 @@ a, arr, asKey,+ binding, collectFrom, idx, mp, opt, tag, withCBORGen,+ withValidator, (...), (=:=), (==>),@@ -53,7 +59,7 @@ import Codec.CBOR.Cuddle.Huddle qualified as H import Codec.CBOR.Term qualified as C import Data.Word (Word64)-import Test.QuickCheck.GenT (MonadGen (..))+import Test.QuickCheck.GenT (MonadGen (..), frequency) huddleRangeArray :: Huddle huddleRangeArray =@@ -108,7 +114,7 @@ simpleRule n = n =:= arr [1, 2, 3] customGenRule :: Name -> Rule-customGenRule = withCBORGen (S . C.TInt <$> choose (4, 6)) . simpleRule+customGenRule = withCBORGen (SingleTerm . C.TInt <$> choose (4, 6)) . simpleRule customGenExample :: Huddle customGenExample =@@ -313,3 +319,38 @@ collectFrom [ HIRule $ "root" =:= tag 42 VBytes ]++-- | @foo<a> = #6.1280(a) / #6.1400(a)@ with a custom generator that picks+-- any tag in @1280..1400@ (broader than what the schema literally allows)+-- and a custom validator that accepts the same range. Exercised at two+-- different generic instantiations to make sure the bound type is+-- resolved correctly per call.+tagRangeExample :: Huddle+tagRangeExample =+ collectFrom+ [ HIRule $+ "root" =:= arr [a (fooTagRange VUInt), a (fooTagRange VNInt)]+ ]+ where+ fooTagRange :: H.IsType0 t0 => t0 -> H.GRuleCall+ fooTagRange = binding $ \x ->+ withCBORGen (generator x)+ . withValidator (validator x)+ $ "foo" =:= tag 1280 x H./ tag 1400 x+ where+ generator x = do+ tagN <-+ frequency+ [ (1, pure 1280)+ , (1, pure 1400)+ , (4, choose (1281, 1399))+ ]+ generateFromGRef x >>= \case+ SingleTerm inner -> pure $ SingleTerm (C.TTagged tagN inner)+ _ -> error "tagRangeExample: generic argument must be a single term"++ validator x = \case+ SingleTerm (C.TTagged t inner)+ | t >= 1280 && t <= 1400 -> validateFromGRef x inner+ | otherwise -> fail $ "Tag out of range 1280..1400: " <> show t+ wt -> fail $ "Expected a tagged term, got: " <> show wt
test/Test/Codec/CBOR/Cuddle/CDDL/Gen.hs view
@@ -8,7 +8,7 @@ import Codec.CBOR.Cuddle.CDDL import Codec.CBOR.Cuddle.CDDL.CtlOp-import Codec.CBOR.Cuddle.Comments (Comment (..))+import Codec.CBOR.Cuddle.Comments (Comment, toComment) import Codec.CBOR.Cuddle.Parser (ParserStage, XTerm (..)) import Codec.CBOR.Cuddle.Pretty (PrettyStage, XRule (..), XTerm (..), XXTopLevel (..)) import Data.ByteString (ByteString)@@ -48,7 +48,7 @@ shrink = fmap BS.pack . shrink . BS.unpack instance Arbitrary Comment where- arbitrary = Comment <$> arbitrary+ arbitrary = toComment <$> arbitrary shrink = genericShrink nameFstChars :: [Char]
test/Test/Codec/CBOR/Cuddle/CDDL/GeneratorSpec.hs view
@@ -7,8 +7,8 @@ import Codec.CBOR.Cuddle.CBOR.Gen (GenPhase, generateFromName) import Codec.CBOR.Cuddle.CBOR.Validator (validateCBOR) import Codec.CBOR.Cuddle.CDDL (Name)-import Codec.CBOR.Cuddle.CDDL.CBORGenerator (GenEnv (..), runCBORGen) import Codec.CBOR.Cuddle.CDDL.CTree (CTreeRoot (..))+import Codec.CBOR.Cuddle.CDDL.Custom.Generator (GenConfig (..), runCBORGen) import Codec.CBOR.Cuddle.CDDL.Resolve (MonoReferenced, MonoSimple, fullResolveCDDL) import Codec.CBOR.Cuddle.Huddle (Huddle, toCDDL) import Codec.CBOR.Cuddle.IndexMappable (IndexMappable (..), mapCDDLDropExt)@@ -30,6 +30,7 @@ refTermExample, sizeBytesExample, sizeTextExample,+ tagRangeExample, taggedUintExample, ) import Test.Codec.CBOR.Cuddle.CDDL.Validator (expectInvalid, genAndValidateRule)@@ -40,12 +41,12 @@ import Text.Pretty.Simple (pShow) generateCDDL :: CTreeRoot GenPhase -> Gen Term-generateCDDL cddl = runAntiGen . runCBORGen env $ generateFromName "root"+generateCDDL cddl = runAntiGen . runCBORGen cfg $ generateFromName "root" where- env =- GenEnv- { geRoot = cddl- , geTwiddle = True+ cfg =+ GenConfig+ { gcRoot = cddl+ , gcTwiddle = True } tryResolveHuddle :: HasCallStack => Huddle -> SpecM () (CTreeRoot MonoReferenced)@@ -57,12 +58,12 @@ expectZapInvalidates :: CTreeRoot MonoReferenced -> Name -> Property expectZapInvalidates cddl name = property $ do let- env =- GenEnv- { geRoot = mapIndex cddl- , geTwiddle = True+ cfg =+ GenConfig+ { gcRoot = mapIndex cddl+ , gcTwiddle = True }- res@ZapResult {zrValue} <- zapAntiGenResult 1 . runCBORGen env $ generateFromName name+ res@ZapResult {zrValue} <- zapAntiGenResult 1 . runCBORGen cfg $ generateFromName name let bs = toStrictByteString $ encodeTerm zrValue validationRes = validateCBOR bs name $ mapIndex cddl@@ -99,6 +100,7 @@ genAndValidateHuddle "sizeBytes" sizeBytesExample genAndValidateHuddle "rangeList" rangeListExample genAndValidateHuddle "rangeMap" rangeMapExample+ genAndValidateHuddle "tagRange" tagRangeExample xdescribe "Generator cannot reliably produce unique keys for maps" $ do genAndValidateHuddle "optionalMapExample" optionalMapExample @@ -139,17 +141,31 @@ TBytes "\x01\x02\x03\xff" -> True TBytesI "\x01\x02\x03\xff" -> True _ -> False+ tagRangeExampleCddl <- tryResolveHuddle tagRangeExample+ prop "tagRange generator covers edges and middle" $ do+ res <- generateCDDL $ mapIndex tagRangeExampleCddl+ let tags = case res of+ TList xs -> [t | TTagged t _ <- xs]+ TListI xs -> [t | TTagged t _ <- xs]+ _ -> []+ classifyTag t p =+ classify (t == 1280 || t == 1400) "edge tag (1280 or 1400)" $+ classify (t > 1280 && t < 1400) "middle tag (1281..1399)" p+ base =+ counterexample ("tags: " <> show tags) $+ all (\t -> t >= 1280 && t <= 1400) tags+ pure $ foldr classifyTag (property base) tags describe "Tagged bytes zapping" $ do taggedBytesCddl <- tryResolveHuddle taggedUintExample- let env =- GenEnv- { geRoot = mapIndex taggedBytesCddl- , geTwiddle = True+ let cfg =+ GenConfig+ { gcRoot = mapIndex taggedBytesCddl+ , gcTwiddle = True } prop "labels zapped result" $ do ZapResult {zrValue} <-- zapAntiGenResult 1 . runCBORGen env $ generateFromName "root"+ zapAntiGenResult 1 . runCBORGen cfg $ generateFromName "root" let isBytes TBytes {} = True isBytes TBytesI {} = True
test/Test/Codec/CBOR/Cuddle/CDDL/Pretty/Golden.hs view
@@ -1,11 +1,16 @@+{-# LANGUAGE OverloadedLists #-} {-# LANGUAGE OverloadedStrings #-} module Test.Codec.CBOR.Cuddle.CDDL.Pretty.Golden (spec) where +import Codec.CBOR.Cuddle.Comments ((//-))+import Codec.CBOR.Cuddle.Huddle (HuddleItem (..), a, (=:=))+import Codec.CBOR.Cuddle.Huddle qualified as H import Codec.CBOR.Cuddle.IndexMappable (mapIndex) import Codec.CBOR.Cuddle.Parser (pCDDL) import Codec.CBOR.Cuddle.Pretty (PrettyStage, renderCDDL) import Control.Monad ((<=<))+import Data.Text (Text) import Data.Text.IO qualified as T import Paths_cuddle (getDataFileName) import Prettyprinter (defaultLayoutOptions)@@ -15,6 +20,18 @@ import Text.Megaparsec (parse) import Text.Megaparsec.Error (errorBundlePretty) +mkGolden :: String -> Text -> Golden Text+mkGolden testName rendered =+ Golden+ { goldenFile = "golden" </> "pretty" </> testName <> ".txt"+ , readFromFile = T.readFile <=< getDataFileName+ , writeToFile = \fp txt -> getDataFileName fp >>= (`T.writeFile` txt)+ , actualFile = Nothing+ , output = rendered+ , encodePretty = show+ , failFirstTime = False+ }+ prettyPrintGolden :: String -> FilePath -> Spec prettyPrintGolden testName cddlPath = do cddl <- runIO $ do@@ -24,16 +41,19 @@ Left err -> fail $ "Failed to parse CDDL:\n" <> errorBundlePretty err Right x -> pure x it testName $- Golden- { goldenFile = "golden" </> "pretty" </> testName <> ".txt"- , readFromFile = T.readFile <=< getDataFileName- , writeToFile = \fp txt -> getDataFileName fp >>= (`T.writeFile` txt)- , actualFile = Nothing- , output = renderCDDL defaultLayoutOptions $ mapIndex @_ @_ @PrettyStage cddl- , encodePretty = show- , failFirstTime = False- }+ mkGolden testName $+ renderCDDL defaultLayoutOptions $+ mapIndex @_ @_ @PrettyStage cddl +huddleGolden :: String -> [HuddleItem] -> Spec+huddleGolden testName items =+ it testName $+ mkGolden testName $+ renderCDDL defaultLayoutOptions $+ mapIndex @_ @_ @PrettyStage $+ H.toCDDLNoRoot $+ H.collectFrom items+ spec :: Spec spec = describe "golden" $ do prettyPrintGolden "basic_assign" "cddl/basic_assign.cddl"@@ -41,3 +61,51 @@ prettyPrintGolden "costmdls_min" "cddl/costmdls_min.cddl" prettyPrintGolden "issue80-min" "cddl/issue80-min.cddl" prettyPrintGolden "conway" "cddl/conway.cddl"+ describe "(//-) on a term" $ do+ huddleGolden+ "term_comment_rule"+ [HIRule $ "a" =:= (H.bool True //- "trailing")]+ huddleGolden+ "term_comment_appends_to_existing"+ [HIRule $ H.comment "existing" $ "a" =:= (H.bool True //- "trailing")]+ huddleGolden+ "term_comment_chained"+ [HIRule $ "a" =:= (H.bool True //- "first" //- "second")]+ huddleGolden+ "term_comment_empty"+ [HIRule $ "a" =:= (H.bool True //- "")]+ huddleGolden+ "term_comment_multiline"+ [HIRule $ "a" =:= (H.bool True //- "line one\nline two")]+ huddleGolden+ "term_comment_array_entries"+ [ HIRule $+ "triple"+ =:= H.arr+ [ a H.VUInt //- "first element"+ , a H.VText //- "second element"+ , a (H.bool True) //- "third element"+ ]+ ]+ describe "(//-) on a rule" $ do+ huddleGolden+ "rule_comment_rule"+ [HIRule $ "a" =:= H.bool True //- "trailing"]+ huddleGolden+ "rule_comment_appends_to_existing"+ [HIRule $ H.comment "existing" ("a" =:= H.bool True) //- "trailing"]+ huddleGolden+ "rule_comment_chained"+ [HIRule $ "a" =:= H.bool True //- "first" //- "second"]+ huddleGolden+ "rule_comment_empty"+ [HIRule $ "a" =:= H.bool True //- ""]+ huddleGolden+ "rule_comment_multiline"+ [HIRule $ "a" =:= H.bool True //- "line one\nline two"]+ huddleGolden+ "rule_comment_multi_rule"+ [ HIRule $ "port" =:= H.VUInt //- "the listening port"+ , HIRule $ "host" =:= H.VText //- "the host name"+ , HIRule $ "secure" =:= H.bool True //- "TLS only"+ ]
test/Test/Codec/CBOR/Cuddle/CDDL/Validator.hs view
@@ -22,9 +22,11 @@ prettyValidationTrace, ) import Codec.CBOR.Cuddle.CDDL (Name (..))-import Codec.CBOR.Cuddle.CDDL.CBORGenerator (CustomValidatorResult (..), GenEnv (..), runCBORGen) import Codec.CBOR.Cuddle.CDDL.CTree (CTreeRoot (..)) import Codec.CBOR.Cuddle.CDDL.CTree qualified as CTree+import Codec.CBOR.Cuddle.CDDL.Custom.Core (RuleTerm (..))+import Codec.CBOR.Cuddle.CDDL.Custom.Generator (GenConfig (..), runCBORGen)+import Codec.CBOR.Cuddle.CDDL.Custom.Validator (TermValidator) import Codec.CBOR.Cuddle.CDDL.Postlude (appendPostlude) import Codec.CBOR.Cuddle.CDDL.Resolve (MonoReferenced, fullResolveCDDL) import Codec.CBOR.Cuddle.Huddle (@@ -99,12 +101,12 @@ genAndValidateRule description name resolvedCddl = prop description $ do let- genEnv =- GenEnv- { geRoot = mapIndex resolvedCddl- , geTwiddle = True+ genCfg =+ GenConfig+ { gcRoot = mapIndex resolvedCddl+ , gcTwiddle = True }- cborTerm <- runAntiGen . runCBORGen genEnv $ generateFromName name+ cborTerm <- runAntiGen . runCBORGen genCfg $ generateFromName name let generatedCbor = toStrictByteString $ encodeTerm cborTerm res = validateCBOR generatedCbor name (mapIndex resolvedCddl)@@ -281,15 +283,15 @@ <> renderStrict (layoutPretty defaultLayoutOptions $ prettyValidationTrace defaultTraceOptions t) expectInvalid _ = pure () -stringValidator :: Term -> CustomValidatorResult-stringValidator (TString _) = CustomValidatorSuccess-stringValidator (TStringI _) = CustomValidatorSuccess-stringValidator t = CustomValidatorFailure $ "Expected a string, got\n" <> T.pack (show t)+stringValidator :: TermValidator+stringValidator (SingleTerm (TString _)) = pure ()+stringValidator (SingleTerm (TStringI _)) = pure ()+stringValidator t = fail $ "Expected a string, got\n" <> show t -bytesValidator :: Term -> CustomValidatorResult-bytesValidator (TBytes _) = CustomValidatorSuccess-bytesValidator (TBytesI _) = CustomValidatorSuccess-bytesValidator t = CustomValidatorFailure $ "Expected bytes, got\n" <> T.pack (show t)+bytesValidator :: TermValidator+bytesValidator (SingleTerm (TBytes _)) = pure ()+bytesValidator (SingleTerm (TBytesI _)) = pure ()+bytesValidator t = fail $ "Expected bytes, got\n" <> show t spec :: Spec spec = describe "Validator" $ do