From 978e83a701a905714dbe5c921111d8ec9b0cd5b7 Mon Sep 17 00:00:00 2001
From: Ramakrishnan Muthukrishnan <ram@rkrishnan.org>
Date: Sun, 17 Jul 2016 17:03:08 +0530
Subject: [PATCH] metainfo: refactoring

---
 src/FuncTorrent/Metainfo.hs | 52 +++++++++++++++----------------------
 test/MetainfoSpec.hs        | 25 +++++++++++-------
 2 files changed, 36 insertions(+), 41 deletions(-)

diff --git a/src/FuncTorrent/Metainfo.hs b/src/FuncTorrent/Metainfo.hs
index ec65294..9a7d7a8 100644
--- a/src/FuncTorrent/Metainfo.hs
+++ b/src/FuncTorrent/Metainfo.hs
@@ -22,7 +22,6 @@
 module FuncTorrent.Metainfo
     (Info(..)
     , Metainfo(..)
-    , DynamicInfo(..)
     , FileInfo(..)
     , torrentToMetainfo
     ) where
@@ -40,15 +39,9 @@ import FuncTorrent.Bencode (BVal(..), encode, decode, bstrToString, bValToIntege
 data Info = Info { pieceLength :: !Integer
                  , pieces :: !ByteString
                  , private :: !(Maybe Integer)
-                 , dyninfo :: !DynamicInfo
+                 , files :: ![FileInfo]
                  } deriving (Eq, Show)
 
-data DynamicInfo = SingleFileInfo { file :: FileInfo }
-                 | MultiFileInfo { dname :: String
-                                 , files :: [FileInfo]
-                                 }
-                 deriving (Eq, Show)
-
 data FileInfo = FileInfo { lengthInBytes :: Integer
                          , md5sum :: Maybe String
                          , path :: String
@@ -63,8 +56,8 @@ data Metainfo = Metainfo { info :: !Info
                          , infoHash :: !ByteString
                          } deriving (Eq, Show)
 
-mkPath :: [BVal] -> String
-mkPath xs = intercalate "/" $ map (\b -> let (Just s) = bstrToString b in s) xs
+mkPath :: String -> [BVal] -> String
+mkPath base xs = base ++ "/" ++ (intercalate "/" $ map (\b -> let (Just s) = bstrToString b in s) xs)
 
 mkInfo :: BVal -> Maybe Info
 mkInfo (Bdict m) = let (Bint pieceLength') = m ! "piece length"
@@ -75,24 +68,22 @@ mkInfo (Bdict m) = let (Bint pieceLength') = m ! "piece length"
                      case bdictfiles of
                        Just fs -> let (Blist files') = fs
                                       (Bstr name') = m ! "name"
+                                      dname' = unpack name'
                                   in
                                     Just Info { pieceLength = pieceLength'
                                               , pieces = pieces'
                                               , private = private'
-                                              , dyninfo = MultiFileInfo {
-                                                  dname = unpack name',
-                                                  files =
-                                                      map (\(Bdict f) ->
-                                                            let (Just len') = bValToInteger (f ! "length")
-                                                                (Blist ds) = f ! "path"
-                                                                path' = mkPath ds
-                                                            in
-                                                              FileInfo { lengthInBytes = len',
-                                                                         md5sum = Nothing,
-                                                                         path = path'
-                                                                     })
-                                                      files' }
-                                              }
+                                              , files =
+                                                  map (\(Bdict f) ->
+                                                        let (Just len') = bValToInteger (f ! "length")
+                                                            (Blist ds) = f ! "path"
+                                                            path' = mkPath dname' ds
+                                                        in
+                                                          FileInfo { lengthInBytes = len',
+                                                                     md5sum = Nothing,
+                                                                     path = path'
+                                                                   })
+                                                  files' }
                        Nothing -> let (Bstr name') = m ! "name"
                                       (Bint length') = m ! "length"
                                       md5sum' = Nothing
@@ -100,13 +91,12 @@ mkInfo (Bdict m) = let (Bint pieceLength') = m ! "piece length"
                                     Just Info { pieceLength = pieceLength'
                                               , pieces = pieces'
                                               , private = private'
-                                              , dyninfo = SingleFileInfo {
-                                                  file = FileInfo {
-                                                      path = unpack name',
-                                                      lengthInBytes = length',
-                                                      md5sum = md5sum'
-                                                      }
-                                                  }
+                                              , files = [ FileInfo {
+                                                            path = unpack name',
+                                                            lengthInBytes = length',
+                                                            md5sum = md5sum'
+                                                            }
+                                                        ]
                                               }
 
 mkInfo _ = Nothing
diff --git a/test/MetainfoSpec.hs b/test/MetainfoSpec.hs
index 060bf9f..98e3b08 100644
--- a/test/MetainfoSpec.hs
+++ b/test/MetainfoSpec.hs
@@ -23,7 +23,7 @@ module MetainfoSpec where
 
 import Test.Hspec
 
-import FuncTorrent.Metainfo (Info(..), Metainfo(..), DynamicInfo(..), FileInfo(..), torrentToMetainfo)
+import FuncTorrent.Metainfo (Info(..), Metainfo(..), FileInfo(..), torrentToMetainfo)
 import qualified Data.ByteString.Lazy.Char8 as BC (readFile, toStrict)
 import qualified Data.ByteString as B
 
@@ -36,25 +36,30 @@ spec =
       length (announceList m) `shouldBe` 1
       pieceLength (info m) `shouldBe` 524288
       pieces (info m) `shouldSatisfy` (\p -> B.length p `mod` 20 == 0)
-      let (SingleFileInfo file') = dyninfo $ info m
-          (FileInfo _ _ name') = file'
+      let fs = files $ info m
+          (FileInfo _ _ name') = head fs
       name' `shouldNotBe` ""
+      length fs `shouldBe` 1
     it "torrent-file-2" $ do
       c <- BC.readFile "data/test2.torrent"
       let (Right m) = torrentToMetainfo (BC.toStrict c)
-          (SingleFileInfo file') = dyninfo $ info m
-          (FileInfo _ _ name') = file'
+          fs = files $ info m
+          (FileInfo _ _ name') = head fs
       name' `shouldNotBe` ""
+      length fs `shouldBe` 1
     it "torrent-file-3" $ do
       c <- BC.readFile "data/test3.torrent"
       let (Right m) = torrentToMetainfo (BC.toStrict c)
-          (SingleFileInfo file') = dyninfo $ info m
-          (FileInfo _ _ name') = file'
+          fs = files $ info m
+          (FileInfo _ _ name') = head fs
       name' `shouldNotBe` ""
+      length fs `shouldBe` 1
     it "torrent-file-4" $ do
       c <- BC.readFile "data/test4.torrent"
       let (Right m) = torrentToMetainfo (BC.toStrict c)
       length (announceList m) `shouldBe` 3
-      let (MultiFileInfo dname' files') = dyninfo $ info m
-      length files' `shouldBe` 9 -- 9 files in the torrent
-      dname' `shouldBe` "NASA_NTRS_Archive_19740027163"
+      let fs = files $ info m
+          p = path $ head fs
+      length fs `shouldBe` 9 -- 9 files in the torrent
+      p `shouldStartWith` "NASA_NTRS_Archive_19740027163"
+
-- 
2.45.2