{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module Ecluse.Core.Wire (
WireVocab (..),
lookupWire,
parseWire,
renderWire,
) where
import Data.Text qualified as T
class WireVocab a where
wireKind :: Text
wireTable :: NonEmpty (a, Text)
wireAliases :: [(a, Text)]
wireAliases = []
lookupWire :: forall a. (WireVocab a) => Text -> Maybe a
lookupWire :: forall a. WireVocab a => Text -> Maybe a
lookupWire Text
raw = (a, Text) -> a
forall a b. (a, b) -> a
fst ((a, Text) -> a) -> Maybe (a, Text) -> Maybe a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ((a, Text) -> Bool) -> [(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) -> [(a, Text)]
forall a. NonEmpty a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (forall a. WireVocab a => NonEmpty (a, Text)
wireTable @a) [(a, Text)] -> [(a, Text)] -> [(a, Text)]
forall a. Semigroup a => a -> a -> a
<> forall a. WireVocab a => [(a, Text)]
wireAliases @a)
parseWire :: forall a. (WireVocab a) => Text -> Either Text a
parseWire :: forall a. WireVocab a => Text -> Either Text a
parseWire Text
raw = Text -> Maybe a -> Either Text a
forall l r. l -> Maybe r -> Either l r
maybeToRight Text
unknown (Text -> Maybe a
forall a. WireVocab a => Text -> Maybe a
lookupWire Text
raw)
where
unknown :: Text
unknown =
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 (forall a. WireVocab a => NonEmpty (a, Text)
wireTable @a)))
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")"
renderWire :: forall a. (WireVocab a, Eq a) => a -> Text
renderWire :: forall a. (WireVocab a, Eq a) => a -> Text
renderWire a
value = case forall a. WireVocab a => NonEmpty (a, Text)
wireTable @a of
(a
v0, Text
n0) :| [(a, Text)]
rest
| a
value a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
v0 -> Text
n0
| Bool
otherwise -> Text -> ((a, Text) -> Text) -> Maybe (a, Text) -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
n0 (a, Text) -> Text
forall a b. (a, b) -> b
snd (((a, Text) -> Bool) -> [(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) [(a, Text)]
rest)