module Data.Serialize.Describe.Combinators.NText where import Prelude hiding ((.), id) import Control.Category import Control.Monad.Trans.Class import Data.String import Data.Text (Text) import qualified Data.Text as T import Data.Serialize.Describe.Internal.Descriptor import Data.Serialize.Describe.Class -- | A null-terminated text descriptor which reads characters until '\0' is encountered. Semantically, the '\0' is consumed by the parser. The entire text will be serialized with a '\0' character appended to the end. ntext :: (MonadTrans m, forall x. Monad x => Monad (m x)) => (s -> Text) -> DescriptorM m s Text ntext f = T.pack . reverse <$> go 0 [] where go i cs = field @Char (test i . f) >>= \case '\0' -> pure cs c -> pure (c:cs) test i t | i >= T.length t = '\0' | otherwise = T.index t i -- | Type-level variant of @ftext@. newtype NText = NText { unwrapNText :: Text } deriving (Show) via Text instance IsString NText where fromString = NText . T.pack instance Describe NText where describe = NText <$> ntext unwrapNText