on dabfac7 help sign in
123 lines 4.4 kB history raw
1{-# LANGUAGE CPP, DeriveDataTypeable #-}
2#if __GLASGOW_HASKELL__ >= 702
3{-# LANGUAGE Trustworthy #-}
4#endif
5-- |
6-- Module : Data.Text.Encoding.Error
7-- Copyright : (c) Bryan O'Sullivan 2009
8--
9-- License : BSD-style
10-- Maintainer : bos@serpentine.com
11-- Stability : experimental
12-- Portability : GHC
13--
14-- Types and functions for dealing with encoding and decoding errors
15-- in Unicode text.
16--
17-- The standard functions for encoding and decoding text are strict,
18-- which is to say that they throw exceptions on invalid input. This
19-- is often unhelpful on real world input, so alternative functions
20-- exist that accept custom handlers for dealing with invalid inputs.
21-- These 'OnError' handlers are normal Haskell functions. You can use
22-- one of the presupplied functions in this module, or you can write a
23-- custom handler of your own.
25module Data.Text.Encoding.Error
26 (
27 -- * Error handling types
28 UnicodeException(..)
29 , OnError
30 , OnDecodeError
31 , OnEncodeError
32 -- * Useful error handling functions
33 , lenientDecode
34 , strictDecode
35 , strictEncode
36 , ignore
37 , replace
38 ) where
40import Control.DeepSeq (NFData (..))
41import Control.Exception (Exception, throw)
42import Data.Typeable (Typeable)
43import Data.Word (Word8)
44import Numeric (showHex)
46-- | Function type for handling a coding error. It is supplied with
47-- two inputs:
48--
49-- * A 'String' that describes the error.
50--
51-- * The input value that caused the error. If the error arose
52-- because the end of input was reached or could not be identified
53-- precisely, this value will be 'Nothing'.
54--
55-- If the handler returns a value wrapped with 'Just', that value will
56-- be used in the output as the replacement for the invalid input. If
57-- it returns 'Nothing', no value will be used in the output.
58--
59-- Should the handler need to abort processing, it should use 'error'
60-- or 'throw' an exception (preferably a 'UnicodeException'). It may
61-- use the description provided to construct a more helpful error
62-- report.
63type OnError a b = String -> Maybe a -> Maybe b
65-- | A handler for a decoding error.
66type OnDecodeError = OnError Word8 Char
68-- | A handler for an encoding error.
69{-# DEPRECATED OnEncodeError "This exception is never used in practice, and will be removed." #-}
70type OnEncodeError = OnError Char Word8
72-- | An exception type for representing Unicode encoding errors.
73data UnicodeException =
74 DecodeError String (Maybe Word8)
75 -- ^ Could not decode a byte sequence because it was invalid under
76 -- the given encoding, or ran out of input in mid-decode.
77 | EncodeError String (Maybe Char)
78 -- ^ Tried to encode a character that could not be represented
79 -- under the given encoding, or ran out of input in mid-encode.
80 deriving (Eq, Typeable)
82{-# DEPRECATED EncodeError "This constructor is never used, and will be removed." #-}
84showUnicodeException :: UnicodeException -> String
85showUnicodeException (DecodeError desc (Just w))
86 = "Cannot decode byte '\\x" ++ showHex w ("': " ++ desc)
87showUnicodeException (DecodeError desc Nothing)
88 = "Cannot decode input: " ++ desc
89showUnicodeException (EncodeError desc (Just c))
90 = "Cannot encode character '\\x" ++ showHex (fromEnum c) ("': " ++ desc)
91showUnicodeException (EncodeError desc Nothing)
92 = "Cannot encode input: " ++ desc
94instance Show UnicodeException where
95 show = showUnicodeException
97instance Exception UnicodeException
99instance NFData UnicodeException where
100 rnf (DecodeError desc w) = rnf desc `seq` rnf w `seq` ()
101 rnf (EncodeError desc c) = rnf desc `seq` rnf c `seq` ()
103-- | Throw a 'UnicodeException' if decoding fails.
104strictDecode :: OnDecodeError
105strictDecode desc c = throw (DecodeError desc c)
107-- | Replace an invalid input byte with the Unicode replacement
108-- character U+FFFD.
109lenientDecode :: OnDecodeError
110lenientDecode _ _ = Just '\xfffd'
112-- | Throw a 'UnicodeException' if encoding fails.
113{-# DEPRECATED strictEncode "This function always throws an exception, and will be removed." #-}
114strictEncode :: OnEncodeError
115strictEncode desc c = throw (EncodeError desc c)
117-- | Ignore an invalid input, substituting nothing in the output.
118ignore :: OnError a b
119ignore _ _ = Nothing
121-- | Replace an invalid input with a valid output.
122replace :: b -> OnError a b
123replace c _ _ = Just c