{"id":37100080,"url":"https://github.com/pauloavelar/go-tlv","last_synced_at":"2026-01-14T12:12:10.202Z","repository":{"id":37624500,"uuid":"347415508","full_name":"pauloavelar/go-tlv","owner":"pauloavelar","description":"Light TLV Decoder Library for Go","archived":false,"fork":false,"pushed_at":"2023-06-20T13:34:14.000Z","size":59,"stargazers_count":17,"open_issues_count":3,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2023-07-27T07:59:42.759Z","etag":null,"topics":["decoder","go","golang","parser","tlv"],"latest_commit_sha":null,"homepage":"https://pkg.go.dev/github.com/pauloavelar/go-tlv","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/pauloavelar.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null}},"created_at":"2021-03-13T16:06:09.000Z","updated_at":"2023-07-24T06:10:42.000Z","dependencies_parsed_at":"2023-02-08T04:32:02.000Z","dependency_job_id":null,"html_url":"https://github.com/pauloavelar/go-tlv","commit_stats":null,"previous_names":[],"tags_count":4,"template":null,"template_full_name":null,"purl":"pkg:github/pauloavelar/go-tlv","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pauloavelar%2Fgo-tlv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pauloavelar%2Fgo-tlv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pauloavelar%2Fgo-tlv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pauloavelar%2Fgo-tlv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pauloavelar","download_url":"https://codeload.github.com/pauloavelar/go-tlv/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pauloavelar%2Fgo-tlv/sbom","scorecard":{"id":723309,"data":{"date":"2025-08-11","repo":{"name":"github.com/pauloavelar/go-tlv","commit":"71244a52fb3c0df42f4e7c797f82a6c1215037db"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.6,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 0/13 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Security-Policy","score":4,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Warn: no linked content found","Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1","Info: Found text in security policy: SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/pauloavelar/go-tlv/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/pauloavelar/go-tlv/ci.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/pauloavelar/go-tlv/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/pauloavelar/go-tlv/ci.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:30: update your workflow using https://app.stepsecurity.io/secureworkflow/pauloavelar/go-tlv/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/pauloavelar/go-tlv/codeql.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/pauloavelar/go-tlv/codeql.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/pauloavelar/go-tlv/codeql.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:26: update your workflow using https://app.stepsecurity.io/secureworkflow/pauloavelar/go-tlv/codeql.yml/main?enable=pin","Info:   0 out of   7 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   2 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'contents' permission set to 'read': .github/workflows/codeql.yml:18","Info: jobLevel 'actions' permission set to 'read': .github/workflows/codeql.yml:17","Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Warn: no topLevel permission defined: .github/workflows/codeql.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":7,"reason":"SAST tool detected but not run on all commits","details":["Info: SAST configuration detected: CodeQL","Warn: 0 commits out of 30 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-22T12:01:12.472Z","repository_id":37624500,"created_at":"2025-08-22T12:01:12.472Z","updated_at":"2025-08-22T12:01:12.472Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28419649,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T10:47:48.104Z","status":"ssl_error","status_checked_at":"2026-01-14T10:46:19.031Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["decoder","go","golang","parser","tlv"],"created_at":"2026-01-14T12:12:09.605Z","updated_at":"2026-01-14T12:12:10.193Z","avatar_url":"https://github.com/pauloavelar.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Go TLV\n\n[![go version](https://img.shields.io/github/go-mod/go-version/pauloavelar/go-tlv)](https://github.com/pauloavelar/go-tlv/blob/main/go.mod)\n[![go docs](https://pkg.go.dev/badge/github.com/pauloavelar/go-tlv.svg)](https://pkg.go.dev/github.com/pauloavelar/go-tlv)\n[![license](https://img.shields.io/github/license/pauloavelar/go-tlv)](https://github.com/pauloavelar/go-tlv/blob/main/LICENSE)\n[![build](https://img.shields.io/github/actions/workflow/status/pauloavelar/go-tlv/ci.yml?branch=main)](https://github.com/pauloavelar/go-tlv/actions/workflows/ci.yml)\n[![codecov](https://codecov.io/gh/pauloavelar/go-tlv/branch/main/graph/badge.svg?token=4V15TQTKRR)](https://codecov.io/gh/pauloavelar/go-tlv)\n[![open issues](https://img.shields.io/github/issues-raw/pauloavelar/go-tlv)](https://github.com/pauloavelar/go-tlv/issues)\n\n## What is TLV?\n\n**Tag-Length-Value (TLV)** is a binary encoding scheme used for data transport.\n\n### Main advantages\n\n* Very flexible, easy to extend and change as needed\n* Messages can be easily decoded/displayed as a hierarchical tree-like structure\n* New tags can be added/moved without breaking decoder compatibility\n* Searching for specific tags in long payloads is easy and efficient\n\n### Format\n\nThere are many implementations of the scheme. The example below is one of them:\n\n```\n00 0f   # 2 bytes reserved for the tag ID\n00 04   # 2 bytes reserved for the length\n01 02   # As many bytes as informed by the\n03 04   # length value\n```\n\nThe **value** itself can be any binary format, such as numerical representations, strings and even\nother TLV messages. See [data_test.go](https://github.com/pauloavelar/go-tlv/blob/main/tlv/data_test.go)\nfor an example of a complex structure.\n\n\u003e It is up to the parser to know the **value** type and format based on the **tag**.\n\n## Features\n\n### Byte array decoding as multiple TLV nodes\n\n```go\ndata := []byte{0x00, 0x01, 0x02 /* ... */}\n\nnodes, err := tlv.DecodeBytes(data)\nif err != nil {\n    panic(err) // invalid payload length vs bytes available\n}\n\nnodes.HasTag(0x0123)        // returns a bool with the tag presence\nnodes.GetByTag(0x0f2a)      // returns a filtered Nodes structure\nnodes.GetFirstByTag(0xabcd) // returns a Node structure with value accessors \n```\n\n### Byte array decoding as a single TLV node\n\n```go\ndata := []byte{0x00, 0x01, 0x02 /* ... */}\n\nn, err := tlv.DecodeSingle(data)\nif err != nil {\n    panic(err) // invalid payload length vs bytes available\n}\n\nn.String()          // returns a base64 representation of the raw message\nn.GetNodes()        // parses the value as TLV and returns a Nodes structure (or error)\nn.GetUint8()        // parses the value as uint8 (returns error if value is too small)\nn.GetPaddedUint8()  // parses the value as uint8 and pads it if too small\n\n// all available types: bool, uint8, uint16, uint32, uint64, string, time.Time and Nodes\n```\n\n### Custom Decoder with different sizes and endianness\n\nThe public functions exposed in the `tlv` package use a **standard decoder** with tags and\nlengths always taking 2 bytes per node, and the bytes are parsed using `binary.BigEndian`\nas the `ByteOrder`.\n\nIn order to decode messages with different configuration, there is Decoder constructor:\n\n```go\ndecoder, err := tlv.CreateDecoder(4, 4, binary.LittleEndian)\n```\n\n\u003e The constructor validates the tag and length sizes, as they must be between `1` and `8`.\n\n### Supported types\n\n| Type     | Max Length (bytes) | Notes                                                             |\n|----------|-------------------:|-------------------------------------------------------------------|\n| `bool`   |                  1 | Any **non-zero** value is treated as `true`                       | \n| `uint8`  |                  1 |                                                                   |\n| `uint16` |                  2 |                                                                   |\n| `uint32` |                  4 |                                                                   |\n| `uint64` |                  8 |                                                                   |\n| `Time`   |                  8 | Value is parsed as padded `uint64` and then as **Unix** (seconds) |\n| `string` |      **Unlimited** | Value is parsed as **UTF-8**                                      |\n| `Nodes`  |      **Unlimited** |                                                                   |\n\n\u003e If the **value** is bigger than the **max length**, only the first _n_ bytes are used.\n\n## Important details\n\n### Tags are non-unique in TLV messages\n\nWhen parsing a value to multiple nodes, tags can be **repeated** and will be returned by the decoder.\nUse `Nodes#GetByTag(tlv.Tag)` and `Nodes#GetFirstByTag(tlv.Tag)` to fetch **all** or **one** node,\nrespectively.\n\n#### Example:\n\n```yaml\n# Visual representation of a repeated tag in an object-like payload\nmessage:\n  - object:\n      - repeated_tag: a  # this will be a node \n      - repeated_tag: b  # this will be another node\n```\n\n### The decoder supports multiple root level messages\n\nAfter reading a TLV-encoded message from a byte-array, when using `tlv.DecodeBytes([]byte)` the parser\nwill continue reading the array until it reaches the end. The returned structure will have **all the\nnodes** found in the payload.\n\n\u003e ⚠️\u0026nbsp; The decoder works in an all or none strategy when dealing with multiple messages.\n\n### Manually-created nodes use the default decoder configuration\n\nWhen a `tlv.Node` is created by declaring the struct, all methods that require context, such as `GetNodes`\nor `GetUint8` (or any other integer parser), will use the **standard decoder** definitions. See above for\nmore details on the decoder. To create a node with custom decoder configuration, first create a decoder\nand call the `NewNode` method on it.\n\n\n```go\nvar node tlv.Node\n\nnode = tlv.Node{Tag: Tag(0x1234), Value: []byte{1}}\nnode.GetNodes() // uses the standard decoder configuration\n\ncustomDecoder := tlv.MustCreateDecoder(1, 1, binary.LittleEndian)\nnode = customDecoder.NewNode(Tag(0x1234), []byte{1})\nnode.GetNodes() // uses the customDecoder configuration\n```\n\n## Caveats\n\n### No bit parity or checksum\n\nThe encoding scheme itself does *not* provide **bit parity** or **checksum** to ensure the integrity\nof received payloads. It is up to the upper layer or to the payload design to add these features.\n\n### Errors with multiple messages are hard to pinpoint\n\nThe bigger the payload, more likely errors will *not* be identified by the parser. The **only**\nfailproof hint of a malformed payload is a mismatch between the read length and the remaining bytes\nin the stream. When that happens, a reading error may have happened *anywhere* in the payload, which\nmeans none of it can be trusted.\n\n\u003e ⚠️\u0026nbsp; If by the end of the stream there is a mismatch between the **provided length** and the\n\u003e **remaining bytes**, the whole payload is invalidated, and the decoder will return an error,\n\u003e **regardless of how many successful messages it has read**.\n\n## Changelog\n\n* **`v1.1.0`** (2023-06-01)\n  * [#23](https://github.com/pauloavelar/go-tlv/pull/23): nil pointer errors on manually-created nodes\n    * fix panics when calling value getters on a node without a decoder reference\n    * provide functions to create a Node with the proper configuration (standard or custom)\n\n* **`v1.0.0`** (2022-07-01)\n  * **Breaking** change: parser has been renamed to decoder\n  * [#10](https://github.com/pauloavelar/go-tlv/issues/10): add support to custom tag and length sizes\n  * [#11](https://github.com/pauloavelar/go-tlv/issues/11): add support to custom endianness (byte order)\n\n* **`v1.0.0-alpha1`** (2021-03-14)\n  * First release with basic parsing support\n  * ⚠️\u0026nbsp; Methods and structs may change completely \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpauloavelar%2Fgo-tlv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpauloavelar%2Fgo-tlv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpauloavelar%2Fgo-tlv/lists"}