<commit_before>module Duffer.Pack.File where

import qualified Data.Map.Strict    as Map
import qualified Data.IntMap.Strict as IntMap

import Prelude hiding       (concat, take, drop)

import Data.Bool            (bool)
import Data.ByteString      (ByteString, concat, take, drop)
import Data.Tuple           (swap)
import Duffer.Loose.Objects (Ref, GitObject)
import Duffer.Pack.Parser   (hashResolved, parseResolved, parsedIndex)
import Duffer.Pack.Entries  (WCL(..), PackDelta(..), PackEntry(..)
                            ,PackedObject(..), DeltaInstruction(..), Delta(..)
                            ,CombinedMap(..), RefIndex, OffsetMap, ObjectMap(..)
                            ,toAssoc, emptyObjectMap, isResolved, insertObject)

applyInstructions :: ByteString -> [DeltaInstruction] -> ByteString
applyInstructions source = concat . map (`applyInstruction` source)

substring :: Int -> Int -> ByteString -> ByteString
substring offset len = take len . drop offset

applyInstruction :: DeltaInstruction -> ByteString -> ByteString
applyInstruction (CopyInstruction offset len) = substring offset len
applyInstruction (InsertInstruction content)  = const content

resolve :: PackedObject -> WCL Delta -> PackedObject
resolve (PackedObject t _ (WCL _ source)) (WCL l (Delta _ _ is)) = let
    resolved = applyInstructions source is
    r        = hashResolved t resolved
    in PackedObject t r (WCL l resolved)

resolveDelta :: CombinedMap -> Int -> (PackedObject, CombinedMap)
resolveDelta combinedMap index = case getOffsetMap combinedMap IntMap.! index of
    Resolved object -> (object, combinedMap)
    UnResolved (OfsDelta o delta) -> let
        index' = index - o
        (source, combinedMap') = resolveDelta combinedMap index'
        resolved = resolve source delta
        in (resolved, updateOffsetMap combinedMap' index resolved)
    UnResolved (RefDelta r delta) -> let
        index' = getRefIndex combinedMap Map.! r
        (source, combinedMap') = resolveDelta combinedMap index'
        resolved = resolve source delta
        in (resolved, updateOffsetMap combinedMap' index resolved)
    where updateOffsetMap cMap newIndex value = let
            offsetMap  = getOffsetMap cMap
            offsetMap' = IntMap.insert newIndex (Resolved value) offsetMap
            in cMap {getOffsetMap = offsetMap'}

resolveEntry :: CombinedMap -> Ref -> Maybe GitObject
resolveEntry combinedMap ref = unpackObject . fst . resolveDelta combinedMap <$>
    Map.lookup ref (getRefIndex combinedMap)<commit_msg>Refactor resolveDelta.<commit_after>module Duffer.Pack.File where

import qualified Data.Map.Strict    as Map
import qualified Data.IntMap.Strict as IntMap

import Prelude hiding       (concat, take, drop)

import Data.Bool            (bool)
import Data.ByteString      (ByteString, concat, take, drop)
import Data.Tuple           (swap)
import Duffer.Loose.Objects (Ref, GitObject)
import Duffer.Pack.Parser   (hashResolved, parseResolved, parsedIndex)
import Duffer.Pack.Entries  (WCL(..), PackDelta(..), PackEntry(..)
                            ,PackedObject(..), DeltaInstruction(..), Delta(..)
                            ,CombinedMap(..), RefIndex, OffsetMap, ObjectMap(..)
                            ,toAssoc, emptyObjectMap, isResolved, insertObject)

applyInstructions :: ByteString -> [DeltaInstruction] -> ByteString
applyInstructions source = concat . map (`applyInstruction` source)

substring :: Int -> Int -> ByteString -> ByteString
substring offset len = take len . drop offset

applyInstruction :: DeltaInstruction -> ByteString -> ByteString
applyInstruction (CopyInstruction offset len) = substring offset len
applyInstruction (InsertInstruction content)  = const content

resolve :: PackedObject -> WCL Delta -> PackedObject
resolve (PackedObject t _ (WCL _ source)) (WCL l (Delta _ _ is)) = let
    resolved = applyInstructions source is
    r        = hashResolved t resolved
    in PackedObject t r (WCL l resolved)

resolveDelta :: CombinedMap -> Int -> (PackedObject, CombinedMap)
resolveDelta combinedMap index = case getOffsetMap combinedMap IntMap.! index of
    Resolved   object     -> (object, combinedMap)
    UnResolved unresolved -> let
        (delta, index') = case unresolved of
            OfsDelta o d -> (d, index - o)
            RefDelta r d -> (d, getRefIndex combinedMap Map.! r)
        (source, combinedMap') = resolveDelta combinedMap index'
        resolved = resolve source delta
        in (resolved, insertOffsetMap index (Resolved resolved) combinedMap')
    where insertOffsetMap key value cMap = cMap
            {getOffsetMap = IntMap.insert key value $ getOffsetMap cMap}

resolveEntry :: CombinedMap -> Ref -> Maybe GitObject
resolveEntry combinedMap ref = unpackObject . fst . resolveDelta combinedMap <$>
    Map.lookup ref (getRefIndex combinedMap)
{'fraction_non_alphanumeric': 0.08931155675005169, 'fraction_numerical': 0.0, 'mean_word_length': 3.174288179465056, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 38, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5489387', 'n_tokens_mistral': 1280, 'n_tokens_neox': 1282, 'n_words': 433}