{-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE FlexibleContexts #-} module Data.Medea.Parser.Spec.Object ( Specification (..), parseSpecification, ) where import Control.Monad (when) import Data.Functor (($>)) import Data.Maybe (isJust) import Data.Medea.Parser.Primitive ( Identifier, ReservedIdentifier (..), parseIdentifier, parseKeyVal, parseLine, parseReserved, ) import qualified Data.Medea.Parser.Spec.Property as Property import Data.Medea.Parser.Types (MedeaParser, ParseError (..)) import Data.Vector (Vector) import qualified Data.Vector as V import Text.Megaparsec ( MonadParsec (..), customFailure, many, option, try, ) data Specification = Specification { properties :: {-# UNPACK #-} !(Vector Property.Specification), additionalAllowed :: !Bool, additionalSchema :: !(Maybe Identifier) } deriving stock (Eq) parseSpecification :: MedeaParser Specification parseSpecification = do _ <- parseLine 4 (parseReserved RProperties) props <- parseProperties additionalAllowed' <- parseAdditionalAllowed additionalSchema' <- parseAdditionalSchema when (not additionalAllowed' && isJust additionalSchema') $ customFailure ConflictingSpecRequirements pure $ Specification props additionalAllowed' additionalSchema' parseProperties :: MedeaParser (Vector Property.Specification) parseProperties = V.fromList <$> many (try Property.parseSpecification) parseAdditionalAllowed :: MedeaParser Bool parseAdditionalAllowed = option False . try . parseLine 8 $ parseReserved RAdditionalPropertiesAllowed $> True parseAdditionalSchema :: MedeaParser (Maybe Identifier) parseAdditionalSchema = option Nothing . fmap Just . try . parseLine 8 $ parseKeyVal RAdditionalPropertySchema parseIdentifier