module Octane.Type.Primitive.PCString (PCString(..)) where
import qualified Data.ByteString.Char8 as BS8
import qualified Data.Text as Text
import Octane.Core
import Octane.Type.Primitive.Int32LE
newtype PCString = PCString
{ getPCString :: Text
} deriving (Eq, Generic, NFData, Ord, Show)
instance Binary PCString where
get = do
(Int32LE size) <- get
string <- if size == 0
then fail "invalid size"
else if size < 0
then do
let actualSize = 2 * negate size
bytes <- getByteString (fromIntegral actualSize)
bytes & decodeUtf16LE & return
else do
bytes <- getByteString (fromIntegral size)
bytes & decodeLatin1 & return
string & Text.dropEnd 1 & PCString & return
put (PCString string) = do
let cString = Text.snoc string '\NUL'
let size = cString & Text.length & fromIntegral
if Text.all isLatin1 cString
then do
size & Int32LE & put
cString & encodeLatin1 & putByteString
else do
size & negate & Int32LE & put
cString & encodeUtf16LE & putByteString
encodeLatin1 :: Text -> ByteString
encodeLatin1 text = text & Text.unpack & BS8.pack