{- |
Copyright : (c) 2024 Pierre Le Marre
Maintainer: dev@wismill.eu
Stability : experimental

[Default values](https://www.unicode.org/reports/tr44/#Default_Values)
for properties.
-}
module Unicode.CharacterDatabase.Parser.Properties.Defaults (
  -- * Default values
  defaultAge,
  defaultBlock,
  defaultGeneralCategory,
  defaultScript,

  -- * Missing convention
  MissingConvention (..),
  MissingPropertyConvention (..),
  parseMissingConventionM,
  parseMissingPropertyConventionM,
) where

import Data.ByteString qualified as B
import Data.ByteString.Char8 qualified as B8
import Data.ByteString.Short qualified as BS

import Unicode.CharacterDatabase.Parser.Internal (
  CodePointRange,
  parseCodePointRange,
  pattern SemiColon,
 )

--------------------------------------------------------------------------------
-- Default values
--------------------------------------------------------------------------------

-- | Default age
defaultAge  BS.ShortByteString
defaultAge :: ShortByteString
defaultAge = ShortByteString
"Unassigned"

-- | Default general category
defaultGeneralCategory  BS.ShortByteString
defaultGeneralCategory :: ShortByteString
defaultGeneralCategory = ShortByteString
"Cn"

-- | Default block
defaultBlock  BS.ShortByteString
defaultBlock :: ShortByteString
defaultBlock = ShortByteString
"No_Block"

-- | Default script
defaultScript  BS.ShortByteString
defaultScript :: ShortByteString
defaultScript = ShortByteString
"Unknown"

--------------------------------------------------------------------------------
-- Missing conventions
--------------------------------------------------------------------------------

{- | [Missing convention](https://www.unicode.org/reports/tr44/#Missing_Conventions)

@since 0.3.0
-}
data MissingConvention = MissingConvention
  { MissingConvention -> CodePointRange
range  !CodePointRange
  , MissingConvention -> ShortByteString
value  !BS.ShortByteString
  }
  deriving (MissingConvention -> MissingConvention -> Bool
(MissingConvention -> MissingConvention -> Bool)
-> (MissingConvention -> MissingConvention -> Bool)
-> Eq MissingConvention
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: MissingConvention -> MissingConvention -> Bool
== :: MissingConvention -> MissingConvention -> Bool
$c/= :: MissingConvention -> MissingConvention -> Bool
/= :: MissingConvention -> MissingConvention -> Bool
Eq, Int -> MissingConvention -> ShowS
[MissingConvention] -> ShowS
MissingConvention -> String
(Int -> MissingConvention -> ShowS)
-> (MissingConvention -> String)
-> ([MissingConvention] -> ShowS)
-> Show MissingConvention
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> MissingConvention -> ShowS
showsPrec :: Int -> MissingConvention -> ShowS
$cshow :: MissingConvention -> String
show :: MissingConvention -> String
$cshowList :: [MissingConvention] -> ShowS
showList :: [MissingConvention] -> ShowS
Show)

{- | Parser for @\@missing@ conventions without property name

>>> parseMissingConventionM "# @missing: 0000..10FFFF; Unassigned"
Just (MissingConvention {range = CharRange {start = '\NUL', end = '\1114111'}, value = "Unassigned"})

For further details, see: https://www.unicode.org/reports/tr44/#Missing_Conventions

@since 0.3.0
-}
parseMissingConventionM  B.ByteString  Maybe MissingConvention
parseMissingConventionM :: ByteString -> Maybe MissingConvention
parseMissingConventionM = (ByteString -> MissingConvention)
-> Maybe ByteString -> Maybe MissingConvention
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ByteString -> MissingConvention
parse (Maybe ByteString -> Maybe MissingConvention)
-> (ByteString -> Maybe ByteString)
-> ByteString
-> Maybe MissingConvention
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString -> Maybe ByteString
B8.stripPrefix ByteString
"# @missing: "
 where
  parse :: ByteString -> MissingConvention
parse ByteString
raw = MissingConvention{ShortByteString
CodePointRange
$sel:range:MissingConvention :: CodePointRange
$sel:value:MissingConvention :: ShortByteString
range :: CodePointRange
value :: ShortByteString
..}
   where
    (ByteString -> CodePointRange
parseCodePointRange  CodePointRange
range, ByteString
raw') = (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
B.span (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word8
SemiColon) ByteString
raw
    value :: ShortByteString
value = ByteString -> ShortByteString
BS.toShort (ByteString -> ByteString
B8.strip (Int -> ByteString -> ByteString
B.drop Int
1 ByteString
raw'))

{- | [Missing convention](https://www.unicode.org/reports/tr44/#Missing_Conventions)

@since 0.3.0
-}
data MissingPropertyConvention = MissingPropertyConvention
  { MissingPropertyConvention -> CodePointRange
range  !CodePointRange
  , MissingPropertyConvention -> ShortByteString
property  !BS.ShortByteString
  , MissingPropertyConvention -> ShortByteString
value  !BS.ShortByteString
  }
  deriving (MissingPropertyConvention -> MissingPropertyConvention -> Bool
(MissingPropertyConvention -> MissingPropertyConvention -> Bool)
-> (MissingPropertyConvention -> MissingPropertyConvention -> Bool)
-> Eq MissingPropertyConvention
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: MissingPropertyConvention -> MissingPropertyConvention -> Bool
== :: MissingPropertyConvention -> MissingPropertyConvention -> Bool
$c/= :: MissingPropertyConvention -> MissingPropertyConvention -> Bool
/= :: MissingPropertyConvention -> MissingPropertyConvention -> Bool
Eq, Int -> MissingPropertyConvention -> ShowS
[MissingPropertyConvention] -> ShowS
MissingPropertyConvention -> String
(Int -> MissingPropertyConvention -> ShowS)
-> (MissingPropertyConvention -> String)
-> ([MissingPropertyConvention] -> ShowS)
-> Show MissingPropertyConvention
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> MissingPropertyConvention -> ShowS
showsPrec :: Int -> MissingPropertyConvention -> ShowS
$cshow :: MissingPropertyConvention -> String
show :: MissingPropertyConvention -> String
$cshowList :: [MissingPropertyConvention] -> ShowS
showList :: [MissingPropertyConvention] -> ShowS
Show)

{- | Parser for @\@missing@ conventions with property name

>>> parseMissingPropertyConventionM "# @missing: 0000..10FFFF; Decomposition_Mapping; <code point>"
Just (MissingPropertyConvention {range = CharRange {start = '\NUL', end = '\1114111'}, property = "Decomposition_Mapping", value = "<code point>"})

For further details, see: https://www.unicode.org/reports/tr44/#Missing_Conventions
-}
parseMissingPropertyConventionM  B.ByteString  Maybe MissingPropertyConvention
parseMissingPropertyConventionM :: ByteString -> Maybe MissingPropertyConvention
parseMissingPropertyConventionM = (ByteString -> MissingPropertyConvention)
-> Maybe ByteString -> Maybe MissingPropertyConvention
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ByteString -> MissingPropertyConvention
parse (Maybe ByteString -> Maybe MissingPropertyConvention)
-> (ByteString -> Maybe ByteString)
-> ByteString
-> Maybe MissingPropertyConvention
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString -> Maybe ByteString
B8.stripPrefix ByteString
"# @missing: "
 where
  parse :: ByteString -> MissingPropertyConvention
parse ByteString
raw = MissingPropertyConvention{ShortByteString
CodePointRange
$sel:range:MissingPropertyConvention :: CodePointRange
$sel:property:MissingPropertyConvention :: ShortByteString
$sel:value:MissingPropertyConvention :: ShortByteString
range :: CodePointRange
property :: ShortByteString
value :: ShortByteString
..}
   where
    (ByteString -> CodePointRange
parseCodePointRange  CodePointRange
range, ByteString
raw1) = (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
B.span (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word8
SemiColon) ByteString
raw
    (ByteString
rawProperty, ByteString
raw2) = (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
B.span (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word8
SemiColon) (Int -> ByteString -> ByteString
B.drop Int
1 ByteString
raw1)
    property :: ShortByteString
property = ByteString -> ShortByteString
BS.toShort (ByteString -> ByteString
B8.strip ByteString
rawProperty)
    value :: ShortByteString
value = ByteString -> ShortByteString
BS.toShort (ByteString -> ByteString
B8.strip (Int -> ByteString -> ByteString
B.drop Int
1 ByteString
raw2))