{"id":13413799,"url":"https://github.com/ghostiam/binstruct","last_synced_at":"2025-04-05T13:01:40.605Z","repository":{"id":33410760,"uuid":"154354680","full_name":"ghostiam/binstruct","owner":"ghostiam","description":"Golang binary decoder for mapping data into the structure","archived":false,"fork":false,"pushed_at":"2024-10-01T14:10:44.000Z","size":175,"stargazers_count":100,"open_issues_count":1,"forks_count":21,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-28T14:11:27.447Z","etag":null,"topics":["binary","decoder","go","golang","reader","struct","structure","unmarshaling"],"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/ghostiam.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-10-23T15:42:22.000Z","updated_at":"2025-02-24T12:16:40.000Z","dependencies_parsed_at":"2024-06-18T15:44:30.944Z","dependency_job_id":null,"html_url":"https://github.com/ghostiam/binstruct","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ghostiam%2Fbinstruct","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ghostiam%2Fbinstruct/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ghostiam%2Fbinstruct/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ghostiam%2Fbinstruct/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ghostiam","download_url":"https://codeload.github.com/ghostiam/binstruct/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247339145,"owners_count":20923012,"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","decoder","go","golang","reader","struct","structure","unmarshaling"],"created_at":"2024-07-30T20:01:49.613Z","updated_at":"2025-04-05T13:01:40.544Z","avatar_url":"https://github.com/ghostiam.png","language":"Go","readme":"[![Go Report Card](https://goreportcard.com/badge/github.com/ghostiam/binstruct)](https://goreportcard.com/report/github.com/ghostiam/binstruct) [![CodeCov](https://codecov.io/gh/ghostiam/binstruct/branch/master/graph/badge.svg)](https://codecov.io/gh/ghostiam/binstruct) [![GoDoc](https://godoc.org/github.com/ghostiam/binstruct?status.svg)](https://godoc.org/github.com/ghostiam/binstruct) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/ghostiam/binstruct/blob/master/LICENSE)\n\n# binstruct\nGolang binary decoder to structure\n\n# Install\n```go get -u github.com/ghostiam/binstruct```\n\n# Examples\n\n[ZIP decoder](examples/zip) \\\n[PNG decoder](examples/png)\n\n# Use\n\n## For struct\n\n### From file or other io.ReadSeeker:\n```go\npackage main\n\nimport (\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\t\"github.com/ghostiam/binstruct\"\n)\n\nfunc main() {\n\tfile, err := os.Open(\"testdata/file.bin\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\ttype dataStruct struct {\n\t\tArr []int16 `bin:\"len:4\"`\n\t}\n\n\tvar actual dataStruct\n\tdecoder := binstruct.NewDecoder(file, binary.BigEndian)\n\t// decoder.SetDebug(true) // you can enable the output of bytes read for debugging\n\terr = decoder.Decode(\u0026actual)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tfmt.Printf(\"%+v\", actual)\n\n\t// Output:\n\t// {Arr:[1 2 3 4]}\n}\n```\n\n### From bytes\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\n\t\"github.com/ghostiam/binstruct\"\n)\n\nfunc main() {\n\tdata := []byte{\n\t\t0x00, 0x01,\n\t\t0x00, 0x02,\n\t\t0x00, 0x03,\n\t\t0x00, 0x04,\n\t}\n\n\ttype dataStruct struct {\n\t\tArr []int16 `bin:\"len:4\"`\n\t}\n\n\tvar actual dataStruct\n\terr := binstruct.UnmarshalBE(data, \u0026actual) // UnmarshalLE() or Unmarshal()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tfmt.Printf(\"%+v\", actual)\n\n\t// Output: {Arr:[1 2 3 4]}\n}\n```\n\n## or just use reader without mapping data into the structure\n\nYou can not use the functionality for mapping data into the structure, you can use the interface to get data from the stream (io.ReadSeeker)\n\n[reader.go](reader.go)\n```go\ntype Reader interface {\n\tio.ReadSeeker\n\n\t// Peek returns the next n bytes without advancing the reader.\n\tPeek(n int) ([]byte, error)\n\n\t// ReadBytes reads up to n bytes. It returns the number of bytes\n\t// read, bytes and any error encountered.\n\tReadBytes(n int) (an int, b []byte, err error)\n\t// ReadAll reads until an error or EOF and returns the data it read.\n\tReadAll() ([]byte, error)\n\n\t// ReadByte read and return one byte\n\tReadByte() (byte, error)\n\t// ReadBool read one byte and return boolean value\n\tReadBool() (bool, error)\n\n\t// ReadUint8 read one byte and return uint8 value\n\tReadUint8() (uint8, error)\n\t// ReadUint16 read two bytes and return uint16 value\n\tReadUint16() (uint16, error)\n\t// ReadUint32 read four bytes and return uint32 value\n\tReadUint32() (uint32, error)\n\t// ReadUint64 read eight bytes and return uint64 value\n\tReadUint64() (uint64, error)\n\t// ReadUintX read X bytes and return uint64 value\n\tReadUintX(x int) (uint64, error)\n\n\t// ReadInt8 read one byte and return int8 value\n\tReadInt8() (int8, error)\n\t// ReadInt16 read two bytes and return int16 value\n\tReadInt16() (int16, error)\n\t// ReadInt32 read four bytes and return int32 value\n\tReadInt32() (int32, error)\n\t// ReadInt64 read eight bytes and return int64 value\n\tReadInt64() (int64, error)\n\t// ReadIntX read X bytes and return int64 value\n\tReadIntX(x int) (int64, error)\n\n\t// ReadFloat32 read four bytes and return float32 value\n\tReadFloat32() (float32, error)\n\t// ReadFloat64 read eight bytes and return float64 value\n\tReadFloat64() (float64, error)\n\n\t// Unmarshal parses the binary data and stores the result\n\t// in the value pointed to by v.\n\tUnmarshal(v interface{}) error\n\n\t// WithOrder changes the byte order for the new Reader\n\tWithOrder(order binary.ByteOrder) Reader\n}\n```\n\nExample:\n```go\npackage main\n\nimport (\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"log\"\n\t\n\t\"github.com/ghostiam/binstruct\"\n)\n\nfunc main() {\n\tdata := []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}\n\n\treader := binstruct.NewReaderFromBytes(data, binary.BigEndian, false)\n\n\ti16, err := reader.ReadInt16()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tfmt.Println(i16)\n\n\ti32, err := reader.ReadInt32()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tfmt.Println(i32)\n\n\tb, err := reader.Peek(4)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tfmt.Printf(\"Peek bytes: %#v\\n\", b)\n\n\tan, b, err := reader.ReadBytes(4)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tfmt.Printf(\"Read %d bytes: %#v\\n\", an, b)\n\n\tother, err := reader.ReadAll()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tfmt.Printf(\"Read all: %#v\\n\", other)\n\n\t// Output:\n\t// 258\n\t// 50595078\n\t// Peek bytes: []byte{0x7, 0x8, 0x9, 0xa}\n\t// Read 4 bytes: []byte{0x7, 0x8, 0x9, 0xa}\n\t// Read all: []byte{0xb, 0xc, 0xd, 0xe, 0xf}\n}\n```\n\n# Decode to fields\n\n```go\ntype test struct {\n\t// Read 1 byte\n\tField bool\n\tField byte\n\tField [1]byte\n\tField int8\n\tField uint8\n\n\t// Read 2 bytes\n\tField int16\n\tField uint16\n\tField [2]byte\n\n\t// Read 4 bytes\n\tField int32\n\tField uint32\n\tField [4]byte\n\n\t// Read 8 bytes\n\tField int64\n\tField uint64\n\tField [8]byte\n\n\t// You can override length\n\tField int64 `bin:\"len:2\"`\n\t// Or even use very weird byte lengths for int\n\tField int64 `bin:\"len:3\"`\n\tField int64 `bin:\"len:5\"`\n\tField int64 `bin:\"len:7\"`\n\n\t// Fields of type int, uint and string are not read automatically \n\t// because the size is not known, you need to set it manually\n\tField int    `bin:\"len:2\"`\n\tField uint   `bin:\"len:4\"`\n\tField string `bin:\"len:42\"`\n\t\n\t// Can read arrays and slices\n\tArray [2]int32              // read 8 bytes (4+4byte for 2 int32)\n\tSlice []int32 `bin:\"len:2\"` // read 8 bytes (4+4byte for 2 int32)\n\t\n\t// Also two-dimensional slices work (binstruct_test.go:307 Test_SliceOfSlice)\n\tSlice2D [][]int32 `bin:\"len:2,[len:2]\"`\n\t// and even three-dimensional slices (binstruct_test.go:329 Test_SliceOfSliceOfSlice)\n\tSlice3D [][][]int32 `bin:\"len:2,[len:2,[len:2]]\"`\n\t\n\t// Structures and embedding are also supported.\n\tStruct struct {\n\t\t...\n\t}\n\tOtherStruct Other\n\tOther // embedding\n}\n\ntype Other struct {\n\t...\n}\n```\n\n# Tags\n\n```go\ntype test struct {\n\tIgnoredField []byte `bin:\"-\"`          // ignore field\n\tCallMethod   []byte `bin:\"MethodName\"` // Call method \"MethodName\"\n\tReadLength   []byte `bin:\"len:42\"`     // read 42 bytes\n\n\t// Offsets test binstruct_test.go:9\n\tOffset      byte `bin:\"offset:42\"`      // move to 42 bytes from current position and read byte\n\tOffsetStart byte `bin:\"offsetStart:42\"` // move to 42 bytes from start position and read byte\n\tOffsetEnd   byte `bin:\"offsetEnd:-42\"`  // move to -42 bytes from end position and read byte\n\tOffsetStart byte `bin:\"offsetStart:42, offset:10\"` // also worked and equally `offsetStart:52`\n\tOffsetWithRestore byte `bin:\"offset:42, offsetRestore\"` // move to 42 bytes from current position and read byte, then restore position to the previous one (before offset)\n\n\t// Calculations supported +,-,/,* and are performed from left to right that is 2+2*2=8 not 6!!!\n\tCalcTagValue []byte `bin:\"len:10+5+2+3\"` // equally len:20\n\n\t// You can refer to another field to get the value.\n\tDataLength              int    // actual length\n\tValueFromOtherField     string `bin:\"len:DataLength\"`\n\tCalcValueFromOtherField string `bin:\"len:DataLength+10\"` // also work calculations\n\n\t// Also supported nested structures.\n\tInner struct {\n\t\tDataLength int // actual length for ValueFromInnerField and CalcValueFromInnerField\n\t}\n\tValueFromInnerField string `bin:\"len:Inner.DataLength\"`\n\tCalcValueFromInnerField string `bin:\"len:Inner.DataLength+10\"`\n\n\t// You can change the byte order directly from the tag\n\tUInt16LE uint16 `bin:\"le\"`\n\tUInt16BE uint16 `bin:\"be\"`\n\t// Or when you call the method, it will contain the Reader with the byte order you need\n\tCallMethodWithLEReader uint16 `bin:\"MethodNameWithLEReader,le\"`\n\tCallMethodWithBEReader uint16 `bin:\"be,MethodNameWithBEReader\"`\n} \n\n// Method can be:\nfunc (*test) MethodName(r binstruct.Reader) (error) {}\n// or\nfunc (*test) MethodName(r binstruct.Reader) (FieldType, error) {}\n```\n\nSee the tests and examples for more information.\n\n# License\n\nMIT License\n","funding_links":[],"categories":["Serialization","序列化","安全领域相关库","Relational Databases"],"sub_categories":["HTTP Clients","HTTP客户端","查询语"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fghostiam%2Fbinstruct","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fghostiam%2Fbinstruct","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fghostiam%2Fbinstruct/lists"}