
Hello, cafe. I have a big problem using builders, so currently I'm using own builder based on Nettle one [1]. It uses Strict bytestring to build into and unchecked writes, thus it's very unsafe, plus other builders/PutM, developed rapidly so I like to switch to another one. However I use some patterns that seems not implemented in other builders, so I'd like to hear advices how to implement it there or how I can write code without using them. All of the patterns is done in order to have more performance and gives a way to build complex data without additional allocations. 1). Delayed input: This unsafe pattern can be implemented in any PutM monad for any constant sized value, the idea is that we write a plaseholder and returns a funtion that will write correct value to the address when applied. This pattern is needed when we need to update length or CRC sum after content is written:
test1 put = delayedWord16be >>= \ph -> someOtherStuff >> undelay ph calculateCRC
2). LookAhead: Sometimes I need to know the length of the content to be written, possibly I can write content to ByteString, and calculate length and write it, however if resulting type is not LBS it leads to additional allocations and memory move. For PutM a special wrapper can be written withLength :: a {- length type -} -> PutM () -> PutM (). Or special data structure and delayed input can be used, special data structure is Marker, it marks a place in datastructure allowing to calculate distances, it works very efficiently with ByteString, but I have no idea how to implement it with LBS:
test1 put = delayedWord32be >>= \ph -> marker -> \m -> put >> distance m >>= undelay . fromIntegral
3). LookBehind Returning back to crc calculation I had to use additional pattern, it's a lookback: I need to inspect unfinished data, that I've already have written, I have not done correct wrappers so I've used markers and fromForeignPtr from ByteString.Internal:
test3 = do m <- marker somestuff d <- distance marker let crc = (unsafePerformIO $ BS.unsafePackAddressLen hlen' (toAddr m))
-- Alexander