{"id":37107175,"url":"https://github.com/ctx42/convert","last_synced_at":"2026-01-14T12:53:20.611Z","repository":{"id":328348125,"uuid":"1115151780","full_name":"ctx42/convert","owner":"ctx42","description":"Go 32bit and 64bit safe conversions between types.","archived":false,"fork":false,"pushed_at":"2026-01-02T12:40:25.000Z","size":224,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-01-08T15:46:44.829Z","etag":null,"topics":["go","golang","golang-library","security"],"latest_commit_sha":null,"homepage":"https://blog.ctx42.com","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/ctx42.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-12T12:18:09.000Z","updated_at":"2026-01-02T12:40:29.000Z","dependencies_parsed_at":"2026-01-02T23:03:25.492Z","dependency_job_id":null,"html_url":"https://github.com/ctx42/convert","commit_stats":null,"previous_names":["ctx42/convert"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/ctx42/convert","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ctx42%2Fconvert","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ctx42%2Fconvert/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ctx42%2Fconvert/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ctx42%2Fconvert/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ctx42","download_url":"https://codeload.github.com/ctx42/convert/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ctx42%2Fconvert/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28420814,"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":["go","golang","golang-library","security"],"created_at":"2026-01-14T12:53:20.011Z","updated_at":"2026-01-14T12:53:20.606Z","avatar_url":"https://github.com/ctx42.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Go Report Card](https://goreportcard.com/badge/github.com/ctx42/convert)](https://goreportcard.com/report/github.com/ctx42/convert)\n[![GoDoc](https://img.shields.io/badge/api-Godoc-blue.svg)](https://pkg.go.dev/github.com/ctx42/convert)\n![Tests](https://github.com/ctx42/convert/actions/workflows/go.yml/badge.svg?branch=master)\n\n\u003c!-- TOC --\u003e\n  * [Installation](#installation)\n  * [Converters](#converters)\n  * [Converter Registry](#converter-registry)\n  * [Converter Types](#converter-types)\n  * [AnyToXXX Converters.](#anytoxxx-converters)\n  * [Register Custom Converters](#register-custom-converters)\n  * [Customize Converters](#customize-converters)\n  * [32bit vs. 64bit Systems](#32bit-vs-64bit-systems)\n\u003c!-- TOC --\u003e\n\n**convert** is a lightweight Go library for safe type conversions, preventing\ntruncation, overflow, or semantic loss when converting between types. \n\nIt has support for 32-bit and 64-bit systems when converting numeric types.   \n\n## Installation\n\nInstall using `go get`:\n\n```bash\ngo get github.com/ctx42/convert\n```\n\n## Converters\n\nUse converter functions directly.\n\n```go\n// Successful conversion.\nui8, err := convert.IntToUint8(42)\nfmt.Printf(\"convert.IntToUint8 output: %[1]T(%[1]d) error: %v\\n\", ui8, err)\n\n// Value too big for uint8.\nui8, err = convert.IntToUint8(420)\nfmt.Printf(\"convert.IntToUint8 output: %[1]T(%[1]d) error: %v\\n\", ui8, err)\n\n// Unsafe conversion.\nf32, err := convert.IntToFloat32(convert.Float32SafeIntMax + 1)\nfmt.Printf(\"convert.IntToUint8 output: %[1]T(%[1]g) error: %v\\n\", f32, err)\n\n// Output:\n// convert.IntToUint8 output: uint8(42) error: \u003cnil\u003e\n// convert.IntToUint8 output: uint8(0) error: int value out of range for uint8\n// convert.IntToUint8 output: float32(0) error: int value out of safe range for float32\n```\n\nPackage `convert` provides more than 200 converter functions between numeric\ntypes:\n\n- `uint`\n- `uint8`\n- `uint16`\n- `uint32`\n- `uint64`\n- `int`\n- `int8`\n- `int16`\n- `int32`\n- `int64`\n- `float32`\n- `float64`\n- `byte`\n- `rune`\n- `uintqptr`\n- `time.Duration`\n\nAs well as converters implemented only between specific type pairs:\n\n- `convert.StringToDuration`\n- `convert.StringToString`\n- `convert.StringToTime` - string must be in `time.RFC3339Nano` format.\n\nAll of them pairs are automatically registered in the package-level registry.\n\n## Converter Registry\n\nTo get a converter function for a pair of types at runtinme use `Lookup`\nfunction.\n\n```go\ncnv := convert.Lookup[int, uint8]()\n\n// Chack cnv is not nil.\n\nhave, err := cnv(42)\n\n// Check conversion error.\n\nfmt.Printf(\"output: %[1]T(%[1]d); error: %v\", have, err)\n// Output:\n// output: uint8(42); error: \u003cnil\u003e\n```\n\nIt returns a non-nil converter if the pair has been registered in the \npackage-level registry.\n\n## Converter Types\n\nAll the converter functions provided by the package match generic `FromTo` type. \n\n```go\n// FromTo represents a converter function that attempts lossless conversion of\n// a value from the type \"From\" to the \"To\" type. On success, it returns the\n// converted value and a nil error. On failure (e.g., truncation, underflow,\n// overflow, or semantic loss), it returns the zero value of \"To\" along with a\n// non-nil error describing the issue.\ntype FromTo[From, To any] func(from From) (to To, err error)\n\n// AnyToAny is a non-generic version of [FromTo]. The behavior is exactly the\n// same in terms of error handling.\ntype AnyToAny func(form any) (to any, err error)\n```\n\nAdditionally, package defines non-generic `AnyToAny` type. Converter functions\ncan be adapted to it with a helper.\n\n```go\nvar cnv func(any) (any, error)\n\ncnv = convert.ToAnyAny(convert.Uint8ToUint8)\n\nhave, err := cnv(\"wrong\")\n\nfmt.Printf(\"output: %[1]T(%[1]d); error: %v\", have, err)\n// Output:\n// output: uint8(0); error: invalid type: expected uint8, got string\n```\n\n## AnyToXXX Converters.\n\nModule also provides a set of functions which can convert `any` type to a given\ntype:\n\n- `AnyToByte`\n- `AnyToDuration`\n- `AnyToFloat32`\n- `AnyToFloat64`\n- `AnyToInt`\n- `AnyToInt8`\n- `AnyToInt16`\n- `AnyToInt32`\n- `AnyToInt64`\n- `AnyToUint`\n- `AnyToUint8`\n- `AnyToUint16`\n- `AnyToUint32`\n- `AnyToUint64`\n- `AnyToUintptr`\n- `AnyToRune`\n\n## Register Custom Converters\n\n```go\ntype A struct{ val int8 }\ntype B struct{ val int }\n\n// Custom converter function matching [convert.Converter] signature.\nmy := func(from A) (to B, err error) {\n    return B{val: int(from.val)}, nil\n}\n\n// Register a converter function between types A and B.\nold := convert.Register(my)\n\n// If there was already a converter for that source-destination type pair,\n// it will be returned, nil otherwise.\n_ = old\n\n// Lookup converter registered converter.\ncnv := convert.Lookup[A, B]()\n\n// Run conversion.\nhave, err := cnv(A{42})\n\nfmt.Printf(\"output: %[1]T(%[1]d); error: %v\", have, err)\n// Output:\n// output: convert_test.B({42}); error: \u003cnil\u003e\n```\n\n## Customize Converters\n\nSome converters, like `convert.StringToTime`, are added to package-level\nregistry with sane defaults but you can customize them by overwriting the\ndefeult configuration.\n\n```go\n// Register a converter function between types A and B.\ndef := convert.Register(convert.StringToTime(time.Kitchen))\n\n// The default converter is returned in case you want to restore it.\ndefer convert.Register(def)\n\n// Lookup converter registered converter.\ncnv := convert.Lookup[string, time.Time]()\n\n// Run conversion.\nhave, err := cnv(\"4:20AM\")\n\nfmt.Printf(\"output: %s; error: %v\", have, err)\n// Output:\n// output: 0000-01-01 04:20:00 +0000 UTC; error: \u003cnil\u003e\n```\n\n## 32bit vs. 64bit Systems\n\nIn cases where its necessary module implements separate boundary checks for\n32-bit and 64-bit systems. See files in [convert](pkg/convert) directory with\n`_32bit` and `_64bit` strings in their filenames.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fctx42%2Fconvert","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fctx42%2Fconvert","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fctx42%2Fconvert/lists"}