module Data.PhoneNumber.LowLevel
(
PhoneNumber(..),
PhoneNumberParseError(..),
PhoneNumberUtil(..),
getPhoneNumberUtil,
newPhoneNumberRef,
parsePhoneNumber,
unsafeConvertAlphaCharacters,
copyPhoneNumberRef,
getCountryCode,
getNationalNumber,
getExtension,
) where
import Data.PhoneNumber.FFI
import Foreign.ForeignPtr(withForeignPtr, newForeignPtr)
import Foreign.Ptr(Ptr)
import Data.Word
import Data.ByteString(ByteString, useAsCStringLen)
import Data.ByteString.Unsafe(unsafePackMallocCString, unsafeUseAsCStringLen)
import Control.Monad
data PhoneNumberParseError = PhoneNumberParseError Int
deriving (Eq, Show)
data PhoneNumber =
PhoneNumber {
countryCode :: Maybe Word64,
nationalNumber :: Maybe Word64,
extension :: Maybe ByteString
} deriving (Eq, Show)
getPhoneNumberUtil :: IO PhoneNumberUtil
getPhoneNumberUtil =
PhoneNumberUtil <$> c_phone_number_util_get_instance
newPhoneNumberRef :: IO PhoneNumberRef
newPhoneNumberRef = do
ptr <- c_phone_number_ctor
PhoneNumberRef <$> newForeignPtr c_phone_number_dtor ptr
parsePhoneNumber
:: PhoneNumberUtil
-> PhoneNumberRef
-> ByteString
-> ByteString
-> IO (Either PhoneNumberParseError ())
parsePhoneNumber (PhoneNumberUtil util_ptr) (PhoneNumberRef f_ptr) number region =
useAsCStringLen number $ \(number_str, fromIntegral -> number_len) ->
useAsCStringLen region $ \(region_str, fromIntegral -> region_len) ->
withForeignPtr f_ptr $ \ptr -> do
e <- c_phone_number_util_parse util_ptr number_str number_len region_str region_len ptr
return $ checkError (fromIntegral e)
where
checkError 0 = Right ()
checkError e = Left $ PhoneNumberParseError e
getCountryCode :: PhoneNumberRef -> IO (Maybe Word64)
getCountryCode =
(fmap . fmap) fromIntegral . maybeFetch c_phone_number_has_country_code c_phone_number_get_country_code
getNationalNumber :: PhoneNumberRef -> IO (Maybe Word64)
getNationalNumber =
(fmap . fmap) fromIntegral . maybeFetch c_phone_number_has_national_number c_phone_number_get_national_number
getExtension :: PhoneNumberRef -> IO (Maybe ByteString)
getExtension =
maybeFetch c_phone_number_has_extension c_phone_number_get_extension >=> traverse unsafePackMallocCString
copyPhoneNumberRef :: PhoneNumberRef -> IO PhoneNumber
copyPhoneNumberRef ref =
PhoneNumber <$> getCountryCode ref
<*> getNationalNumber ref
<*> getExtension ref
unsafeConvertAlphaCharacters :: PhoneNumberUtil -> ByteString -> IO ()
unsafeConvertAlphaCharacters (PhoneNumberUtil util_ptr) number =
unsafeUseAsCStringLen number $ \(number_str, fromIntegral -> number_len) ->
c_phone_number_convert_alpha_characters_in_number util_ptr number_str number_len
maybeFetch
:: (Ptr PhoneNumberRef -> IO Bool)
-> (Ptr PhoneNumberRef -> IO a)
-> PhoneNumberRef
-> IO (Maybe a)
maybeFetch p f (PhoneNumberRef f_ptr) =
withForeignPtr f_ptr $ \ptr -> do
r <- p ptr
if r
then Just <$> f ptr
else return Nothing