diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,10 @@
 
 ##0.3.0.1 -- 2020-01-09
 
+* Added NText combinator
+
+##0.3.0.1 -- 2020-01-09
+
 * Added unexposed combinator modules
 
 ##0.3.0.0 -- 2020-01-09
diff --git a/describe.cabal b/describe.cabal
--- a/describe.cabal
+++ b/describe.cabal
@@ -3,7 +3,7 @@
 --   For further documentation, see http://haskell.org/cabal/users-guide/
 
 name:                describe
-version:             0.3.0.1
+version:             0.3.1.0
 synopsis:            Combinators for describing binary data structures
 description:         Combinators for describing binary data structures, which eliminate the boilerplate of having to write isomorphic Get and Put instances. Please see the Github page for examples.
 homepage:            https://github.com/riugabachi/describe
@@ -28,6 +28,7 @@
                       TypeFamilies,
                       TypeOperators,
                       OverlappingInstances,
+                      LambdaCase,
                       GeneralizedNewtypeDeriving,
                       FlexibleContexts,
                       DefaultSignatures,
@@ -63,6 +64,7 @@
                        Data.Serialize.Describe.Combinators.Byte,
                        Data.Serialize.Describe.Combinators.Remaining,
                        Data.Serialize.Describe.Combinators.ByteEnum,
+                       Data.Serialize.Describe.Combinators.NText,
                        Data.Serialize.Describe.Class
   hs-source-dirs:      src
 
diff --git a/src/Data/Serialize/Describe/Class.hs b/src/Data/Serialize/Describe/Class.hs
--- a/src/Data/Serialize/Describe/Class.hs
+++ b/src/Data/Serialize/Describe/Class.hs
@@ -9,6 +9,7 @@
 import Data.Serialize.Get
 import Data.Serialize.Put
 import Data.Vector.Fixed.Boxed (Vec)
+import Data.Char
 import Data.Int
 import Data.Proxy
 import Data.Word
@@ -47,6 +48,9 @@
 
 instance Describe Bool where
     describe f = toEnum . fromIntegral <$> describe (fromIntegral @_ @Word8 . fromEnum . f)
+
+instance Describe Char where
+    describe f = chr . fromIntegral <$> describe @Word8 (fromIntegral . ord <$> f)
 
 instance Describe Word8 where
     describe f = Descriptor (fromIntegral <$> getWord8, \s' -> putWord8 (fromIntegral $ f s') >> pure (fromIntegral $ f s'))
diff --git a/src/Data/Serialize/Describe/Combinators.hs b/src/Data/Serialize/Describe/Combinators.hs
--- a/src/Data/Serialize/Describe/Combinators.hs
+++ b/src/Data/Serialize/Describe/Combinators.hs
@@ -7,6 +7,7 @@
   module Data.Serialize.Describe.Combinators.Const,
   module Data.Serialize.Describe.Combinators.ByteEnum,
   module Data.Serialize.Describe.Combinators.Conditional,
+  module Data.Serialize.Describe.Combinators.NText,
   module Data.Serialize.Describe.Combinators.Byte
 ) where
 
@@ -18,4 +19,5 @@
 import Data.Serialize.Describe.Combinators.Const
 import Data.Serialize.Describe.Combinators.ByteEnum
 import Data.Serialize.Describe.Combinators.Conditional
+import Data.Serialize.Describe.Combinators.NText
 import Data.Serialize.Describe.Combinators.Byte
diff --git a/src/Data/Serialize/Describe/Combinators/NText.hs b/src/Data/Serialize/Describe/Combinators/NText.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Serialize/Describe/Combinators/NText.hs
@@ -0,0 +1,37 @@
+module Data.Serialize.Describe.Combinators.NText where
+
+import Data.Word
+import Data.Char
+import Data.String
+import Data.Text (Text)
+import qualified Data.Text as T
+import Data.Serialize.Describe.Descriptor
+import Data.Serialize.Describe.Class
+import Data.Serialize.Put
+import Control.Monad
+
+-- | 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 :: (s -> Text) -> Descriptor s Text
+ntext f = Descriptor (g, p)
+  where
+    g = unwrapGet $ T.pack . reverse <$> go []
+      where
+        go cs = describe @Char (const '\0') >>= \case
+          '\0' -> pure cs
+          c -> go $ c:cs
+    p s = do
+      forM_ (T.unpack (f s)) $ putWord8 . fromIntegral . ord
+      putWord8 $ fromIntegral $ ord '\0'
+      pure (f s)
+
+-- | 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 f = 
+    NText <$> ntext (fmap unwrapNText f)
+
