field2 :: T.Text} deriving (Show, Generic) deriving Binary
С помощью binary эту структуру можно (де)сериализовывать.
После сериалзации T.Text будет храниться длина строка, а потом её содержимое. Удобно, однако проблема в том, что я работаю со c string. Это набор байт, который заканчивается \NUL (то есть нам не надо знать длину строки, мы должны читать поток байт, пока не наткнёмся на \NUL). Как парсить ту же структуру (X), но так, чтобы каждое поле, которое имеет тип T.Text, (де)сериализовывалсь по-другому? Я попытался что-то сделать с Generic, но быстро встрял (к тому же требуется расширение UndecidableInstances, ещё и BSL.toStrict, который работает за O(n))
Если коротко, то
class MyGBinaryGet f where
mygGet :: Get (f a)
instance MyGBinaryGet (K1 i T.Text) where
mygGet = K1 . decodeUtf8 . BSL.toStrict<$> getLazyByteStringNul
instance Binary c => MyGBinaryGet (K1 i c) where
mygGet = K1 <$> get
То есть decode (BS.pack [49, 50, 51, 0, 51, 50, 49, 0]) :: X == X "123" "321"
Как ни странно, тут будут overlapping instances, но даже добавление {-# OVERLAPPING #-} не работает. Да и вообще моё решение — большой костыль
Проще всего парсить не Text, а свой newtype в этих полях
Обсуждают сегодня