@@ -17,10 +17,15 @@
17---------------------------------------------------------
17---------------------------------------------------------
19module Text.Yaml
19module Text.Yaml
20− ( module Data.Object
20+ (
21− , encode
21+ -- * Converting to/from 'TextObject's
24+ -- * Convert to/from 'ScalarObejct's
22 , encodeFile
28 , encodeFile
24 , decodeFile
29 , decodeFile
26 , testSuite
31 , testSuite
@@ -33,6 +38,7 @@ import qualified Data.ByteString as B
33import qualified Data.ByteString.Lazy as BL
38import qualified Data.ByteString.Lazy as BL
34import Data.Object
39import Data.Object
35import Data.Object.Text
40import Data.Object.Text
41+import Data.Object.Scalar
36import System.IO.Unsafe
42import System.IO.Unsafe
37import Control.Arrow (first)
43import Control.Arrow (first)
38import Control.Monad (liftM, join)
44import Control.Monad (liftM, join)
@@ -50,19 +56,56 @@ import Test.Framework.Providers.HUnit
50import Test.Framework.Providers.QuickCheck (testProperty)
56import Test.Framework.Providers.QuickCheck (testProperty)
51import Test.HUnit hiding (Test, path)
57import Test.HUnit hiding (Test, path)
52import Test.QuickCheck
58import Test.QuickCheck
60+import Control.Monad (replicateM)
61+import Control.Arrow ((***))
64+-- Low level, non-exported functions
55−encode :: (ConvertSuccess B.ByteString a, ToObject o Text Text) => o -> a
65+encode' :: ConvertSuccess B.ByteString a
56−encode = unsafePerformIO . encode'
66+ => TextObject
69+ let events = objectToEvents o
70+ result = withEmitter $ flip emitEvents events
71+ in convertSuccess `fmap` joinAttempt result
58−decode :: (ConvertSuccess a B.ByteString,
73+decode' :: (ConvertSuccess a B.ByteString,
74+ MonadFailure YamlException m
79+ events <- withParser (convertSuccess bs) parserParse
80+ return $ liftM eventsToTextObject events
83+encodeText :: ConvertSuccess B.ByteString a
86+encodeText = unsafePerformIO . encode'
88+decodeText :: (ConvertSuccess a B.ByteString,
59− MonadFailure YamlException m)
89+ MonadFailure YamlException m)
61− -> m TextObject
91+ -> m TextObject
92+decodeText = unsafePerformIO . decode'
95+encodeScalar :: ConvertSuccess B.ByteString a
98+encodeScalar = unsafePerformIO . encode' . toTextObject
100+decodeScalar :: (ConvertSuccess a B.ByteString,
101+ MonadFailure YamlException m)
62−decode = unsafePerformIO . decode'
104+decodeScalar = liftM toScalarObject . unsafePerformIO . decode'
64encodeFile :: ToObject o Text Text => FilePath -> o -> IO ()
107encodeFile :: ToObject o Text Text => FilePath -> o -> IO ()
65−encodeFile path o = encode' o >>= ltWriteFile path
108+encodeFile path o = encode' (toTextObject o) >>= ltWriteFile path
67ltWriteFile :: FilePath -> Text -> IO ()
110ltWriteFile :: FilePath -> Text -> IO ()
68ltWriteFile fp = BL.writeFile fp . LTE.encodeUtf8
111ltWriteFile fp = BL.writeFile fp . LTE.encodeUtf8
@@ -78,24 +121,7 @@ decodeFile path = do
78ltReadFile :: FilePath -> IO Text
121ltReadFile :: FilePath -> IO Text
79ltReadFile = fmap LTE.decodeUtf8 . BL.readFile
122ltReadFile = fmap LTE.decodeUtf8 . BL.readFile
81−encode' :: (ConvertSuccess B.ByteString a,
124+-- The real worker functions
82− ToObject o Text Text)
86− let events = objectToEvents $ toObject o
87− result = withEmitter $ flip emitEvents events
88− in convertSuccess `fmap` joinAttempt result
90−decode' :: (ConvertSuccess a B.ByteString,
91− MonadFailure YamlException m
96− events <- withParser (convertSuccess bs) parserParse
97− return $ liftM eventsToTextObject events
99objectToEvents :: TextObject -> [Event]
125objectToEvents :: TextObject -> [Event]
100objectToEvents y = concat
126objectToEvents y = concat
101 [ [EventStreamStart, EventDocumentStart]
127 [ [EventStreamStart, EventDocumentStart]
@@ -144,6 +170,7 @@ eventsToTextObject = fst . readSingle . dropWhile isIgnored where
144 readMap _ (e:_) = error $ "Unexpected event in readMap: " ++ show e
170 readMap _ (e:_) = error $ "Unexpected event in readMap: " ++ show e
145 readMap _ [] = error "Unexpected empty event list in readMap"
171 readMap _ [] = error "Unexpected empty event list in readMap"
147newtype MyString = MyString String
174newtype MyString = MyString String
148 deriving (Eq, Show)
175 deriving (Eq, Show)
149instance ConvertAttempt MyString Text where
176instance ConvertAttempt MyString Text where
@@ -151,12 +178,53 @@ instance ConvertAttempt MyString Text where
151instance ConvertSuccess MyString Text where
178instance ConvertSuccess MyString Text where
152 convertSuccess (MyString s) = convertSuccess s
179 convertSuccess (MyString s) = convertSuccess s
153instance ConvertAttempt Text MyString where
180instance ConvertAttempt Text MyString where
181+ convertAttempt = return . convertSuccess
182+instance ConvertSuccess Text MyString where
183+ convertSuccess = MyString . convertSuccess
185+myEquals :: Eq v => Attempt v -> Attempt v -> Bool
186+myEquals (Success v1) (Success v2) = v1 == v2
189+instance ConvertSuccess B.ByteString B.ByteString where -- FIXME belongs elsewhere
191+instance ConvertAttempt B.ByteString B.ByteString where -- FIXME belongs elsewhere
154− convertAttempt raw = MyString `liftM` convertAttempt raw
192+ convertAttempt = return
157propEncodeDecode :: Object MyString MyString -> Bool
194propEncodeDecode :: Object MyString MyString -> Bool
158−propEncodeDecode o = fromAttempt (decode (encode o :: B.ByteString))
195+propEncodeDecode o =
159− == Just o
196+ fmap h2 (decodeText (encodeText (h1 o) :: B.ByteString))
197+ `myEquals` Success o
199+ h1 = mapKeysValues convertSuccess convertSuccess
200+ h2 = mapKeysValues convertSuccess convertSuccess
202+toSBS :: ConvertSuccess a B.ByteString => a -> B.ByteString
203+toSBS = convertSuccess
205+toLBS :: ConvertSuccess a BL.ByteString => a -> BL.ByteString
206+toLBS = convertSuccess
208+instance ToObject (Object Text Text) Text Text where -- FIXME belongs elsewhere
211+instance ConvertSuccess B.ByteString [Char] where -- FIXME belongs elsewhere
212+ convertSuccess = convertSuccess . (convertSuccess :: B.ByteString -> Text)
213+instance ConvertAttempt B.ByteString [Char] where -- FIXME belongs elsewhere
214+ convertAttempt = return . convertSuccess
215+instance ConvertSuccess [Char] B.ByteString where -- FIXME belongs elsewhere
216+ convertSuccess = convertSuccess . (convertSuccess :: String -> Text)
217+instance ConvertAttempt [Char] B.ByteString where -- FIXME belongs elsewhere
218+ convertAttempt = return . convertSuccess
220+instance ConvertSuccess BL.ByteString [Char] where -- FIXME belongs elsewhere
221+ convertSuccess = convertSuccess . (convertSuccess :: BL.ByteString -> Text)
222+instance ConvertAttempt BL.ByteString [Char] where -- FIXME belongs elsewhere
223+ convertAttempt = return . convertSuccess
224+instance ConvertSuccess [Char] BL.ByteString where -- FIXME belongs elsewhere
225+ convertSuccess = convertSuccess . (convertSuccess :: String -> Text)
226+instance ConvertAttempt [Char] BL.ByteString where -- FIXME belongs elsewhere
227+ convertAttempt = return . convertSuccess
161caseEmptyStrings :: Assertion
229caseEmptyStrings :: Assertion
162caseEmptyStrings = do
230caseEmptyStrings = do
@@ -165,9 +233,14 @@ caseEmptyStrings = do
165 , ("baz", "")
233 , ("baz", "")
166 , ("bin", "")
234 , ("bin", "")
168− let m' = map (toStrictByteString *** toStrictByteString) m
236+ let m' = map (toSBS *** toSBS) m
169− let m'' = map (toLazyByteString *** toLazyByteString) m
237+ let m'' = map (toLBS *** toLBS) m
170− let test' x = Just x @=? fromAttempt (decode (encode x :: String))
238+ let test' :: (ToObject x Text Text, FromObject x Text Text, Eq x, Show x)
241+ test' x = Just x @=?
242+ fa (decodeText (encodeText (toTextObject x) :: String)
173 test' m''
246 test' m''