diff --git a/Codec/Binary/UTF8/String.hs b/Codec/Binary/UTF8/String.hs
--- a/Codec/Binary/UTF8/String.hs
+++ b/Codec/Binary/UTF8/String.hs
@@ -14,6 +14,8 @@
 module Codec.Binary.UTF8.String (
       encode
     , decode
+    , encodeString
+    , decodeString
   ) where
 
 import Data.Word        (Word8)
@@ -21,6 +23,16 @@
 import Data.Char        (chr,ord)
 
 default(Int)
+
+-- | Encode a string using 'encode' and store the result in a 'String'.
+encodeString :: String -> String
+encodeString xs = map (toEnum . fromEnum) (encode xs)
+
+-- | Decode a string using 'decode' using a 'String' as input.
+-- | This is not safe but it is necessary if UTF-8 encoded text
+-- | has been loaded into a 'String' prior to being decoded.
+decodeString :: String -> String
+decodeString xs = decode (map (toEnum . fromEnum) xs)
 
 replacement_character :: Char
 replacement_character = '\xfffd'
diff --git a/tests/Bench.hs b/tests/Bench.hs
deleted file mode 100644
--- a/tests/Bench.hs
+++ /dev/null
@@ -1,211 +0,0 @@
-{-# OPTIONS -cpp -fglasgow-exts #-}
-
-{-
-$ ghc --make -O2 Bench.hs -o bench 
-
-$ ./bench 
-Size of test data: 2428k
-Char    Optimal byteString decode
- 1 0.102  0.109  0.102  0.109  0.102  
-   0.063  0.063  0.070  0.055  0.070        # "decode"   
--}
-
---
--- Benchmark tool.
--- Compare a function against equivalent code from other libraries for
--- space and time.
---
-
-import Data.ByteString (ByteString)
-import qualified Data.ByteString as P
--- import qualified Data.ByteString as L
-
-import Data.List
-import Data.Char
-import Data.Word
-import Data.Int
-
-import System.Mem
-import Control.Concurrent
-
-import System.IO
-import System.CPUTime
-import System.IO.Unsafe
-import Control.Monad
-import Control.Exception
-import Text.Printf
-
-------------------------------------------------------------------------
--- a reference (incorrect, but fast) implementation:
-
-import GHC.Ptr
-import qualified GHC.Base as GHC
-import qualified Data.ByteString      as B
-import qualified Data.ByteString.Base as B
-
-import Data.ByteString (ByteString)
-import qualified Data.ByteString        as B
-import qualified Data.ByteString.Char8  as C
-import qualified Data.ByteString.Lazy   as L
-
-import Data.List
-import Data.Char
-import Data.Word
-import Data.Int
-
-import System.IO
-import Control.Monad
-import Text.Printf
-
-import qualified Codec.Binary.UTF8.String as UTF8
-
-------------------------------------------------------------------------
-
-main :: IO ()
-main = do
-    force (fps,chars,strs)
-    printf "# Size of test data: %dk\n" ((floor $ (fromIntegral (B.length fps)) / 1024) :: Int)
-    printf "#Char\t Optimal byteString decode\n"
-    run 5 (fps,chars,strs) tests
-
---
--- Measure the difference building an decoded String from
--- bytestring+GHC's inbuilt decoder, and ours.
---
--- Most cost is in building the String.
---
-tests =
-    [ ("decode",
-        [F ( app UTF8.decode)
-        ,F ( app unpackCStringUTF8) ])
-
-    , ("encode",
-        [F ( app UTF8.encode) ])
-    ]
-
-
--- unpackCStringUtf8# wants \0 termianted strings. rewrite it to take a
--- length instead, and we avoid the copy in useAsCString.
-unpackCStringUTF8 :: B.ByteString -> [Char]
-unpackCStringUTF8 b = unsafePerformIO $ B.unsafeUseAsCString b $ \(Ptr a) ->
-    return (GHC.unpackCStringUtf8# a)
-
-
-------------------------------------------------------------------------
-
-run c x tests = sequence_ $ zipWith (doit c x) [1..] tests
-
-doit :: Int -> a -> Int -> (String, [F a]) -> IO ()
-doit count x n (s,ls) = do
-    printf "%2d " n
-    fn ls
-    printf "\t# %-16s\n" (show s)
-    hFlush stdout
-  where fn xs = case xs of
-                    [f,g]   -> runN count f x >> putStr "\n   "
-                            >> runN count g x >> putStr "\t"
-                    [f]     -> runN count f x >> putStr "\t"
-                    _       -> return ()
-        run f x = dirtyCache fps >> performGC >> threadDelay 100 >> time f x
-        runN 0 f x = return ()
-        runN c f x = run f x >> runN (c-1) f x
-
-dirtyCache x = evaluate (P.foldl1' (+) x)
-{-# NOINLINE dirtyCache #-}
-
-time :: F a -> a -> IO ()
-time (F f) a = do
-    start <- getCPUTime
-    v     <- force (f a)
-    case v of
-        B -> printf "--\t"
-        _ -> do
-            end   <- getCPUTime
-            let diff = (fromIntegral (end - start)) / (10^12)
-            printf "%0.3f  " (diff :: Double)
-    hFlush stdout
-
-------------------------------------------------------------------------
--- 
--- an existential list
---
-data F a = forall b . Forceable b => F (a -> b)
-
-data Result = T | B
-
---
--- a bit deepSeqish
---
-class Forceable a where
-    force :: a -> IO Result
-    force v = v `seq` return T
-
-#if !defined(HEAD)
-instance Forceable P.ByteString where
-    force v = P.length v `seq` return T
-#endif
-
-instance Forceable L.ByteString where
-    force v = L.length v `seq` return T
-
--- instance Forceable SPS.PackedString where
---     force v = SPS.length v `seq` return T
-
--- instance Forceable PS.PackedString where
---     force v = PS.lengthPS v `seq` return T
-
-instance Forceable a => Forceable (Maybe a) where
-    force Nothing  = return T
-    force (Just v) = force v `seq` return T
-
-instance Forceable [a] where
-    force v = length v `seq` return T
-
-instance (Forceable a, Forceable b) => Forceable (a,b) where
-    force (a,b) = force a >> force b
-
-instance (Forceable a, Forceable b, Forceable c) => Forceable (a,b,c) where
-    force (a,b,c) = force a >> force b >> force c
-
-instance Forceable Int
-instance Forceable Int64
-instance Forceable Bool
-instance Forceable Char
-instance Forceable Word8
-instance Forceable Ordering
-
--- used to signal undefinedness
-instance Forceable () where force () = return B
-
-------------------------------------------------------------------------
---
--- some large strings to play with
---
-
-fps     :: P.ByteString
-fps     = unsafePerformIO $ P.readFile dict
-{-# NOINLINE fps #-}
-
-chars   :: [Word8]
-chars   = B.unpack fps
-{-# NOINLINE chars #-}
-
-strs    :: String
-strs    = C.unpack fps
-{-# NOINLINE strs #-}
-
-dict  = "/usr/share/dict/words"
-
-------------------------------------------------------------------------
-
-type Input = (B.ByteString,[Word8],String)
-
-class (Eq a, Ord a) => Ap a where app :: (a -> b) -> Input -> b
-
-instance Ap B.ByteString where app f x = f (fst3 x)
-instance Ap [Word8]      where app f x = f (snd3 x)
-instance Ap String       where app f x = f (thd3 x)
-
-fst3 (a,_,_) = a
-snd3 (_,a,_) = a
-thd3 (_,_,a) = a
diff --git a/tests/Tests.hs b/tests/Tests.hs
deleted file mode 100644
--- a/tests/Tests.hs
+++ /dev/null
@@ -1,16 +0,0 @@
-import Codec.Binary.UTF8.String
-
-main = let v = encodeDecodeTest
-       in putStrLn $ case v of
-            [] -> "Ok. All passed."
-            s  -> "Encode/decode failures: " ++ show s
-
---
--- test decode . encode == id for the class of chars we know that to be true of
---
-encodeDecodeTest :: [Char]
-encodeDecodeTest = filter (\x -> [x] /= decode (encode [x])) legal_codepoints ++
-                   filter (\x -> ['\xfffd'] /= decode (encode [x])) illegal_codepoints
-  where
-    legal_codepoints = ['\0'..'\xd7ff'] ++ ['\xe000'..'\xfffd'] ++ ['\x10000'..'\x10ffff']
-    illegal_codepoints = '\xffff' : '\xfffe' : ['\xd800'..'\xdfff']
diff --git a/utf8-string.cabal b/utf8-string.cabal
--- a/utf8-string.cabal
+++ b/utf8-string.cabal
@@ -1,5 +1,5 @@
 Name:               utf8-string
-Version:            0.1
+Version:            0.2
 Author:             Eric Mertens
 Maintainer:         emertens@galois.com
 License:            BSD3
