{"id":20157570,"url":"https://github.com/g4s8/go-bundle","last_synced_at":"2025-04-09T22:53:01.285Z","repository":{"id":57557137,"uuid":"319887870","full_name":"g4s8/go-bundle","owner":"g4s8","description":"Go binary bundle for typed data","archived":false,"fork":false,"pushed_at":"2021-09-21T11:28:40.000Z","size":22,"stargazers_count":7,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-09T22:52:56.275Z","etag":null,"topics":["binary","encoding","go","marshalling","serialization"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/g4s8.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-12-09T08:15:57.000Z","updated_at":"2023-12-17T20:40:27.000Z","dependencies_parsed_at":"2022-09-07T18:00:15.024Z","dependency_job_id":null,"html_url":"https://github.com/g4s8/go-bundle","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/g4s8%2Fgo-bundle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/g4s8%2Fgo-bundle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/g4s8%2Fgo-bundle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/g4s8%2Fgo-bundle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/g4s8","download_url":"https://codeload.github.com/g4s8/go-bundle/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248125638,"owners_count":21051766,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["binary","encoding","go","marshalling","serialization"],"created_at":"2024-11-13T23:46:54.772Z","updated_at":"2025-04-09T22:53:01.259Z","avatar_url":"https://github.com/g4s8.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![CI](https://github.com/g4s8/go-bundle/workflows/CI/badge.svg)](https://github.com/g4s8/go-bundle/actions?query=workflow%3ACI)\n[![GitHub release](https://img.shields.io/github/release/g4s8/go-bundle.svg?label=version)](https://github.com/g4s8/go-bundle/releases/latest)\n\n[![Hits-of-Code](https://hitsofcode.com/github/g4s8/go-bundle)](https://hitsofcode.com/view/github/g4s8/go-bundle)\n[![Lines of code](https://img.shields.io/tokei/lines/github/g4s8/go-bundle)](https://github.com/g4s8/go-bundle/tree/master/)\n\nSimple binary encoding and decoding tool, a type-safe wrapper for `encoding/binary` package.\n\nImplements `BinaryMarshaler` and `BinaryUnmarshaler` from `encoding`, supports different\n`encoding.BiteOrder`s. Errors accumulator to avoid each line error checks.\nIt could be useful to implement custom `encoding` binary protocols.\n\n# The problem\n\nGo has a package [encoding/binary](https://golang.org/pkg/encoding/binary/)\nfor binary serialization, it provides good and low-level API for encoding.\nThe problem is that it's not really handy and requires a lot of boilerplate\ncode to read and write data to stream, such as: lack of type safety (accepts\n`interface{}` params) error-checks for each line,\ncustom array/slice encoding/decoding protocols, custom nested encoding/decoding.\n\nThis library aims to solve these issues by providing type-safe\nand extended wrapper over `encoding/binary` package which reduce the amount\nof bolierplate codes and ensures type-safety.\n\nSince it uses `encoding/binary` under the hood, keep in mind that:\n\u003e This package favors simplicity over efficiency.\nClients that require high-performance serialization,\nespecially for large data structures,\nshould look at more advanced solutions such as the encoding/gob\npackage or protocol buffers.\n\n# Install\n\nAdd to imports: `\"github.com/g4s8/go-bundle\"`\n\n# Usage\n\nThe bundle package provides two main types:\n`Out` and `Inp`. `Out` (output) is used to put data into bundle\nand produce byte array from it, `Inp` (input) is used to read\ndata from bytes array.\n\n## Output\n\n### Create new bundle output\n\nThere are different factory functions to create bundle outputs:\n```go\nout := NewOut(order) // creates bundle and specify byte order\noutBE := NewBEOut() // creates bundle with big-endian byte order\noutLE := NewLEOut() // creates bundle with little-endian byte order\n```\n\n### Put data into bundle\n\nEach out bundle method has type-name suffix and accepts only\nfixed-length and strongly typed parameters:\n```go\nout := NewBEOut()\nout.PutInt32(int32(42))\nout.PutUIint64(uint64(1111111111111))\nout.PutFloat32(float32(1.4))\nout.PutBytes([]byte{0x00, 0x01, 0x02})\nout.PutString(\"hello bundle!\")\n```\n\nAlso, output accepts `encoding.BinaryMarshaler` types to put:\n`out.PutBinary(binary)`.\n\n### Nested bundles\n\nBundle can contain nested bundles, to put one bundle into another\nuse `PutBundle` method:\n```go\nparent := NewLEOut()\nnested := NewLEOut()\nparent.PutBundle(nested)\n```\n\n### Errors\n\nOutput `Put*` methods doesn't return errors, but in case of error it will be\naccumulated. It can be checked with `out.Error()` method. If error happens,\nput method won't try to put next values to internal bytes buffer.\n\n### Marshaling\n\nOutput implements `encoding.BinaryMarshaler` protocol. It can be used to\nget byte array of the bundle:\n```go\nout := NewBEOut()\nout.PutInt32(int32(42))\nbytes, err := out.MarshalBinary()\n```\n\nIt returns buffer bytes or first error.\n\n### Flip\n\n`Flip` methods creates input from output: `func (o *Out) Flip() *Inp`.\nIt can be useful for testing.\n\n## Input\n\n### Creating new input\n\nThese factory functions can be used to wrap byte array with\nbundle input type:\n```go\n\ni1 := NewInput(order) // creates input with specified order\ni1 := NewBEInput() // creates big-endian input\ni3 := NewLEInput() // creates little-endian input\ni4 := InpWrapBytes(order, bts) // creates input from bytes with order\n```\n\n### Filling input with data\n\nBundle input implements `encoding.BinaryUnmarshaler` protocol, it means\nit can be read from byte array:\n```go\ninp := NewInput(binary.BigEndian)\nerr := inp.UnmarshalBinary(data)\n```\nAlternatively, it can be constructed directly from bytes using wrap factory method:\n```go\ninp := InpWrapBytes(order, bytes)\n```\n\nInput can't be read twise, the call to `UnmarshalBinary` returns an error\nif input was already read.\n\n### Reading data from input\n\nInput bundle methods has type suffixes and accepts output reference\nparameters to read the data:\n```go\n// Reads int32\nvar i32 int32\ninp.ReadInt32(\u0026i32)\n\n// Reads byte-array\nvar bts []byte\ninp.ReadBytes(\u0026bts)\n\n// Read binary unmarshaler\n// subInput - implements `encoding.BinaryUnmarshaler`\ninp.ReadBinary(subInput)\n```\n\n### Reading nested bundles\n\n`Inp` can contain nested bundles, to read it create new empty `Inp` with\n`new(Inp)` and read it from parent bundle:\n```go\n// var parent Inp\nnested := new(Inp)\nparent.GetBundle(nested)\n```\n\n### Errors\n\nErrors are accumulated and can be accessed with `Error()` method.\nIn case of error, next read methods won't be performed.\n\n## Example\n\nAssuming you need to implement `encoding.BinaryMarshaler` and\n`encoding.BinaryUnmarshaler` for some struct. You can use `bundle`\nto do that:\n```go\nimport (\n  \"encoding/binary\"\n  \"github.com/g4s8/go-bundle\"\n  ma \"github.com/multiformats/go-multiaddr\"\n)\n\ntype Foo struct {\n  ID int32\n  Description string\n  internal []byte\n  Addr ma.Multiaddr\n}\n\nvar byteOrder = binary.BigEndian\n\nfunc (f *Foo) MarshalBinary() ([]byte, error) {\n  out := bundle.NewOut(byteOrder)\n  out.PutInt32(f.ID)\n  out.PutString(f.Description)\n  out.PutBytes(f.internal)\n  out.PutBinary(f.Addr)\n  return out.MarshalBinary()\n}\n\nfunc (f *Foo) UnmarshalBinary(data []byte) error {\n  inp := bundle.NewInput(byteOrder)\n  if err := inp.UnmarshalBinary(data); err != nil {\n         return err\n  }\n  inp.GetInt32(\u0026f.ID)\n  inp.GetString(\u0026f.Description)\n  inp.GetBytes(\u0026f.internal)\n  var rawAddr []byte\n  inp.GetBytes(\u0026rawAddr)\n  addr, err := ma.NewMultiaddrBytes(rawAddr)\n  if err != nil {\n    return err\n  }\n  f.Addr = addr\n  return nil\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fg4s8%2Fgo-bundle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fg4s8%2Fgo-bundle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fg4s8%2Fgo-bundle/lists"}