module String where
import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as BC
import qualified Data.ByteString.Short as SB
import Data.Word (Word64)
newTraceIdFromHeader :: ByteString -> SB.ShortByteString
newTraceIdFromHeader = SB.toShort . fillLeadingZeros 16 . convertWord64ToBinaryByteString . read . BC.unpack
newSpanIdFromHeader :: ByteString -> SB.ShortByteString
newSpanIdFromHeader = SB.toShort . fillLeadingZeros 8 . convertWord64ToBinaryByteString . read . BC.unpack
newHeaderFromTraceId :: SB.ShortByteString -> ByteString
newHeaderFromTraceId = BC.pack . show . convertBinaryByteStringToWord64 . SB.fromShort
newHeaderFromSpanId :: SB.ShortByteString -> ByteString
newHeaderFromSpanId = BC.pack . show . convertBinaryByteStringToWord64 . SB.fromShort
convertWord64ToBinaryByteString :: Word64 -> ByteString
convertWord64ToBinaryByteString =
B.pack . toWord8s []
where
toWord8s acc 0 = acc
toWord8s acc n =
let (p, q) = n `divMod` (2 ^ (8 :: Int))
in toWord8s (fromIntegral q : acc) p
fillLeadingZeros :: Word -> ByteString -> ByteString
fillLeadingZeros len bs = B.replicate (fromIntegral len - B.length bs) 0 <> bs
convertBinaryByteStringToWord64 :: ByteString -> Word64
convertBinaryByteStringToWord64 = B.foldl (\acc b -> (2 ^ (8 :: Int)) * acc + fromIntegral b) 0 -- GHC.Prim.indexWord8ArrayAsWord64# とか駆使すると早くなりそう