{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}

-- The inference lattice (sample classification, 'ParsingAssumption',
-- Int -> Double promotion) lives in "DataFrame.Operations.Inference"
-- and is re-exported here for backwards compatibility.
module DataFrame.Operations.Typing (
    module DataFrame.Operations.Typing,
    module DataFrame.Operations.Inference,
) where

import qualified Data.Map as M
import qualified Data.Text as T
import qualified Data.Vector as V
import qualified Data.Vector.Mutable as VM
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VUM

import Control.Applicative (asum)
import Control.Monad (join)
import Control.Monad.ST (runST)
import Data.Maybe (fromMaybe)
import qualified Data.Proxy as P
import Data.Time
import Data.Type.Equality (TestEquality (..))
import DataFrame.Internal.Column (
    Bitmap,
    Column (..),
    Columnable,
    bitmapTestBit,
    ensureOptional,
    finalizeParseResult,
    fromVector,
    materializePacked,
 )
import DataFrame.Internal.DataFrame (
    DataFrame (..),
    insertColumn,
    unsafeGetColumn,
 )
import DataFrame.Internal.Parsing
import DataFrame.Operations.Core ()
import DataFrame.Operations.Inference
import DataFrame.Schema
import Text.Read
import Type.Reflection

{- | How parse failures are surfaced: 'NoSafeRead' throws, 'MaybeRead' yields
@Nothing@ (column wrapped @Maybe a@), 'EitherRead' yields @Left rawText@
(column wrapped @Either Text a@, preserving the original input).
-}
data SafeReadMode
    = NoSafeRead
    | MaybeRead
    | EitherRead
    deriving (SafeReadMode -> SafeReadMode -> Bool
(SafeReadMode -> SafeReadMode -> Bool)
-> (SafeReadMode -> SafeReadMode -> Bool) -> Eq SafeReadMode
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SafeReadMode -> SafeReadMode -> Bool
== :: SafeReadMode -> SafeReadMode -> Bool
$c/= :: SafeReadMode -> SafeReadMode -> Bool
/= :: SafeReadMode -> SafeReadMode -> Bool
Eq, Int -> SafeReadMode -> ShowS
[SafeReadMode] -> ShowS
SafeReadMode -> String
(Int -> SafeReadMode -> ShowS)
-> (SafeReadMode -> String)
-> ([SafeReadMode] -> ShowS)
-> Show SafeReadMode
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SafeReadMode -> ShowS
showsPrec :: Int -> SafeReadMode -> ShowS
$cshow :: SafeReadMode -> String
show :: SafeReadMode -> String
$cshowList :: [SafeReadMode] -> ShowS
showList :: [SafeReadMode] -> ShowS
Show, ReadPrec [SafeReadMode]
ReadPrec SafeReadMode
Int -> ReadS SafeReadMode
ReadS [SafeReadMode]
(Int -> ReadS SafeReadMode)
-> ReadS [SafeReadMode]
-> ReadPrec SafeReadMode
-> ReadPrec [SafeReadMode]
-> Read SafeReadMode
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS SafeReadMode
readsPrec :: Int -> ReadS SafeReadMode
$creadList :: ReadS [SafeReadMode]
readList :: ReadS [SafeReadMode]
$creadPrec :: ReadPrec SafeReadMode
readPrec :: ReadPrec SafeReadMode
$creadListPrec :: ReadPrec [SafeReadMode]
readListPrec :: ReadPrec [SafeReadMode]
Read)

-- | Options controlling how text columns are parsed into typed values.
data ParseOptions = ParseOptions
    { ParseOptions -> [Text]
missingValues :: [T.Text]
    -- ^ Values to treat as @Nothing@ when the effective mode is 'MaybeRead'.
    , ParseOptions -> Int
sampleSize :: Int
    -- ^ Number of rows to inspect when inferring a column's type (0 = all rows).
    , ParseOptions -> SafeReadMode
parseSafe :: SafeReadMode
    -- ^ Default 'SafeReadMode' for columns without a 'parseSafeOverrides' entry.
    , ParseOptions -> [(Text, SafeReadMode)]
parseSafeOverrides :: [(T.Text, SafeReadMode)]
    {- ^ Per-column overrides taking precedence over 'parseSafe' — e.g. strict
    IDs (@NoSafeRead@) alongside lenient fields (@MaybeRead@/@EitherRead@).
    -}
    , ParseOptions -> String
parseDateFormat :: DateFormat
    -- ^ Date format string as accepted by "Data.Time.Format" (e.g. @\"%Y-%m-%d\"@).
    }

{- | Sensible out-of-the-box parse options: infer from the first 100 rows,
  treat common nullish strings as missing, and expect ISO 8601 dates.
-}
defaultParseOptions :: ParseOptions
defaultParseOptions :: ParseOptions
defaultParseOptions =
    ParseOptions
        { missingValues :: [Text]
missingValues = []
        , sampleSize :: Int
sampleSize = Int
100
        , parseSafe :: SafeReadMode
parseSafe = SafeReadMode
MaybeRead
        , parseSafeOverrides :: [(Text, SafeReadMode)]
parseSafeOverrides = []
        , parseDateFormat :: String
parseDateFormat = String
"%Y-%m-%d"
        }

{- | Resolve a column's effective 'SafeReadMode': the override if present,
otherwise the default.
-}
effectiveSafeRead ::
    SafeReadMode -> [(T.Text, SafeReadMode)] -> T.Text -> SafeReadMode
effectiveSafeRead :: SafeReadMode -> [(Text, SafeReadMode)] -> Text -> SafeReadMode
effectiveSafeRead SafeReadMode
def [(Text, SafeReadMode)]
overrides Text
name = SafeReadMode -> Maybe SafeReadMode -> SafeReadMode
forall a. a -> Maybe a -> a
fromMaybe SafeReadMode
def (Text -> [(Text, SafeReadMode)] -> Maybe SafeReadMode
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup Text
name [(Text, SafeReadMode)]
overrides)

parseDefaults :: ParseOptions -> DataFrame -> DataFrame
parseDefaults :: ParseOptions -> DataFrame -> DataFrame
parseDefaults ParseOptions
opts DataFrame
df = DataFrame
df{columns = V.imap forCol (columns df)}
  where
    nameAt :: Int -> Text
nameAt =
        let inverted :: Map Int Text
inverted = [(Int, Text)] -> Map Int Text
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [(Int
i, Text
n) | (Text
n, Int
i) <- Map Text Int -> [(Text, Int)]
forall k a. Map k a -> [(k, a)]
M.toList (DataFrame -> Map Text Int
columnIndices DataFrame
df)]
         in \Int
i -> Text -> Int -> Map Int Text -> Text
forall k a. Ord k => a -> k -> Map k a -> a
M.findWithDefault Text
"" Int
i Map Int Text
inverted
    forCol :: Int -> Column -> Column
forCol Int
i Column
col =
        let mode :: SafeReadMode
mode =
                SafeReadMode -> [(Text, SafeReadMode)] -> Text -> SafeReadMode
effectiveSafeRead
                    (ParseOptions -> SafeReadMode
parseSafe ParseOptions
opts)
                    (ParseOptions -> [(Text, SafeReadMode)]
parseSafeOverrides ParseOptions
opts)
                    (Int -> Text
nameAt Int
i)
         in ParseOptions -> Column -> Column
parseDefault ParseOptions
opts{parseSafe = mode, parseSafeOverrides = []} Column
col

parseDefault :: ParseOptions -> Column -> Column
parseDefault :: ParseOptions -> Column -> Column
parseDefault ParseOptions
opts (BoxedColumn Maybe Bitmap
Nothing (Vector a
c :: V.Vector a)) =
    case (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @a) TypeRep a -> TypeRep Text -> Maybe (a :~: Text)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
`testEquality` (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @T.Text) of
        Maybe (a :~: Text)
Nothing -> case (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @a) TypeRep a -> TypeRep String -> Maybe (a :~: String)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
`testEquality` (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @String) of
            Just a :~: String
Refl -> ParseOptions -> Vector Text -> Column
parseFromExamples ParseOptions
opts ((String -> Text) -> Vector String -> Vector Text
forall a b. (a -> b) -> Vector a -> Vector b
V.map String -> Text
T.pack Vector a
Vector String
c)
            Maybe (a :~: String)
Nothing -> Maybe Bitmap -> Vector a -> Column
forall a. Columnable a => Maybe Bitmap -> Vector a -> Column
BoxedColumn Maybe Bitmap
forall a. Maybe a
Nothing Vector a
c
        Just a :~: Text
Refl -> ParseOptions -> Vector Text -> Column
parseFromExamples ParseOptions
opts Vector a
Vector Text
c
parseDefault ParseOptions
opts (BoxedColumn (Just Bitmap
bm) (Vector a
c :: V.Vector a)) =
    case (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @a) TypeRep a -> TypeRep Text -> Maybe (a :~: Text)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
`testEquality` (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @T.Text) of
        Maybe (a :~: Text)
Nothing -> case (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @a) TypeRep a -> TypeRep String -> Maybe (a :~: String)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
`testEquality` (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @String) of
            Just a :~: String
Refl ->
                ParseOptions -> Vector Text -> Column
parseFromExamples
                    ParseOptions
opts
                    ((Int -> String -> Text) -> Vector String -> Vector Text
forall a b. (Int -> a -> b) -> Vector a -> Vector b
V.imap (\Int
i String
x -> if Bitmap -> Int -> Bool
bitmapTestBit Bitmap
bm Int
i then String -> Text
T.pack String
x else Text
"") Vector a
Vector String
c)
            Maybe (a :~: String)
Nothing -> Maybe Bitmap -> Vector a -> Column
forall a. Columnable a => Maybe Bitmap -> Vector a -> Column
BoxedColumn (Bitmap -> Maybe Bitmap
forall a. a -> Maybe a
Just Bitmap
bm) Vector a
c
        Just a :~: Text
Refl ->
            ParseOptions -> Vector Text -> Column
parseFromExamples ParseOptions
opts ((Int -> Text -> Text) -> Vector Text -> Vector Text
forall a b. (Int -> a -> b) -> Vector a -> Vector b
V.imap (\Int
i Text
x -> if Bitmap -> Int -> Bool
bitmapTestBit Bitmap
bm Int
i then Text
x else Text
"") Vector a
Vector Text
c)
parseDefault ParseOptions
_ Column
column = Column
column

parseFromExamples :: ParseOptions -> V.Vector T.Text -> Column
parseFromExamples :: ParseOptions -> Vector Text -> Column
parseFromExamples ParseOptions
opts Vector Text
cols =
    let isNull :: Text -> Bool
isNull = case ParseOptions -> SafeReadMode
parseSafe ParseOptions
opts of
            SafeReadMode
NoSafeRead -> Text -> Bool
T.null
            SafeReadMode
_ -> [Text] -> Text -> Bool
isNullishOrMissing (ParseOptions -> [Text]
missingValues ParseOptions
opts)
        examples :: Vector (Maybe Text)
examples = (Text -> Maybe Text) -> Vector Text -> Vector (Maybe Text)
forall a b. (a -> b) -> Vector a -> Vector b
V.map ((Text -> Bool) -> Text -> Maybe Text
forall {a}. (a -> Bool) -> a -> Maybe a
classify Text -> Bool
isNull) (Int -> Vector Text -> Vector Text
forall a. Int -> Vector a -> Vector a
V.take (ParseOptions -> Int
sampleSize ParseOptions
opts) Vector Text
cols)
        dfmt :: String
dfmt = ParseOptions -> String
parseDateFormat ParseOptions
opts
        assumption :: ParsingAssumption
assumption = String -> Vector (Maybe Text) -> ParsingAssumption
makeParsingAssumption String
dfmt Vector (Maybe Text)
examples
     in case ParseOptions -> SafeReadMode
parseSafe ParseOptions
opts of
            SafeReadMode
EitherRead -> String -> ParsingAssumption -> Vector Text -> Column
handleEitherAssumption String
dfmt ParsingAssumption
assumption Vector Text
cols
            SafeReadMode
mode ->
                let result :: Column
result = case ParsingAssumption
assumption of
                        ParsingAssumption
BoolAssumption -> (Text -> Bool) -> Vector Text -> Column
handleBoolAssumption Text -> Bool
isNull Vector Text
cols
                        ParsingAssumption
IntAssumption -> (Text -> Bool) -> Vector Text -> Column
handleIntAssumption Text -> Bool
isNull Vector Text
cols
                        ParsingAssumption
DoubleAssumption -> (Text -> Bool) -> Vector Text -> Column
handleDoubleAssumption Text -> Bool
isNull Vector Text
cols
                        ParsingAssumption
TextAssumption -> (Text -> Bool) -> Vector Text -> Column
handleTextAssumption Text -> Bool
isNull Vector Text
cols
                        ParsingAssumption
DateAssumption -> String -> (Text -> Bool) -> Vector Text -> Column
handleDateAssumption String
dfmt Text -> Bool
isNull Vector Text
cols
                        ParsingAssumption
NoAssumption -> String -> (Text -> Bool) -> Vector Text -> Column
handleNoAssumption String
dfmt Text -> Bool
isNull Vector Text
cols
                 in if SafeReadMode
mode SafeReadMode -> SafeReadMode -> Bool
forall a. Eq a => a -> a -> Bool
== SafeReadMode
MaybeRead then Column -> Column
ensureOptional Column
result else Column
result
  where
    classify :: (a -> Bool) -> a -> Maybe a
classify a -> Bool
p a
t = if a -> Bool
p a
t then Maybe a
forall a. Maybe a
Nothing else a -> Maybe a
forall a. a -> Maybe a
Just a
t

{- | For 'EitherRead' mode: parse under the chosen assumption into an
@Either Text a@ column. Successful parses become @Right@; failures (including
null/missing cells) become @Left@ carrying the raw input verbatim.
-}
handleEitherAssumption ::
    DateFormat -> ParsingAssumption -> V.Vector T.Text -> Column
handleEitherAssumption :: String -> ParsingAssumption -> Vector Text -> Column
handleEitherAssumption String
dfmt ParsingAssumption
assumption Vector Text
raw = case ParsingAssumption
assumption of
    ParsingAssumption
BoolAssumption -> Vector (Either Text Bool) -> Column
forall a.
(Columnable a, ColumnifyRep (KindOf a) a) =>
Vector a -> Column
fromVector ((Text -> Either Text Bool)
-> Vector Text -> Vector (Either Text Bool)
forall a b. (a -> b) -> Vector a -> Vector b
V.map ((Text -> Maybe Bool) -> Text -> Either Text Bool
forall a. (Text -> Maybe a) -> Text -> Either Text a
toEither HasCallStack => Text -> Maybe Bool
Text -> Maybe Bool
readBool) Vector Text
raw)
    ParsingAssumption
IntAssumption -> Vector (Either Text Int) -> Column
forall a.
(Columnable a, ColumnifyRep (KindOf a) a) =>
Vector a -> Column
fromVector ((Text -> Either Text Int)
-> Vector Text -> Vector (Either Text Int)
forall a b. (a -> b) -> Vector a -> Vector b
V.map ((Text -> Maybe Int) -> Text -> Either Text Int
forall a. (Text -> Maybe a) -> Text -> Either Text a
toEither HasCallStack => Text -> Maybe Int
Text -> Maybe Int
readInt) Vector Text
raw)
    ParsingAssumption
DoubleAssumption -> Vector (Either Text Double) -> Column
forall a.
(Columnable a, ColumnifyRep (KindOf a) a) =>
Vector a -> Column
fromVector ((Text -> Either Text Double)
-> Vector Text -> Vector (Either Text Double)
forall a b. (a -> b) -> Vector a -> Vector b
V.map ((Text -> Maybe Double) -> Text -> Either Text Double
forall a. (Text -> Maybe a) -> Text -> Either Text a
toEither HasCallStack => Text -> Maybe Double
Text -> Maybe Double
readDouble) Vector Text
raw)
    ParsingAssumption
DateAssumption -> Vector (Either Text Day) -> Column
forall a.
(Columnable a, ColumnifyRep (KindOf a) a) =>
Vector a -> Column
fromVector ((Text -> Either Text Day)
-> Vector Text -> Vector (Either Text Day)
forall a b. (a -> b) -> Vector a -> Vector b
V.map ((Text -> Maybe Day) -> Text -> Either Text Day
forall a. (Text -> Maybe a) -> Text -> Either Text a
toEither (String -> Text -> Maybe Day
parseTimeOpt String
dfmt)) Vector Text
raw)
    ParsingAssumption
TextAssumption -> Vector (Either Text Text) -> Column
forall a.
(Columnable a, ColumnifyRep (KindOf a) a) =>
Vector a -> Column
fromVector ((Text -> Either Text Text)
-> Vector Text -> Vector (Either Text Text)
forall a b. (a -> b) -> Vector a -> Vector b
V.map Text -> Either Text Text
textToEither Vector Text
raw)
    ParsingAssumption
NoAssumption -> Vector (Either Text Text) -> Column
forall a.
(Columnable a, ColumnifyRep (KindOf a) a) =>
Vector a -> Column
fromVector ((Text -> Either Text Text)
-> Vector Text -> Vector (Either Text Text)
forall a b. (a -> b) -> Vector a -> Vector b
V.map Text -> Either Text Text
textToEither Vector Text
raw)
  where
    toEither :: (T.Text -> Maybe a) -> T.Text -> Either T.Text a
    toEither :: forall a. (Text -> Maybe a) -> Text -> Either Text a
toEither Text -> Maybe a
p Text
t = Either Text a -> (a -> Either Text a) -> Maybe a -> Either Text a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Text -> Either Text a
forall a b. a -> Either a b
Left Text
t) a -> Either Text a
forall a b. b -> Either a b
Right (Text -> Maybe a
p Text
t)

    textToEither :: T.Text -> Either T.Text T.Text
    textToEither :: Text -> Either Text Text
textToEither Text
t = if Text -> Bool
T.null Text
t then Text -> Either Text Text
forall a b. a -> Either a b
Left Text
t else Text -> Either Text Text
forall a b. b -> Either a b
Right Text
t

parseUnboxedColumnWithPred ::
    forall src a.
    (VU.Unbox a) =>
    a ->
    (src -> Bool) ->
    (src -> Maybe a) ->
    V.Vector src ->
    Maybe (Maybe Bitmap, VU.Vector a)
parseUnboxedColumnWithPred :: forall src a.
Unbox a =>
a
-> (src -> Bool)
-> (src -> Maybe a)
-> Vector src
-> Maybe (Maybe Bitmap, Vector a)
parseUnboxedColumnWithPred a
nullValue src -> Bool
isNull src -> Maybe a
parser Vector src
vec = (forall s. ST s (Maybe (Maybe Bitmap, Vector a)))
-> Maybe (Maybe Bitmap, Vector a)
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s (Maybe (Maybe Bitmap, Vector a)))
 -> Maybe (Maybe Bitmap, Vector a))
-> (forall s. ST s (Maybe (Maybe Bitmap, Vector a)))
-> Maybe (Maybe Bitmap, Vector a)
forall a b. (a -> b) -> a -> b
$ do
    let n :: Int
n = Vector src -> Int
forall a. Vector a -> Int
V.length Vector src
vec
    STVector s a
values <- Int -> ST s (MVector (PrimState (ST s)) a)
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
Int -> m (MVector (PrimState m) a)
VUM.unsafeNew Int
n
    STVector s Word8
vmask <- Int -> ST s (MVector (PrimState (ST s)) Word8)
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
Int -> m (MVector (PrimState m) a)
VUM.unsafeNew Int
n
    let go :: Int -> Bool -> ST s (Maybe (Maybe Bitmap, Vector a))
go !Int
i !Bool
anyNull
            | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
n = STVector s a
-> STVector s Word8
-> Bool
-> ST s (Maybe (Maybe Bitmap, Vector a))
forall a s.
Unbox a =>
STVector s a
-> STVector s Word8
-> Bool
-> ST s (Maybe (Maybe Bitmap, Vector a))
finalizeParseResult STVector s a
values STVector s Word8
vmask Bool
anyNull
            | Bool
otherwise =
                let !src :: src
src = Vector src -> Int -> src
forall a. Vector a -> Int -> a
V.unsafeIndex Vector src
vec Int
i
                 in if src -> Bool
isNull src
src
                        then do
                            MVector (PrimState (ST s)) Word8 -> Int -> Word8 -> ST s ()
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
MVector (PrimState m) a -> Int -> a -> m ()
VUM.unsafeWrite STVector s Word8
MVector (PrimState (ST s)) Word8
vmask Int
i Word8
0
                            MVector (PrimState (ST s)) a -> Int -> a -> ST s ()
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
MVector (PrimState m) a -> Int -> a -> m ()
VUM.unsafeWrite STVector s a
MVector (PrimState (ST s)) a
values Int
i a
nullValue
                            Int -> Bool -> ST s (Maybe (Maybe Bitmap, Vector a))
go (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Bool
True
                        else case src -> Maybe a
parser src
src of
                            Just a
v -> do
                                MVector (PrimState (ST s)) Word8 -> Int -> Word8 -> ST s ()
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
MVector (PrimState m) a -> Int -> a -> m ()
VUM.unsafeWrite STVector s Word8
MVector (PrimState (ST s)) Word8
vmask Int
i Word8
1
                                MVector (PrimState (ST s)) a -> Int -> a -> ST s ()
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
MVector (PrimState m) a -> Int -> a -> m ()
VUM.unsafeWrite STVector s a
MVector (PrimState (ST s)) a
values Int
i a
v
                                Int -> Bool -> ST s (Maybe (Maybe Bitmap, Vector a))
go (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Bool
anyNull
                            Maybe a
Nothing -> Maybe (Maybe Bitmap, Vector a)
-> ST s (Maybe (Maybe Bitmap, Vector a))
forall a. a -> ST s a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (Maybe Bitmap, Vector a)
forall a. Maybe a
Nothing
    Int -> Bool -> ST s (Maybe (Maybe Bitmap, Vector a))
go Int
0 Bool
False
{-# INLINE parseUnboxedColumnWithPred #-}

-- | Wrap a successful 'parseUnboxedColumnWithPred' result as a 'Column'.
unboxedOrFallback ::
    (Columnable a, VU.Unbox a) =>
    Maybe (Maybe Bitmap, VU.Vector a) ->
    Column ->
    Column
unboxedOrFallback :: forall a.
(Columnable a, Unbox a) =>
Maybe (Maybe Bitmap, Vector a) -> Column -> Column
unboxedOrFallback (Just (Maybe Bitmap
mbm, Vector a
vec)) Column
_ = Maybe Bitmap -> Vector a -> Column
forall a.
(Columnable a, Unbox a) =>
Maybe Bitmap -> Vector a -> Column
UnboxedColumn Maybe Bitmap
mbm Vector a
vec
unboxedOrFallback Maybe (Maybe Bitmap, Vector a)
Nothing Column
fallback = Column
fallback

handleBoolAssumption :: (T.Text -> Bool) -> V.Vector T.Text -> Column
handleBoolAssumption :: (Text -> Bool) -> Vector Text -> Column
handleBoolAssumption Text -> Bool
isNull Vector Text
cols =
    Maybe (Maybe Bitmap, Vector Bool) -> Column -> Column
forall a.
(Columnable a, Unbox a) =>
Maybe (Maybe Bitmap, Vector a) -> Column -> Column
unboxedOrFallback
        (Bool
-> (Text -> Bool)
-> (Text -> Maybe Bool)
-> Vector Text
-> Maybe (Maybe Bitmap, Vector Bool)
forall src a.
Unbox a =>
a
-> (src -> Bool)
-> (src -> Maybe a)
-> Vector src
-> Maybe (Maybe Bitmap, Vector a)
parseUnboxedColumnWithPred Bool
False Text -> Bool
isNull HasCallStack => Text -> Maybe Bool
Text -> Maybe Bool
readBool Vector Text
cols)
        ((Text -> Bool) -> Vector Text -> Column
handleTextAssumption Text -> Bool
isNull Vector Text
cols)

{- | Int columns: one fused pass with in-place Int -> Double promotion; a cell
parsing as neither demotes the column to Text. 'readIntStrict' rejects overflow
so a huge integer promotes to 'Double' rather than wrapping.
-}
handleIntAssumption :: (T.Text -> Bool) -> V.Vector T.Text -> Column
handleIntAssumption :: (Text -> Bool) -> Vector Text -> Column
handleIntAssumption Text -> Bool
isNull Vector Text
cols =
    case (Int -> Text -> Bool)
-> (Text -> Maybe Int)
-> (Text -> Maybe Double)
-> Vector Text
-> Maybe Column
forall src.
(Int -> src -> Bool)
-> (src -> Maybe Int)
-> (src -> Maybe Double)
-> Vector src
-> Maybe Column
promoteIntColumn (\Int
_ Text
t -> Text -> Bool
isNull Text
t) Text -> Maybe Int
readIntStrict HasCallStack => Text -> Maybe Double
Text -> Maybe Double
readDouble Vector Text
cols of
        Just Column
col -> Column
col
        Maybe Column
Nothing -> (Text -> Bool) -> Vector Text -> Column
handleTextAssumption Text -> Bool
isNull Vector Text
cols

handleDoubleAssumption :: (T.Text -> Bool) -> V.Vector T.Text -> Column
handleDoubleAssumption :: (Text -> Bool) -> Vector Text -> Column
handleDoubleAssumption Text -> Bool
isNull Vector Text
cols =
    Maybe (Maybe Bitmap, Vector Double) -> Column -> Column
forall a.
(Columnable a, Unbox a) =>
Maybe (Maybe Bitmap, Vector a) -> Column -> Column
unboxedOrFallback
        (Double
-> (Text -> Bool)
-> (Text -> Maybe Double)
-> Vector Text
-> Maybe (Maybe Bitmap, Vector Double)
forall src a.
Unbox a =>
a
-> (src -> Bool)
-> (src -> Maybe a)
-> Vector src
-> Maybe (Maybe Bitmap, Vector a)
parseUnboxedColumnWithPred Double
0 Text -> Bool
isNull HasCallStack => Text -> Maybe Double
Text -> Maybe Double
readDouble Vector Text
cols)
        ((Text -> Bool) -> Vector Text -> Column
handleTextAssumption Text -> Bool
isNull Vector Text
cols)

{- | Text columns: no parse, just null-marking. An all-non-null column stays a
plain @V.Vector T.Text@; otherwise it becomes @V.Vector (Maybe T.Text)@.
-}
handleTextAssumption :: (T.Text -> Bool) -> V.Vector T.Text -> Column
handleTextAssumption :: (Text -> Bool) -> Vector Text -> Column
handleTextAssumption Text -> Bool
isNull Vector Text
cols
    | (Text -> Bool) -> Vector Text -> Bool
forall a. (a -> Bool) -> Vector a -> Bool
V.any Text -> Bool
isNull Vector Text
cols =
        Vector (Maybe Text) -> Column
forall a.
(Columnable a, ColumnifyRep (KindOf a) a) =>
Vector a -> Column
fromVector
            ((Text -> Maybe Text) -> Vector Text -> Vector (Maybe Text)
forall a b. (a -> b) -> Vector a -> Vector b
V.map (\Text
t -> if Text -> Bool
isNull Text
t then Maybe Text
forall a. Maybe a
Nothing else Text -> Maybe Text
forall a. a -> Maybe a
Just Text
t) Vector Text
cols)
    | Bool
otherwise = Vector Text -> Column
forall a.
(Columnable a, ColumnifyRep (KindOf a) a) =>
Vector a -> Column
fromVector Vector Text
cols

{- | Date: single boxed parse pass ('Day' is not unboxable). Bails to
'handleTextAssumption' the moment a non-null cell fails to parse as a 'Day'.
A column with no nulls keeps type 'Day' rather than 'Maybe Day'.
-}
handleDateAssumption ::
    DateFormat -> (T.Text -> Bool) -> V.Vector T.Text -> Column
handleDateAssumption :: String -> (Text -> Bool) -> Vector Text -> Column
handleDateAssumption String
dateFormat Text -> Bool
isNull Vector Text
cols =
    case (Text -> Bool)
-> (Text -> Maybe Day)
-> Vector Text
-> Maybe (Bool, Vector (Maybe Day))
forall a.
(Text -> Bool)
-> (Text -> Maybe a)
-> Vector Text
-> Maybe (Bool, Vector (Maybe a))
parseBoxedMaybeColumn Text -> Bool
isNull (String -> Text -> Maybe Day
parseTimeOpt String
dateFormat) Vector Text
cols of
        Just (Bool
anyNull, Vector (Maybe Day)
vec)
            | Bool
anyNull -> Vector (Maybe Day) -> Column
forall a.
(Columnable a, ColumnifyRep (KindOf a) a) =>
Vector a -> Column
fromVector Vector (Maybe Day)
vec
            | Bool
otherwise -> Vector Day -> Column
forall a.
(Columnable a, ColumnifyRep (KindOf a) a) =>
Vector a -> Column
fromVector ((Maybe Day -> Maybe Day) -> Vector (Maybe Day) -> Vector Day
forall a b. (a -> Maybe b) -> Vector a -> Vector b
V.mapMaybe Maybe Day -> Maybe Day
forall a. a -> a
id Vector (Maybe Day)
vec)
        Maybe (Bool, Vector (Maybe Day))
Nothing -> (Text -> Bool) -> Vector Text -> Column
handleTextAssumption Text -> Bool
isNull Vector Text
cols

parseBoxedMaybeColumn ::
    (T.Text -> Bool) ->
    (T.Text -> Maybe a) ->
    V.Vector T.Text ->
    Maybe (Bool, V.Vector (Maybe a))
parseBoxedMaybeColumn :: forall a.
(Text -> Bool)
-> (Text -> Maybe a)
-> Vector Text
-> Maybe (Bool, Vector (Maybe a))
parseBoxedMaybeColumn Text -> Bool
isNull Text -> Maybe a
parser Vector Text
cols = (forall s. ST s (Maybe (Bool, Vector (Maybe a))))
-> Maybe (Bool, Vector (Maybe a))
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s (Maybe (Bool, Vector (Maybe a))))
 -> Maybe (Bool, Vector (Maybe a)))
-> (forall s. ST s (Maybe (Bool, Vector (Maybe a))))
-> Maybe (Bool, Vector (Maybe a))
forall a b. (a -> b) -> a -> b
$ do
    let n :: Int
n = Vector Text -> Int
forall a. Vector a -> Int
V.length Vector Text
cols
    MVector s (Maybe a)
out <- Int -> ST s (MVector (PrimState (ST s)) (Maybe a))
forall (m :: * -> *) a.
PrimMonad m =>
Int -> m (MVector (PrimState m) a)
VM.new Int
n
    let loop :: Int -> Bool -> ST s (Maybe (Bool, Vector (Maybe a)))
loop !Int
i !Bool
anyNull
            | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
n = do
                Vector (Maybe a)
frozen <- MVector (PrimState (ST s)) (Maybe a) -> ST s (Vector (Maybe a))
forall (m :: * -> *) a.
PrimMonad m =>
MVector (PrimState m) a -> m (Vector a)
V.unsafeFreeze MVector s (Maybe a)
MVector (PrimState (ST s)) (Maybe a)
out
                Maybe (Bool, Vector (Maybe a))
-> ST s (Maybe (Bool, Vector (Maybe a)))
forall a. a -> ST s a
forall (m :: * -> *) a. Monad m => a -> m a
return ((Bool, Vector (Maybe a)) -> Maybe (Bool, Vector (Maybe a))
forall a. a -> Maybe a
Just (Bool
anyNull, Vector (Maybe a)
frozen))
            | Bool
otherwise =
                let !t :: Text
t = Vector Text -> Int -> Text
forall a. Vector a -> Int -> a
V.unsafeIndex Vector Text
cols Int
i
                 in if Text -> Bool
isNull Text
t
                        then do
                            MVector (PrimState (ST s)) (Maybe a) -> Int -> Maybe a -> ST s ()
forall (m :: * -> *) a.
PrimMonad m =>
MVector (PrimState m) a -> Int -> a -> m ()
VM.unsafeWrite MVector s (Maybe a)
MVector (PrimState (ST s)) (Maybe a)
out Int
i Maybe a
forall a. Maybe a
Nothing
                            Int -> Bool -> ST s (Maybe (Bool, Vector (Maybe a)))
loop (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Bool
True
                        else case Text -> Maybe a
parser Text
t of
                            Just a
v -> do
                                MVector (PrimState (ST s)) (Maybe a) -> Int -> Maybe a -> ST s ()
forall (m :: * -> *) a.
PrimMonad m =>
MVector (PrimState m) a -> Int -> a -> m ()
VM.unsafeWrite MVector s (Maybe a)
MVector (PrimState (ST s)) (Maybe a)
out Int
i (a -> Maybe a
forall a. a -> Maybe a
Just a
v)
                                Int -> Bool -> ST s (Maybe (Bool, Vector (Maybe a)))
loop (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Bool
anyNull
                            Maybe a
Nothing -> Maybe (Bool, Vector (Maybe a))
-> ST s (Maybe (Bool, Vector (Maybe a)))
forall a. a -> ST s a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (Bool, Vector (Maybe a))
forall a. Maybe a
Nothing
    Int -> Bool -> ST s (Maybe (Bool, Vector (Maybe a)))
loop Int
0 Bool
False

-- Reached only when the sample was all-null: try each concrete type in turn,
-- falling back to Text. A column with no nulls keeps type 'Day', not 'Maybe Day'.
handleNoAssumption ::
    DateFormat -> (T.Text -> Bool) -> V.Vector T.Text -> Column
handleNoAssumption :: String -> (Text -> Bool) -> Vector Text -> Column
handleNoAssumption String
dateFormat Text -> Bool
isNull Vector Text
cols
    | (Text -> Bool) -> Vector Text -> Bool
forall a. (a -> Bool) -> Vector a -> Bool
V.all Text -> Bool
isNull Vector Text
cols =
        Vector (Maybe Text) -> Column
forall a.
(Columnable a, ColumnifyRep (KindOf a) a) =>
Vector a -> Column
fromVector ((Text -> Maybe Text) -> Vector Text -> Vector (Maybe Text)
forall a b. (a -> b) -> Vector a -> Vector b
V.map (Maybe Text -> Text -> Maybe Text
forall a b. a -> b -> a
const (Maybe Text
forall a. Maybe a
Nothing :: Maybe T.Text)) Vector Text
cols)
    | Just (Maybe Bitmap
mbm, Vector Bool
vec) <- Bool
-> (Text -> Bool)
-> (Text -> Maybe Bool)
-> Vector Text
-> Maybe (Maybe Bitmap, Vector Bool)
forall src a.
Unbox a =>
a
-> (src -> Bool)
-> (src -> Maybe a)
-> Vector src
-> Maybe (Maybe Bitmap, Vector a)
parseUnboxedColumnWithPred Bool
False Text -> Bool
isNull HasCallStack => Text -> Maybe Bool
Text -> Maybe Bool
readBool Vector Text
cols =
        Maybe Bitmap -> Vector Bool -> Column
forall a.
(Columnable a, Unbox a) =>
Maybe Bitmap -> Vector a -> Column
UnboxedColumn Maybe Bitmap
mbm Vector Bool
vec
    | Just (Maybe Bitmap
mbm, Vector Int
vec) <- Int
-> (Text -> Bool)
-> (Text -> Maybe Int)
-> Vector Text
-> Maybe (Maybe Bitmap, Vector Int)
forall src a.
Unbox a =>
a
-> (src -> Bool)
-> (src -> Maybe a)
-> Vector src
-> Maybe (Maybe Bitmap, Vector a)
parseUnboxedColumnWithPred Int
0 Text -> Bool
isNull HasCallStack => Text -> Maybe Int
Text -> Maybe Int
readInt Vector Text
cols =
        Maybe Bitmap -> Vector Int -> Column
forall a.
(Columnable a, Unbox a) =>
Maybe Bitmap -> Vector a -> Column
UnboxedColumn Maybe Bitmap
mbm Vector Int
vec
    | Just (Maybe Bitmap
mbm, Vector Double
vec) <- Double
-> (Text -> Bool)
-> (Text -> Maybe Double)
-> Vector Text
-> Maybe (Maybe Bitmap, Vector Double)
forall src a.
Unbox a =>
a
-> (src -> Bool)
-> (src -> Maybe a)
-> Vector src
-> Maybe (Maybe Bitmap, Vector a)
parseUnboxedColumnWithPred Double
0 Text -> Bool
isNull HasCallStack => Text -> Maybe Double
Text -> Maybe Double
readDouble Vector Text
cols =
        Maybe Bitmap -> Vector Double -> Column
forall a.
(Columnable a, Unbox a) =>
Maybe Bitmap -> Vector a -> Column
UnboxedColumn Maybe Bitmap
mbm Vector Double
vec
    | Bool
otherwise = case (Text -> Bool)
-> (Text -> Maybe Day)
-> Vector Text
-> Maybe (Bool, Vector (Maybe Day))
forall a.
(Text -> Bool)
-> (Text -> Maybe a)
-> Vector Text
-> Maybe (Bool, Vector (Maybe a))
parseBoxedMaybeColumn Text -> Bool
isNull (String -> Text -> Maybe Day
parseTimeOpt String
dateFormat) Vector Text
cols of
        Just (Bool
anyNull, Vector (Maybe Day)
vec)
            | Bool
anyNull -> Vector (Maybe Day) -> Column
forall a.
(Columnable a, ColumnifyRep (KindOf a) a) =>
Vector a -> Column
fromVector Vector (Maybe Day)
vec
            | Bool
otherwise -> Vector Day -> Column
forall a.
(Columnable a, ColumnifyRep (KindOf a) a) =>
Vector a -> Column
fromVector ((Maybe Day -> Maybe Day) -> Vector (Maybe Day) -> Vector Day
forall a b. (a -> Maybe b) -> Vector a -> Vector b
V.mapMaybe Maybe Day -> Maybe Day
forall a. a -> a
id Vector (Maybe Day)
vec)
        Maybe (Bool, Vector (Maybe Day))
Nothing -> (Text -> Bool) -> Vector Text -> Column
handleTextAssumption Text -> Bool
isNull Vector Text
cols

{- | True for nullish or explicitly-listed missing strings. ('convertNullish'
and 'convertOnlyEmpty' below are kept only for external callers.)
-}
isNullishOrMissing :: [T.Text] -> T.Text -> Bool
isNullishOrMissing :: [Text] -> Text -> Bool
isNullishOrMissing [Text]
missing Text
v = Text -> Bool
isNullish Text
v Bool -> Bool -> Bool
|| Text
v Text -> [Text] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Text]
missing

convertNullish :: [T.Text] -> T.Text -> Maybe T.Text
convertNullish :: [Text] -> Text -> Maybe Text
convertNullish [Text]
missing Text
v = if Text -> Bool
isNullish Text
v Bool -> Bool -> Bool
|| Text
v Text -> [Text] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Text]
missing then Maybe Text
forall a. Maybe a
Nothing else Text -> Maybe Text
forall a. a -> Maybe a
Just Text
v

convertOnlyEmpty :: T.Text -> Maybe T.Text
convertOnlyEmpty :: Text -> Maybe Text
convertOnlyEmpty Text
v = if Text
v Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"" then Maybe Text
forall a. Maybe a
Nothing else Text -> Maybe Text
forall a. a -> Maybe a
Just Text
v

unsafeParseTime :: DateFormat -> T.Text -> Day
unsafeParseTime :: String -> Text -> Day
unsafeParseTime String
dateFormat Text
s =
    Bool -> TimeLocale -> String -> String -> Day
forall t.
ParseTime t =>
Bool -> TimeLocale -> String -> String -> t
parseTimeOrError
        Bool
True
        TimeLocale
defaultTimeLocale
        String
dateFormat
        (Text -> String
T.unpack Text
s)

hasNullValues :: (Eq a) => V.Vector (Maybe a) -> Bool
hasNullValues :: forall a. Eq a => Vector (Maybe a) -> Bool
hasNullValues = (Maybe a -> Bool) -> Vector (Maybe a) -> Bool
forall a. (a -> Bool) -> Vector a -> Bool
V.any (Maybe a -> Maybe a -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe a
forall a. Maybe a
Nothing)

vecSameConstructor :: V.Vector (Maybe a) -> V.Vector (Maybe b) -> Bool
vecSameConstructor :: forall a b. Vector (Maybe a) -> Vector (Maybe b) -> Bool
vecSameConstructor Vector (Maybe a)
xs Vector (Maybe b)
ys = (Vector (Maybe a) -> Int
forall a. Vector a -> Int
V.length Vector (Maybe a)
xs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Vector (Maybe b) -> Int
forall a. Vector a -> Int
V.length Vector (Maybe b)
ys) Bool -> Bool -> Bool
&& Vector Bool -> Bool
V.and ((Maybe a -> Maybe b -> Bool)
-> Vector (Maybe a) -> Vector (Maybe b) -> Vector Bool
forall a b c. (a -> b -> c) -> Vector a -> Vector b -> Vector c
V.zipWith Maybe a -> Maybe b -> Bool
forall a b. Maybe a -> Maybe b -> Bool
hasSameConstructor Vector (Maybe a)
xs Vector (Maybe b)
ys)
  where
    hasSameConstructor :: Maybe a -> Maybe b -> Bool
    hasSameConstructor :: forall a b. Maybe a -> Maybe b -> Bool
hasSameConstructor (Just a
_) (Just b
_) = Bool
True
    hasSameConstructor Maybe a
Nothing Maybe b
Nothing = Bool
True
    hasSameConstructor Maybe a
_ Maybe b
_ = Bool
False

{- | Re-type columns of a 'DataFrame' according to a schema map. @resolveMode@
maps a column name to its 'SafeReadMode' (typically via 'effectiveSafeRead').
-}
parseWithTypes ::
    (T.Text -> SafeReadMode) ->
    M.Map T.Text SchemaType ->
    DataFrame ->
    DataFrame
parseWithTypes :: (Text -> SafeReadMode)
-> Map Text SchemaType -> DataFrame -> DataFrame
parseWithTypes Text -> SafeReadMode
resolveMode Map Text SchemaType
ts DataFrame
df
    | Map Text SchemaType -> Bool
forall k a. Map k a -> Bool
M.null Map Text SchemaType
ts = DataFrame
df
    | Bool
otherwise =
        (Text -> SchemaType -> DataFrame -> DataFrame)
-> DataFrame -> Map Text SchemaType -> DataFrame
forall k a b. (k -> a -> b -> b) -> b -> Map k a -> b
M.foldrWithKey
            (\Text
k SchemaType
v DataFrame
d -> Text -> Column -> DataFrame -> DataFrame
insertColumn Text
k (SafeReadMode -> SchemaType -> Column -> Column
asType (Text -> SafeReadMode
resolveMode Text
k) SchemaType
v (Text -> DataFrame -> Column
unsafeGetColumn Text
k DataFrame
d)) DataFrame
d)
            DataFrame
df
            Map Text SchemaType
ts
  where
    plainType ::
        forall a b.
        (Columnable a, Read a) =>
        SafeReadMode -> V.Vector b -> (b -> String) -> Column
    plainType :: forall a b.
(Columnable a, Read a) =>
SafeReadMode -> Vector b -> (b -> String) -> Column
plainType SafeReadMode
mode Vector b
col b -> String
toStr = case SafeReadMode
mode of
        SafeReadMode
NoSafeRead -> Vector a -> Column
forall a.
(Columnable a, ColumnifyRep (KindOf a) a) =>
Vector a -> Column
fromVector ((b -> a) -> Vector b -> Vector a
forall a b. (a -> b) -> Vector a -> Vector b
V.map ((forall a. Read a => String -> a
read @a) (String -> a) -> (b -> String) -> b -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> String
toStr) Vector b
col)
        SafeReadMode
MaybeRead -> Vector (Maybe a) -> Column
forall a.
(Columnable a, ColumnifyRep (KindOf a) a) =>
Vector a -> Column
fromVector ((b -> Maybe a) -> Vector b -> Vector (Maybe a)
forall a b. (a -> b) -> Vector a -> Vector b
V.map ((forall a. Read a => String -> Maybe a
readMaybe @a) (String -> Maybe a) -> (b -> String) -> b -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> String
toStr) Vector b
col)
        SafeReadMode
EitherRead -> Vector (Either Text a) -> Column
forall a.
(Columnable a, ColumnifyRep (KindOf a) a) =>
Vector a -> Column
fromVector ((b -> Either Text a) -> Vector b -> Vector (Either Text a)
forall a b. (a -> b) -> Vector a -> Vector b
V.map ((forall a. Read a => String -> Either Text a
readEitherRaw @a) (String -> Either Text a) -> (b -> String) -> b -> Either Text a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> String
toStr) Vector b
col)

    asType :: SafeReadMode -> SchemaType -> Column -> Column
    asType :: SafeReadMode -> SchemaType -> Column -> Column
asType SafeReadMode
mode SchemaType
st c :: Column
c@(PackedText Maybe Bitmap
_ PackedTextData
_) = SafeReadMode -> SchemaType -> Column -> Column
asType SafeReadMode
mode SchemaType
st (Column -> Column
materializePacked Column
c)
    asType SafeReadMode
mode (SType (Proxy a
_ :: P.Proxy a)) c :: Column
c@(BoxedColumn Maybe Bitmap
_ (Vector a
col :: V.Vector b)) = case forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @a of
        App TypeRep a
t1 TypeRep b
_t2 -> case TypeRep a -> TypeRep Maybe -> Maybe (a :~~: Maybe)
forall k1 k2 (a :: k1) (b :: k2).
TypeRep a -> TypeRep b -> Maybe (a :~~: b)
eqTypeRep TypeRep a
t1 (forall {k} (a :: k). Typeable a => TypeRep a
forall (a :: * -> *). Typeable a => TypeRep a
typeRep @Maybe) of
            Just a :~~: Maybe
HRefl -> case TypeRep a -> TypeRep a -> Maybe (a :~: a)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
testEquality (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @a) (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @b) of
                Just a :~: a
Refl -> Column
c
                Maybe (a :~: a)
Nothing -> case TypeRep Text -> TypeRep a -> Maybe (Text :~: a)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
testEquality (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @T.Text) (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @b) of
                    Just Text :~: a
Refl -> Vector (Maybe b) -> Column
forall a.
(Columnable a, ColumnifyRep (KindOf a) a) =>
Vector a -> Column
fromVector ((Text -> Maybe b) -> Vector Text -> Vector (Maybe b)
forall a b. (a -> b) -> Vector a -> Vector b
V.map (Maybe (Maybe b) -> Maybe b
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join (Maybe (Maybe b) -> Maybe b)
-> (Text -> Maybe (Maybe b)) -> Text -> Maybe b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. Read a => String -> Maybe a
readAsMaybe @a) (String -> Maybe (Maybe b))
-> (Text -> String) -> Text -> Maybe (Maybe b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
T.unpack) Vector a
Vector Text
col)
                    Maybe (Text :~: a)
Nothing -> Vector (Maybe b) -> Column
forall a.
(Columnable a, ColumnifyRep (KindOf a) a) =>
Vector a -> Column
fromVector ((a -> Maybe b) -> Vector a -> Vector (Maybe b)
forall a b. (a -> b) -> Vector a -> Vector b
V.map (Maybe (Maybe b) -> Maybe b
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join (Maybe (Maybe b) -> Maybe b)
-> (a -> Maybe (Maybe b)) -> a -> Maybe b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. Read a => String -> Maybe a
readAsMaybe @a) (String -> Maybe (Maybe b))
-> (a -> String) -> a -> Maybe (Maybe b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
forall a. Show a => a -> String
show) Vector a
col)
            Maybe (a :~~: Maybe)
Nothing -> case TypeRep a
t1 of
                App TypeRep a
t1' TypeRep b
_t2' -> case TypeRep a -> TypeRep Either -> Maybe (a :~~: Either)
forall k1 k2 (a :: k1) (b :: k2).
TypeRep a -> TypeRep b -> Maybe (a :~~: b)
eqTypeRep TypeRep a
t1' (forall {k} (a :: k). Typeable a => TypeRep a
forall (a :: * -> * -> *). Typeable a => TypeRep a
typeRep @Either) of
                    Just a :~~: Either
HRefl -> case TypeRep a -> TypeRep a -> Maybe (a :~: a)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
testEquality (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @a) (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @b) of
                        Just a :~: a
Refl -> Column
c
                        Maybe (a :~: a)
Nothing -> case TypeRep Text -> TypeRep a -> Maybe (Text :~: a)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
testEquality (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @T.Text) (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @b) of
                            Just Text :~: a
Refl -> Vector a -> Column
forall a.
(Columnable a, ColumnifyRep (KindOf a) a) =>
Vector a -> Column
fromVector ((Text -> a) -> Vector Text -> Vector a
forall a b. (a -> b) -> Vector a -> Vector b
V.map ((forall a. Read a => String -> a
readAsEither @a) (String -> a) -> (Text -> String) -> Text -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
T.unpack) Vector a
Vector Text
col)
                            Maybe (Text :~: a)
Nothing -> Vector a -> Column
forall a.
(Columnable a, ColumnifyRep (KindOf a) a) =>
Vector a -> Column
fromVector ((a -> a) -> Vector a -> Vector a
forall a b. (a -> b) -> Vector a -> Vector b
V.map ((forall a. Read a => String -> a
readAsEither @a) (String -> a) -> (a -> String) -> a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
forall a. Show a => a -> String
show) Vector a
col)
                    Maybe (a :~~: Either)
Nothing -> case TypeRep a -> TypeRep a -> Maybe (a :~: a)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
testEquality (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @a) (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @b) of
                        Just a :~: a
Refl -> Column
c
                        Maybe (a :~: a)
Nothing -> case TypeRep Text -> TypeRep a -> Maybe (Text :~: a)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
testEquality (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @T.Text) (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @b) of
                            Just Text :~: a
Refl -> forall a b.
(Columnable a, Read a) =>
SafeReadMode -> Vector b -> (b -> String) -> Column
plainType @a SafeReadMode
mode Vector a
col a -> String
Text -> String
T.unpack
                            Maybe (Text :~: a)
Nothing -> forall a b.
(Columnable a, Read a) =>
SafeReadMode -> Vector b -> (b -> String) -> Column
plainType @a SafeReadMode
mode Vector a
col a -> String
forall a. Show a => a -> String
show
                TypeRep a
_ -> Column
c
        TypeRep a
_ -> case TypeRep a -> TypeRep a -> Maybe (a :~: a)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
testEquality (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @a) (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @b) of
            Just a :~: a
Refl -> Column
c
            Maybe (a :~: a)
Nothing -> case TypeRep Text -> TypeRep a -> Maybe (Text :~: a)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
testEquality (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @T.Text) (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @b) of
                Just Text :~: a
Refl -> forall a b.
(Columnable a, Read a) =>
SafeReadMode -> Vector b -> (b -> String) -> Column
plainType @a SafeReadMode
mode Vector a
col a -> String
Text -> String
T.unpack
                Maybe (Text :~: a)
Nothing -> forall a b.
(Columnable a, Read a) =>
SafeReadMode -> Vector b -> (b -> String) -> Column
plainType @a SafeReadMode
mode Vector a
col a -> String
forall a. Show a => a -> String
show
    asType SafeReadMode
_ SchemaType
_ Column
c = Column
c

readAsMaybe :: (Read a) => String -> Maybe a
readAsMaybe :: forall a. Read a => String -> Maybe a
readAsMaybe String
s
    | String -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
s = Maybe a
forall a. Maybe a
Nothing
    | Bool
otherwise = String -> Maybe a
forall a. Read a => String -> Maybe a
readMaybe (String -> Maybe a) -> String -> Maybe a
forall a b. (a -> b) -> a -> b
$ String
"Just " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
s

readAsEither :: (Read a) => String -> a
readAsEither :: forall a. Read a => String -> a
readAsEither String
v = case [Maybe a] -> Maybe a
forall (t :: * -> *) (f :: * -> *) a.
(Foldable t, Alternative f) =>
t (f a) -> f a
asum [String -> Maybe a
forall a. Read a => String -> Maybe a
readMaybe (String -> Maybe a) -> String -> Maybe a
forall a b. (a -> b) -> a -> b
$ String
"Left " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
s, String -> Maybe a
forall a. Read a => String -> Maybe a
readMaybe (String -> Maybe a) -> String -> Maybe a
forall a b. (a -> b) -> a -> b
$ String
"Right " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
s] of
    Maybe a
Nothing -> String -> a
forall a. HasCallStack => String -> a
error (String -> a) -> String -> a
forall a b. (a -> b) -> a -> b
$ String
"Couldn't read value: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
s
    Just a
v' -> a
v'
  where
    s :: String
s = if String -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
v then String
"\"\"" else String
v

{- | Try 'readMaybe'; on failure return @Left raw@ where @raw@ is the original
input text. Used by 'parseWithTypes' under 'EitherRead'.
-}
readEitherRaw :: forall a. (Read a) => String -> Either T.Text a
readEitherRaw :: forall a. Read a => String -> Either Text a
readEitherRaw String
s = case String -> Maybe a
forall a. Read a => String -> Maybe a
readMaybe String
s of
    Just a
v -> a -> Either Text a
forall a b. b -> Either a b
Right a
v
    Maybe a
Nothing -> Text -> Either Text a
forall a b. a -> Either a b
Left (String -> Text
T.pack String
s)