### Install cborg and serialise Libraries Source: https://github.com/well-typed/cborg/blob/master/README.md Installs the 'cborg' and 'serialise' Haskell libraries using the cabal build tool. This is the primary method for getting started with the libraries. ```bash cabal install cborg serialise ``` -------------------------------- ### Run cborg Package Tests Source: https://github.com/well-typed/cborg/blob/master/README.md Executes the tests for the 'cborg' package, which are included within the 'serialise' package. This command is used to verify the integrity and functionality of the installed libraries. ```bash cabal test serialise ``` -------------------------------- ### Pretty Print CBOR Encodings with cborg.Pretty Source: https://context7.com/well-typed/cborg/llms.txt This snippet demonstrates the `prettyHexEnc` function from `Codec.CBOR.Pretty` for visualizing CBOR encodings in a human-readable hexadecimal format with semantic annotations. It shows examples of pretty-printing a map and a list, highlighting the structure and content of the CBOR data. Key imports include `Codec.CBOR.Pretty`, `Codec.CBOR.Encoding`, and `Data.Text`. ```haskell import Codec.CBOR.Pretty (prettyHexEnc) import Codec.CBOR.Encoding import Codec.CBOR.Term (encodeTerm, TInt, TString, TList, TMap) import qualified Data.Text as T main :: IO () main = do -- Create an encoding let enc = encodeMapLen 2 <> encodeString (T.pack "name") <> encodeString (T.pack "Alice") <> encodeString (T.pack "age") <> encodeInt 30 -- Pretty print the encoding putStrLn $ prettyHexEnc enc -- Output: -- a2 # map(2) -- 64 6e 61 6d 65 # text("name") -- 65 41 6c 69 63 65 # text("Alice") -- 63 61 67 65 # text("age") -- 18 1e # int(30) -- Pretty print a list let listEnc = encodeListLen 3 <> encodeInt 1 <> encodeInt 2 <> encodeInt 3 putStrLn $ prettyHexEnc listEnc -- Output: -- 83 # list(3) -- 01 # int(1) -- 02 # int(2) -- 03 # int(3) ``` -------------------------------- ### Decode CBOR Data with Precise Control in Haskell Source: https://context7.com/well-typed/cborg/llms.txt Illustrates using `Codec.CBOR.Decoding` for precise CBOR data decoding. It shows how to define decoders for custom data structures like `Point`, inspect token types for flexible decoding, and handle indefinite-length structures. The example also demonstrates deserializing data from a file. ```haskell import Codec.CBOR.Decoding import Codec.CBOR.Read (deserialiseFromBytes) import qualified Data.ByteString.Lazy as BSL import qualified Data.Text as T import Control.Monad (replicateM) -- Decoder for a custom record structure data Point = Point { x :: Int, y :: Int, label :: T.Text } deriving Show decodePoint :: Decoder s Point decodePoint = do -- Expect a list of 3 elements len <- decodeListLen if len /= 3 then fail "Expected list of length 3 for Point" else Point <$> decodeInt <*> decodeInt <*> decodeString -- Decoder using token type inspection decodeFlexibleValue :: Decoder s String decodeFlexibleValue = do tokenType <- peekTokenType case tokenType of TypeUInt -> show <$> decodeWord TypeNInt -> show <$> decodeInt TypeString -> T.unpack <$> decodeString TypeBool -> show <$> decodeBool TypeNull -> "null" <$ decodeNull _ -> fail $ "Unexpected token type: " ++ show tokenType -- Decoder for indefinite-length structures decodeIntList :: Decoder s [Int] decodeIntList = do mn <- decodeListLenOrIndef case mn of Just n -> replicateM n decodeInt -- Fixed length Nothing -> decodeIndefList [] -- Indefinite length where decodeIndefList acc = do stop <- decodeBreakOr if stop then return (reverse acc) -- Indefinite length else do val <- decodeInt decodeIndefList (val : acc) -- Usage with deserialiseFromBytes main :: IO () main = do cborData <- BSL.readFile "data.cbor" case deserialiseFromBytes decodePoint cborData of Left err -> putStrLn $ "Decode error: " ++ show err Right (remaining, point) -> do print point putStrLn $ "Remaining bytes: " ++ show (BSL.length remaining) ``` -------------------------------- ### Serializing Common Haskell Types with Codec.Serialise Source: https://context7.com/well-typed/cborg/llms.txt This snippet showcases the `Serialise` instances provided by the `Codec.Serialise` module for numerous standard Haskell types. It demonstrates serializing and deserializing basic types, optionals, sums, containers (lists, maps, sets, sequences, vectors), tuples, and time types. The examples confirm that nested structures are handled automatically. Dependencies include `Codec.Serialise`, `GHC.Generics`, and various container and time modules. ```haskell {-# LANGUAGE DeriveGeneric #-} import Codec.Serialise import GHC.Generics import qualified Data.Map.Strict as Map import qualified Data.Set as Set import qualified Data.Sequence as Seq import qualified Data.Vector as V import qualified Data.Text as T import qualified Data.ByteString as BS import Data.Time (UTCTime, getCurrentTime) -- All these types have Serialise instances exampleTypes :: IO () exampleTypes = do -- Basic types let intVal :: Int = 42 let strVal :: String = "hello" let textVal :: T.Text = T.pack "world" let bytesVal :: BS.ByteString = BS.pack [1,2,3] -- Optional and sum types let maybeVal :: Maybe Int = Just 42 let eitherVal :: Either String Int = Right 100 -- Container types let listVal :: [Int] = [1, 2, 3, 4, 5] let mapVal :: Map.Map String Int = Map.fromList [("a", 1), ("b", 2)] let setVal :: Set.Set Int = Set.fromList [1, 2, 3] let seqVal :: Seq.Seq Int = Seq.fromList [1, 2, 3] let vecVal :: V.Vector Int = V.fromList [1, 2, 3] -- Tuples let tupleVal :: (Int, String, Bool) = (42, "test", True) -- Time types (encoded using CBOR tag 1000) now <- getCurrentTime let timeVal :: UTCTime = now -- All can be serialised directly print $ deserialise (serialise maybeVal) == maybeVal -- True print $ deserialise (serialise mapVal) == mapVal -- True print $ deserialise (serialise tupleVal) == tupleVal -- True -- Nested structures work automatically let nested :: Map.Map String [Maybe Int] nested = Map.fromList [("evens", [Just 2, Just 4, Nothing])] print $ deserialise (serialise nested) == nested -- True ``` -------------------------------- ### Clone cborg Git Repository Source: https://github.com/well-typed/cborg/blob/master/README.md Clones the master git repository for the cborg project. This allows developers to access the source code for development, contribution, or offline analysis. ```bash git clone https://github.com/well-typed/cborg.git ``` -------------------------------- ### Serialise Haskell Values to ByteString with cborg Source: https://context7.com/well-typed/cborg/llms.txt Demonstrates serializing and deserializing Haskell data types to/from CBOR ByteStrings using the `Serialise` type class. Requires `Codec.Serialise` and `GHC.Generics`. Supports automatic instance derivation and safe deserialization with error handling. ```haskell #{-# LANGUAGE DeriveGeneric #-} import Codec.Serialise import GHC.Generics import qualified Data.ByteString.Lazy as BSL -- Define a data type with Generic derivation data Person = Person { name :: String , age :: Int } deriving (Show, Generic) -- Derive Serialise instance automatically instance Serialise Person -- Serialise to ByteString main :: IO () main = do let alice = Person "Alice" 30 -- Encode to CBOR ByteString let encoded :: BSL.ByteString encoded = serialise alice -- Decode from CBOR ByteString let decoded :: Person decoded = deserialise encoded print decoded -- Output: Person {name = "Alice", age = 30} -- Safe deserialisation with error handling case deserialiseOrFail encoded of Left err -> putStrLn $ "Decode failed: " ++ show err Right person -> print (person :: Person) ``` -------------------------------- ### Convert JSON to CBOR and CBOR to JSON with cborg-json Source: https://context7.com/well-typed/cborg/llms.txt This snippet demonstrates how to use the `cborg-json` package to convert between Aeson's `Value` type and CBOR byte strings. It includes functions for both JSON to CBOR and CBOR to JSON conversion, handling potential errors during deserialization. Dependencies include `Codec.CBOR.JSON`, `Codec.CBOR.Write`, `Codec.CBOR.Read`, and `Data.Aeson`. ```haskell import Codec.CBOR.JSON (encodeValue, decodeValue) import Codec.CBOR.Write (toLazyByteString) import Codec.CBOR.Read (deserialiseFromBytes) import Data.Aeson (Value(..), object, (.=)) import qualified Data.Aeson as Aeson import qualified Data.ByteString.Lazy as BSL -- Convert JSON to CBOR jsonToCbor :: Value -> BSL.ByteString jsonToCbor = toLazyByteString . encodeValue -- Convert CBOR to JSON cborToJson :: BSL.ByteString -> Either String Value cborToJson bs = case deserialiseFromBytes (decodeValue False) bs of Left err -> Left (show err) Right (_, value) -> Right value main :: IO () main = do -- Create a JSON value let jsonValue = object [ "name" .= ("Alice" :: String) , "age" .= (30 :: Int) , "scores" .= ([95, 87, 92] :: [Int]) , "active" .= True ] -- Convert to CBOR let cborData = jsonToCbor jsonValue BSL.writeFile "data.cbor" cborData putStrLn $ "CBOR size: " ++ show (BSL.length cborData) ++ " bytes" -- Read JSON file and convert to CBOR jsonFile <- BSL.readFile "input.json" case Aeson.decode jsonFile of Nothing -> putStrLn "Invalid JSON" Just val -> do let cbor = jsonToCbor val BSL.writeFile "output.cbor" cbor -- Convert CBOR back to JSON cborFile <- BSL.readFile "data.cbor" case cborToJson cborFile of Left err -> putStrLn $ "Error: " ++ err Right val -> BSL.putStr (Aeson.encode val) ``` -------------------------------- ### Represent CBOR Data with Term in Haskell Source: https://context7.com/well-typed/cborg/llms.txt The `Term` type in `Codec.CBOR.Term` provides a generic Abstract Syntax Tree (AST) for representing arbitrary CBOR values. This snippet demonstrates creating, encoding, and decoding various `Term` types like integers, strings, lists, maps, bytes, tagged values, floats, booleans, and null. It uses `Codec.CBOR.Write.toLazyByteString` for encoding and `Codec.CBOR.Read.deserialiseFromBytes` for decoding. ```haskell import Codec.CBOR.Term import Codec.CBOR.Read (deserialiseFromBytes) import Codec.CBOR.Write (toLazyByteString) import qualified Data.ByteString.Lazy as BSL import qualified Data.ByteString as BS import qualified Data.Text as T -- Term represents arbitrary CBOR values exampleTerms :: IO () exampleTerms = do -- Create various Term values let intTerm = TInt 42 let stringTerm = TString (T.pack "hello") let listTerm = TList [TInt 1, TInt 2, TInt 3] let mapTerm = TMap [(TString (T.pack "name"), TString (T.pack "Alice")), (TString (T.pack "age"), TInt 30)] let byteTerm = TBytes (BS.pack [0xDE, 0xAD, 0xBE, 0xEF]) let taggedTerm = TTagged 32 (TString (T.pack "http://example.com")) let floatTerm = TDouble 3.14159 let boolTerm = TBool True let nullTerm = TNull -- Encode Term to CBOR let encoded = toLazyByteString (encodeTerm mapTerm) BSL.writeFile "term.cbor" encoded -- Decode arbitrary CBOR to Term cborData <- BSL.readFile "unknown.cbor" case deserialiseFromBytes decodeTerm cborData of Left err -> putStrLn $ "Decode error: " ++ show err Right (_, term) -> do -- Pattern match on the decoded term case term of TMap pairs -> do putStrLn "Decoded a map:" mapM_ (\(k, v) -> putStrLn $ " " ++ show k ++ " -> " ++ show v) pairs TList items -> do putStrLn "Decoded a list:" mapM_ (putStrLn . (" " ++) . show) items _ -> print term ``` -------------------------------- ### Read/Write Serialised Haskell Values to Files with cborg Source: https://context7.com/well-typed/cborg/llms.txt Provides convenient functions `writeFileSerialise` and `readFileDeserialise` for direct file I/O of serialised Haskell values. This avoids manual ByteString handling. Requires `Codec.Serialise` and `GHC.Generics` for data type serialization. ```haskell #{-# LANGUAGE DeriveGeneric #-} import Codec.Serialise import GHC.Generics data Config = Config { serverHost :: String , serverPort :: Int , debug :: Bool } deriving (Show, Generic) instance Serialise Config main :: IO () main = do let config = Config "localhost" 8080 True -- Write serialised config to file writeFileSerialise "config.cbor" config -- Read config back from file loadedConfig <- readFileDeserialise "config.cbor" :: IO Config print loadedConfig -- Output: Config {serverHost = "localhost", serverPort = 8080, debug = True} ``` -------------------------------- ### Encode CBOR Primitive Types in Haskell Source: https://context7.com/well-typed/cborg/llms.txt Demonstrates how to use `Codec.CBOR.Encoding` primitives to encode integers, floating-point numbers, strings, bytes, booleans, null, lists (fixed and indefinite length), maps, and tagged values. The encoded data is written to a file named 'primitives.cbor'. ```haskell import Codec.CBOR.Encoding import Codec.CBOR.Write (toLazyByteString) import qualified Data.ByteString.Lazy as BSL import qualified Data.Text as T -- Encode various primitive types primitiveEncodings :: IO () primitiveEncodings = do -- Integers let intEnc = encodeInt 42 <> encodeInt (-100) <> encodeInteger 12345678901234567890 -- Floating point let floatEnc = encodeFloat 3.14 <> encodeDouble 2.718281828 -- Strings and bytes let strEnc = encodeString (T.pack "Hello, CBOR!") <> encodeBytes (BSL.toStrict $ BSL.pack [0x01, 0x02, 0x03]) -- Booleans and null let boolEnc = encodeBool True <> encodeBool False <> encodeNull -- Lists (fixed length) let listEnc = encodeListLen 3 <> encodeInt 1 <> encodeInt 2 <> encodeInt 3 -- Lists (indefinite length) let listIndefEnc = encodeListLenIndef <> encodeInt 1 <> encodeInt 2 <> encodeBreak -- Maps let mapEnc = encodeMapLen 2 <> encodeString (T.pack "key1") <> encodeInt 100 <> encodeString (T.pack "key2") <> encodeInt 200 -- Tagged values (CBOR semantic tags) let taggedEnc = encodeTag 0 <> encodeString (T.pack "2024-01-15T10:30:00Z") -- Combine all encodings let combined = intEnc <> floatEnc <> strEnc <> boolEnc -- Convert to ByteString BSL.writeFile "primitives.cbor" (toLazyByteString combined) ``` -------------------------------- ### Encode CBOR to ByteString using Haskell Source: https://context7.com/well-typed/cborg/llms.txt Functions like `toLazyByteString`, `toStrictByteString`, and `toBuilder` from `Codec.CBOR.Write` convert a CBOR `Encoding` into different ByteString formats. `toLazyByteString` is suitable for large data, `toStrictByteString` for network transmission, and `toBuilder` for concatenation with other builders. ```haskell import Codec.CBOR.Encoding import Codec.CBOR.Write import qualified Data.ByteString.Lazy as BSL import qualified Data.ByteString as BS import qualified Data.ByteString.Builder as Builder buildComplexEncoding :: Encoding buildComplexEncoding = encodeMapLen 3 <> encodeString "version" <> encodeInt 1 <> encodeString "data" <> (encodeListLen 2 <> encodeInt 100 <> encodeInt 200) <> encodeString "valid" <> encodeBool True main :: IO () main = do let encoding = buildComplexEncoding -- Convert to lazy ByteString (efficient for large data) let lazyBS :: BSL.ByteString lazyBS = toLazyByteString encoding BSL.writeFile "output.cbor" lazyBS -- Convert to strict ByteString (for network transmission) let strictBS :: BS.ByteString strictBS = toStrictByteString encoding print $ BS.length strictBS -- Convert to Builder (for concatenation with other data) let builder :: Builder.Builder builder = toBuilder encoding -- Can be combined: builder <> otherBuilder ``` -------------------------------- ### Perform Incremental CBOR Decoding in Haskell Source: https://context7.com/well-typed/cborg/llms.txt The `deserialiseFromBytes` function from `Codec.CBOR.Read` decodes CBOR data from a `ByteString` while returning the remaining unconsumed bytes. This is crucial for processing streams or multiple concatenated CBOR values within a single input. It handles decoding errors by returning a `DeserialiseFailure`. ```haskell import Codec.CBOR.Read import Codec.CBOR.Term (decodeTerm, Term) import Codec.Serialise import qualified Data.ByteString.Lazy as BSL -- Decode multiple CBOR values from a single ByteString decodeMultiple :: BSL.ByteString -> IO [Term] decodeMultiple bs = go bs [] where go remaining acc | BSL.null remaining = return (reverse acc) | otherwise = case deserialiseFromBytes decodeTerm remaining of Left (DeserialiseFailure offset msg) -> do putStrLn $ "Error at offset " ++ show offset ++ ": " ++ msg return (reverse acc) Right (rest, term) -> go rest (term : acc) -- Decode with explicit Decoder decodeWithDecoder :: Serialise a => BSL.ByteString -> Either DeserialiseFailure a decodeWithDecoder bs = case deserialiseFromBytes decode bs of Left err -> Left err Right (_, value) -> Right value main :: IO () main = do -- Read file with multiple CBOR values content <- BSL.readFile "multi.cbor" terms <- decodeMultiple content putStrLn $ "Decoded " ++ show (length terms) ++ " values" mapM_ print terms ``` -------------------------------- ### Custom CBOR Encoding/Decoding for Haskell Types with cborg Source: https://context7.com/well-typed/cborg/llms.txt Enables fine-grained control over CBOR representation by implementing custom `encode` and `decode` methods using primitive combinators from `Codec.CBOR.Encoding` and `Codec.CBOR.Decoding`. Useful for complex or non-standard data structures. ```haskell #{-# LANGUAGE DeriveGeneric #-} import Codec.Serialise import Codec.Serialise.Decoding import Codec.CBOR.Encoding import Codec.CBOR.Decoding -- Sum type with multiple constructors data Animal = HoppingAnimal { animalName :: String, hoppingHeight :: Int } | WalkingAnimal { animalName :: String, walkingSpeed :: Int } | SwimmingAnimal { numberOfFins :: Int } deriving (Show, Eq) -- Custom encoding: list with tag + fields instance Serialise Animal where encode (HoppingAnimal name height) = encodeListLen 3 <> encodeWord 0 <> encode name <> encode height encode (WalkingAnimal name speed) = encodeListLen 3 <> encodeWord 1 <> encode name <> encode speed encode (SwimmingAnimal fins) = encodeListLen 2 <> encodeWord 2 <> encode fins decode = do len <- decodeListLen tag <- decodeWord case (len, tag) of (3, 0) -> HoppingAnimal <$> decode <*> decode (3, 1) -> WalkingAnimal <$> decode <*> decode (2, 2) -> SwimmingAnimal <$> decode _ -> fail "invalid Animal encoding" main :: IO () main = do let frog = HoppingAnimal "Fred" 4 let fish = SwimmingAnimal 2 -- Round-trip test print (deserialise (serialise frog) :: Animal) -- Output: HoppingAnimal {animalName = "Fred", hoppingHeight = 4} print (deserialise (serialise fish) :: Animal) -- Output: SwimmingAnimal {numberOfFins = 2} ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.