{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module Ecluse.Core.Wire (
WireVocab (..),
renderWire,
parseWire,
) where
import Data.List.NonEmpty qualified as NE
import Data.Text qualified as T
class WireVocab a where
wireKind :: Text
wireTable :: NonEmpty (a, Text)
renderWire :: forall a. (Eq a, WireVocab a) => a -> Text
renderWire :: forall a. (Eq a, WireVocab a) => a -> Text
renderWire a
value =
Text -> ((a, Text) -> Text) -> Maybe (a, Text) -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe ((a, Text) -> Text
forall a b. (a, b) -> b
snd (NonEmpty (a, Text) -> (a, Text)
forall a. NonEmpty a -> a
NE.head NonEmpty (a, Text)
table)) (a, Text) -> Text
forall a b. (a, b) -> b
snd (((a, Text) -> Bool) -> NonEmpty (a, Text) -> Maybe (a, Text)
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find ((a
value a -> a -> Bool
forall a. Eq a => a -> a -> Bool
==) (a -> Bool) -> ((a, Text) -> a) -> (a, Text) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a, Text) -> a
forall a b. (a, b) -> a
fst) NonEmpty (a, Text)
table)
where
table :: NonEmpty (a, Text)
table = forall a. WireVocab a => NonEmpty (a, Text)
wireTable @a
parseWire :: forall a. (WireVocab a) => Text -> Either Text a
parseWire :: forall a. WireVocab a => Text -> Either Text a
parseWire Text
raw =
case ((a, Text) -> Bool) -> NonEmpty (a, Text) -> Maybe (a, Text)
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find ((Text
raw Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
==) (Text -> Bool) -> ((a, Text) -> Text) -> (a, Text) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a, Text) -> Text
forall a b. (a, b) -> b
snd) NonEmpty (a, Text)
table of
Just (a
value, Text
_name) -> a -> Either Text a
forall a b. b -> Either a b
Right a
value
Maybe (a, Text)
Nothing ->
Text -> Either Text a
forall a b. a -> Either a b
Left
( Text
"unknown "
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> forall a. WireVocab a => Text
wireKind @a
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" \""
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
raw
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\" (expected one of: "
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> [Text] -> Text
T.intercalate Text
", " (NonEmpty Text -> [Text]
forall a. NonEmpty a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (((a, Text) -> Text) -> NonEmpty (a, Text) -> NonEmpty Text
forall a b. (a -> b) -> NonEmpty a -> NonEmpty b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a, Text) -> Text
forall a b. (a, b) -> b
snd NonEmpty (a, Text)
table))
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")"
)
where
table :: NonEmpty (a, Text)
table = forall a. WireVocab a => NonEmpty (a, Text)
wireTable @a