{"id":15018350,"url":"https://github.com/dreamacro/protobytes","last_synced_at":"2025-04-24T00:23:23.387Z","repository":{"id":152043705,"uuid":"616936624","full_name":"Dreamacro/protobytes","owner":"Dreamacro","description":null,"archived":false,"fork":false,"pushed_at":"2025-03-22T14:29:55.000Z","size":41,"stargazers_count":21,"open_issues_count":0,"forks_count":34,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-21T18:21:32.986Z","etag":null,"topics":["bytes","golang","io"],"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/Dreamacro.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,"zenodo":null}},"created_at":"2023-03-21T11:40:22.000Z","updated_at":"2025-03-22T14:29:59.000Z","dependencies_parsed_at":null,"dependency_job_id":"f57d0c73-5ad4-4f3b-a40c-d99b9df05bc9","html_url":"https://github.com/Dreamacro/protobytes","commit_stats":{"total_commits":13,"total_committers":2,"mean_commits":6.5,"dds":0.07692307692307687,"last_synced_commit":"0bbf144b9b9a3aef269bf659689737a968ea37cf"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dreamacro%2Fprotobytes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dreamacro%2Fprotobytes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dreamacro%2Fprotobytes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dreamacro%2Fprotobytes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Dreamacro","download_url":"https://codeload.github.com/Dreamacro/protobytes/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250536395,"owners_count":21446726,"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":["bytes","golang","io"],"created_at":"2024-09-24T19:51:52.038Z","updated_at":"2025-04-24T00:23:23.335Z","avatar_url":"https://github.com/Dreamacro.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Protobytes\n\nProtobytes is a Go library inspired by Rust's crate bytes. It provides a series of methods for big-endian and little-endian number operations, as well as a helper for `io.Reader`.\n\n## Purpose\n\nThe goal of this library is to provide an easy-to-use `bytes.Buffer`. However, it has been split into `BytesReader` and `BytesWriter`, which perform similarly to using `bytes.Buffer` directly.\n\nWhen using `bytes.Buffer`, `binary.Write` has poor performance and unnecessary allocation. Instead, you can use the methods provided by protobytes.\n\n## Usage\n\n`BytesReader` and `BytesWriter` are similar to `bytes.Buffer`, but they are not thread-safe. `bytes.Buffer`, `binary.Write` and `[]byte` conversion is very easy and cheap.\n\n```go\nbuf := make([]byte, 0, 1024)\nw := BytesWriter(buf)\nw.ReadFull(rand.Reader, 64)\nw.PutUint8(0x01)\nw.PutUint16be(0x0203)\n\nr := BytesReader(w.Bytes())\nrandomBytes, r := r.SplitAt(64) // split to two BytesReader\nr.ReadUint8() // auto step forward\nr.ReadUint16be()\n```\n\nexample for parse proxy protocol v2 using `BytesReader`:\n\n```go\nhexStr := \"0d0a0d0a000d0a515549540a20120c000c22384eac10000104d21f90\"\nbuf, _ := hex.DecodeString(hexStr)\n\nr := BytesReader(buf)\n\nif r.Len() \u003c 16 {\n    panic(\"short buffer\")\n}\n\nsign, r := r.SplitAt(12)\nif !bytes.Equal(signature, sign) {\n    panic(\"invalid signature\")\n}\n\nheader := \u0026Header{}\n\nswitch command := r.ReadUint8(); command {\ncase LOCAL, PROXY:\n    header.Command = command\ndefault:\n    panic(fmt.Errorf(\"invalid command %x\", command))\n}\n\nswitch protocol := r.ReadUint8(); protocol {\ncase UNSPEC, TCPOverIPv4, UDPOverIPv4, TCPOverIPv6, UDPOverIPv6, UNIXStream, UNIXDatagram:\n    header.TransportProtocol = protocol\ndefault:\n    panic(fmt.Errorf(\"invalid protocol %x\", protocol))\n}\n\nlength := r.ReadUint16le()\nswitch length {\ncase lengthIPv4, lengthIPv6, lengthUnix:\ndefault:\n    panic(fmt.Errorf(\"invalid length %x\", length))\n}\n\nif r.Len() \u003c int(length) {\n    panic(\"short buffer\")\n}\n\nswitch length {\ncase lengthIPv4:\n    srcAddr := r.ReadIPv4()\n    dstAddr := r.ReadIPv4()\n    srcPort := r.ReadUint16be()\n    dstPort := r.ReadUint16be()\n\n    header.SourceAddr = netip.AddrPortFrom(srcAddr, srcPort)\n    header.DestinationAddr = netip.AddrPortFrom(dstAddr, dstPort)\ncase lengthIPv6:\n    srcAddr := r.ReadIPv6()\n    dstAddr := r.ReadIPv6()\n    srcPort := r.ReadUint16be()\n    dstPort := r.ReadUint16be()\n\n    header.SourceAddr = netip.AddrPortFrom(srcAddr, srcPort)\n    header.DestinationAddr = netip.AddrPortFrom(dstAddr, dstPort)\ndefault:\n    panic(fmt.Errorf(\"unsupported protocol %x\", length))\n}\n\nfmt.Printf(\"%+v\\n\", header)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdreamacro%2Fprotobytes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdreamacro%2Fprotobytes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdreamacro%2Fprotobytes/lists"}