-- |
-- SPDX-License-Identifier: BSD-3-Clause
--
-- Representation of the "type" of a schema.
module Swarm.Doc.Schema.SchemaType where

import Control.Applicative ((<|>))
import Data.Aeson
import Data.Text (Text)
import Data.Text qualified as T
import System.FilePath (takeBaseName)

newtype SingleOrList a = SingleOrList
  { forall a. SingleOrList a -> [a]
getList :: [a]
  }
  deriving (SingleOrList a -> SingleOrList a -> Bool
forall a. Eq a => SingleOrList a -> SingleOrList a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SingleOrList a -> SingleOrList a -> Bool
$c/= :: forall a. Eq a => SingleOrList a -> SingleOrList a -> Bool
== :: SingleOrList a -> SingleOrList a -> Bool
$c== :: forall a. Eq a => SingleOrList a -> SingleOrList a -> Bool
Eq, SingleOrList a -> SingleOrList a -> Bool
SingleOrList a -> SingleOrList a -> Ordering
SingleOrList a -> SingleOrList a -> SingleOrList a
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall {a}. Ord a => Eq (SingleOrList a)
forall a. Ord a => SingleOrList a -> SingleOrList a -> Bool
forall a. Ord a => SingleOrList a -> SingleOrList a -> Ordering
forall a.
Ord a =>
SingleOrList a -> SingleOrList a -> SingleOrList a
min :: SingleOrList a -> SingleOrList a -> SingleOrList a
$cmin :: forall a.
Ord a =>
SingleOrList a -> SingleOrList a -> SingleOrList a
max :: SingleOrList a -> SingleOrList a -> SingleOrList a
$cmax :: forall a.
Ord a =>
SingleOrList a -> SingleOrList a -> SingleOrList a
>= :: SingleOrList a -> SingleOrList a -> Bool
$c>= :: forall a. Ord a => SingleOrList a -> SingleOrList a -> Bool
> :: SingleOrList a -> SingleOrList a -> Bool
$c> :: forall a. Ord a => SingleOrList a -> SingleOrList a -> Bool
<= :: SingleOrList a -> SingleOrList a -> Bool
$c<= :: forall a. Ord a => SingleOrList a -> SingleOrList a -> Bool
< :: SingleOrList a -> SingleOrList a -> Bool
$c< :: forall a. Ord a => SingleOrList a -> SingleOrList a -> Bool
compare :: SingleOrList a -> SingleOrList a -> Ordering
$ccompare :: forall a. Ord a => SingleOrList a -> SingleOrList a -> Ordering
Ord, Int -> SingleOrList a -> ShowS
forall a. Show a => Int -> SingleOrList a -> ShowS
forall a. Show a => [SingleOrList a] -> ShowS
forall a. Show a => SingleOrList a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SingleOrList a] -> ShowS
$cshowList :: forall a. Show a => [SingleOrList a] -> ShowS
show :: SingleOrList a -> String
$cshow :: forall a. Show a => SingleOrList a -> String
showsPrec :: Int -> SingleOrList a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> SingleOrList a -> ShowS
Show)

instance (FromJSON a) => FromJSON (SingleOrList a) where
  parseJSON :: Value -> Parser (SingleOrList a)
parseJSON Value
x =
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. [a] -> SingleOrList a
SingleOrList forall a b. (a -> b) -> a -> b
$
      forall (f :: * -> *) a. Applicative f => a -> f a
pure forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. FromJSON a => Value -> Parser a
parseJSON Value
x forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall a. FromJSON a => Value -> Parser a
parseJSON Value
x

data SchemaType
  = -- | A basic built-in type
    Simple (SingleOrList Text)
  | -- | Any one of multiple possible schema types
    Alternatives [SchemaType]
  | -- | A reference to a schema defined elsewhere
    Reference SchemaIdReference
  | -- | Members of a list, all of the given schema type
    ListOf SchemaType
  deriving (SchemaType -> SchemaType -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SchemaType -> SchemaType -> Bool
$c/= :: SchemaType -> SchemaType -> Bool
== :: SchemaType -> SchemaType -> Bool
$c== :: SchemaType -> SchemaType -> Bool
Eq, Eq SchemaType
SchemaType -> SchemaType -> Bool
SchemaType -> SchemaType -> Ordering
SchemaType -> SchemaType -> SchemaType
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: SchemaType -> SchemaType -> SchemaType
$cmin :: SchemaType -> SchemaType -> SchemaType
max :: SchemaType -> SchemaType -> SchemaType
$cmax :: SchemaType -> SchemaType -> SchemaType
>= :: SchemaType -> SchemaType -> Bool
$c>= :: SchemaType -> SchemaType -> Bool
> :: SchemaType -> SchemaType -> Bool
$c> :: SchemaType -> SchemaType -> Bool
<= :: SchemaType -> SchemaType -> Bool
$c<= :: SchemaType -> SchemaType -> Bool
< :: SchemaType -> SchemaType -> Bool
$c< :: SchemaType -> SchemaType -> Bool
compare :: SchemaType -> SchemaType -> Ordering
$ccompare :: SchemaType -> SchemaType -> Ordering
Ord, Int -> SchemaType -> ShowS
[SchemaType] -> ShowS
SchemaType -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SchemaType] -> ShowS
$cshowList :: [SchemaType] -> ShowS
show :: SchemaType -> String
$cshow :: SchemaType -> String
showsPrec :: Int -> SchemaType -> ShowS
$cshowsPrec :: Int -> SchemaType -> ShowS
Show)

newtype SchemaIdReference = SchemaIdReference Text
  deriving (SchemaIdReference -> SchemaIdReference -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SchemaIdReference -> SchemaIdReference -> Bool
$c/= :: SchemaIdReference -> SchemaIdReference -> Bool
== :: SchemaIdReference -> SchemaIdReference -> Bool
$c== :: SchemaIdReference -> SchemaIdReference -> Bool
Eq, Eq SchemaIdReference
SchemaIdReference -> SchemaIdReference -> Bool
SchemaIdReference -> SchemaIdReference -> Ordering
SchemaIdReference -> SchemaIdReference -> SchemaIdReference
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: SchemaIdReference -> SchemaIdReference -> SchemaIdReference
$cmin :: SchemaIdReference -> SchemaIdReference -> SchemaIdReference
max :: SchemaIdReference -> SchemaIdReference -> SchemaIdReference
$cmax :: SchemaIdReference -> SchemaIdReference -> SchemaIdReference
>= :: SchemaIdReference -> SchemaIdReference -> Bool
$c>= :: SchemaIdReference -> SchemaIdReference -> Bool
> :: SchemaIdReference -> SchemaIdReference -> Bool
$c> :: SchemaIdReference -> SchemaIdReference -> Bool
<= :: SchemaIdReference -> SchemaIdReference -> Bool
$c<= :: SchemaIdReference -> SchemaIdReference -> Bool
< :: SchemaIdReference -> SchemaIdReference -> Bool
$c< :: SchemaIdReference -> SchemaIdReference -> Bool
compare :: SchemaIdReference -> SchemaIdReference -> Ordering
$ccompare :: SchemaIdReference -> SchemaIdReference -> Ordering
Ord, Int -> SchemaIdReference -> ShowS
[SchemaIdReference] -> ShowS
SchemaIdReference -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SchemaIdReference] -> ShowS
$cshowList :: [SchemaIdReference] -> ShowS
show :: SchemaIdReference -> String
$cshow :: SchemaIdReference -> String
showsPrec :: Int -> SchemaIdReference -> ShowS
$cshowsPrec :: Int -> SchemaIdReference -> ShowS
Show)

fromFilePath :: FilePath -> SchemaIdReference
fromFilePath :: String -> SchemaIdReference
fromFilePath = Text -> SchemaIdReference
SchemaIdReference forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
T.pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS
takeBaseName