{"id":17302327,"url":"https://github.com/coriolinus/num-runtime-fmt","last_synced_at":"2025-08-27T02:19:17.580Z","repository":{"id":54326694,"uuid":"338086600","full_name":"coriolinus/num-runtime-fmt","owner":"coriolinus","description":"Format numbers according to runtime specifications.","archived":false,"fork":false,"pushed_at":"2021-02-24T15:26:02.000Z","size":106,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-25T00:18:51.110Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/coriolinus.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":"2021-02-11T16:37:02.000Z","updated_at":"2022-05-25T07:26:26.000Z","dependencies_parsed_at":"2022-08-13T12:10:09.441Z","dependency_job_id":null,"html_url":"https://github.com/coriolinus/num-runtime-fmt","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/coriolinus/num-runtime-fmt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coriolinus%2Fnum-runtime-fmt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coriolinus%2Fnum-runtime-fmt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coriolinus%2Fnum-runtime-fmt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coriolinus%2Fnum-runtime-fmt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coriolinus","download_url":"https://codeload.github.com/coriolinus/num-runtime-fmt/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coriolinus%2Fnum-runtime-fmt/sbom","scorecard":{"id":305058,"data":{"date":"2025-08-11","repo":{"name":"github.com/coriolinus/num-runtime-fmt","commit":"9ae5b781b5655c06a19f6496bbe507e64651cc21"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.4,"checks":[{"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":"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/rust.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/coriolinus/num-runtime-fmt/rust.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/rust.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/coriolinus/num-runtime-fmt/rust.yml/main?enable=pin","Info:   0 out of   2 GitHub-owned 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":"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":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/rust.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":"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"}},{"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":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"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":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: GNU General Public License v3.0: 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":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"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":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 19 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"}}]},"last_synced_at":"2025-08-17T21:49:19.461Z","repository_id":54326694,"created_at":"2025-08-17T21:49:19.461Z","updated_at":"2025-08-17T21:49:19.461Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272280342,"owners_count":24906116,"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","status":"online","status_checked_at":"2025-08-27T02:00:09.397Z","response_time":76,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2024-10-15T11:47:13.069Z","updated_at":"2025-08-27T02:19:17.560Z","avatar_url":"https://github.com/coriolinus.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `num-runtime-fmt`\n\nFormat numbers according to runtime specifications.\n\n[![Build and Test Status](https://github.com/coriolinus/num-runtime-fmt/workflows/Build%20and%20Test/badge.svg?branch=main)](https://github.com/coriolinus/num-runtime-fmt/actions?query=branch%3Amain+workflow%3A%22Build+and+Test%22)\n\n## Why another numeric formatting crate?\n\nThis crate implements numeric formatting with a combination of properties not\nfound elsewhere:\n\n- **Runtime**: The format specifiers do not need to be known in advance\n- **Flexible**: The format specification supports nearly a superset of the\n  features of the standard library.\n- **Focused**: Keeps things simple by offering a very simple interface which can\n  format a single number at a time. More complicated formatting jobs can be\n  accomplished by passing the output into standard formatting machinery.\n\n### Alternatives\n\n- [`std::fmt`](https://doc.rust-lang.org/std/fmt/) is expressive and built into\n  the standard library. However, you must provide the format string at compile\n  time, and it can't handle digit separation.\n- [`num-format`](https://crates.io/crates/num-format) is fairly comprehensive\n  and supports `no-std` applications. However, it doesn't support non-decimal\n  output modes or arbitrary groupings.\n- [`runtime-fmt`](https://crates.io/crates/runtime-fmt) allows for runtime\n  format strings which support everything the standard library does, but it's\n  nightly-only.\n- [`fomat-macros`](https://crates.io/crates/fomat-macros) provides alternate\n  formatting macros with their own syntax, but which appear to be somewhat less\n  powerful than those of the stdlib.\n\n## Format String Reference\n\nThe formatters in this crate implement a near superset of features available in the\nformat macros provided by `std::fmt`. However, they are exclusively concerned\nwith formatting a single numeric value. Therefore, the specification language is\nsomewhat truncated: it omits both braces and the colon which precedes the format\nspecification. Therefore, where in the standard formatting machinery you might\nwrite:\n\n```rust\nlet hex_digit = format!(\"{:02x}\", 0xf0);\n```\n\nWith this library, the equivalent would be:\n\n```rust\nlet hex_digit = NumFmt::from_str(\"02x\")?.fmt(0xf0);\n```\n\n\u003e **Note**: though these formatters support a superset of features of the\n\u003e standard ones, in that anything possible with the standard formatters is\n\u003e possible with this library, they do not have a superset of the syntax: while\n\u003e the intersection is large, there are a few syntax elements legal in the\n\u003e standard formatter which are not legal for this formatter. In particular, the\n\u003e standard formatter supports named width parameters. Dynamic width parameters\n\u003e are legal in this crate, but they cannot be named.\n\n### Grammar\n\nThe gramar for the format string derives substantially from the standard library's:\n\n```text\nformat_spec := [[fill]align][sign]['#'][['0']width]['.' precision][format][separator[spacing]]\nfill := character\nalign := '\u003c' | '^' | '\u003e' | 'v'\nsign := '+' | '-'\nwidth := integer not beginning with '0'\nprecision := integer\nformat := 'b' | 'o' | 'd' | 'x' | 'X'\nseparator := '_', | ',' | ' '\nspacing := integer\n```\n\n\u003e **Note**: there is no special syntax for dynamic insertion of `with`, `precision` and `spacing`.\n\u003e Simply use `NumFmt::format_with`; the dynamic values there always override any values for those\n\u003e fields, whether set or unset in the format string.\n\n### `fill`\n\nAny single `char` which precedes an align specifier is construed as the fill\ncharacter: when `width` is greater than the actual rendered width of the number,\nthe excess is padded with this character.\n\n\u003e **Note**: Wide characters are counted according to their bit width, not their\n\u003e quantity.\n\n```rust\nlet heart = '🖤';\nassert_eq!(heart.len_utf8(), 4);\nlet fmt = NumFmt::builder().fill(heart).width(6).build();\n// Note that this renders as two characters: we requested a width of 6.\n// The number renders as a single character. The heart fills up the next 4 for a total of 5.\n// Adding an extra heart would exceed the requested width, so it only renders one.\nassert_eq!(fmt.fmt(1), \"🖤1\");\n```\n\n### `align`ment\n\n- `\u003e`: the output is right-aligned in `width` columns (default).\n- `^`: the output is centered in `width` columns.\n- `\u003c`: the output is left-aligned in `width` columns.\n- `v`: attempt to align the decimal point at column index `width`. For integers,\n  equivalent to `\u003e`.\n\n### `sign`\n\n- `-`: print a leading `-` for negative numbers, and nothing in particular for\n  positive (default)\n- `+`: print a leading `+` for positive numbers\n\n### `#`\n\nIf a `#` character is present, print a base specification before the number\naccording to its format (see `format` below).\n\n- binary: `0b`\n- octal: `0o`\n- decimal: `0d`\n- hex: `0x`\n\nThis base specification counts toward the width of the number:\n\n```rust\nassert_eq!(NumFmt::from_str(\"#04b\").unwrap().fmt(2), \"0b10\");\n```\n\n### `0`\n\nEngage the zero handler.\n\nThe zero handler overrides the padding specification to `0`, and\ntreats pad characters as part of the number, in contrast\nto the default behavior which treats them as arbitrary spacing.\n\n## Examples\n\n```rust\n// sign handling\nassert_eq!(NumFmt::from_str(\"-03\").unwrap().fmt(-1).unwrap(),   \"-01\");\nassert_eq!(NumFmt::from_str(\"0\u003e-3\").unwrap().fmt(-1).unwrap(), \"-001\");\n```\n\n```rust\n// separator handling\nassert_eq!(NumFmt::from_str(\"0\u003e7,\").fmt(1).unwrap(), \"0000001\");\nassert_eq!(NumFmt::from_str(\"07,\").fmt(1).unwrap(),  \"000,001\");\n```\n\n### `width`\n\nThis is a parameter for the \"minimum width\" that the format should take up. If\nthe value's string does not fill up this many characters, then the padding\nspecified by fill/alignment will be used to take up the required space (see\n`fill` above).\n\nWhen using the `$` sigil instead of an explicit width, the width can be set\ndynamically:\n\n```rust\nassert_eq!(NumFmt::from_str(\"-^$\").unwrap().fmt_with(1, Dynamic::width(5)), \"--1--\");\n```\n\nIf an explicit width is not provided, defaults to 0.\n\n### `precision`\n\nHow many digits after the decimal point are printed. Note that integers can be forced\nto emit decimal places with this modifier.\n\nIf an explicit precision is not provided, defaults to emitting all post-decimal\ndigits emitted by the underlying type.\n\n```rust\nassert_eq!(NumFmt::from_str(\".2\").unwrap().fmt(3.14159).unwrap(), \"3.14\");\nassert_eq!(NumFmt::from_str(\".7\").unwrap().fmt(3.14159).unwrap(), \"3.1415900\");\n```\n\nIf the requested precision exceeds the native precision available to this number,\nthe remainder is always filled with `'0'`, even if `fill` is specified:\n\n```rust\nassert_eq!(NumFmt::from_str(\"-\u003c6.2\").unwrap().fmt(1.0_f32).unwrap(), \"1.00--\");\n```\n\n### `format`\n\n- `b`: Emit this number's binary representation\n- `o`: Emit this number's octal representation\n- `d`: Emit this number's decimal representation (default)\n- `x`: Emit this number's hexadecimal representation with lowercase letters\n- `X`: Emit this number's hexadecimal representation with uppercase letters\n\n\u003e **Note**: This is one of a few areas where the standard library has\n\u003e capabilities this library does not: it supports some other numeric formats.\n\u003e Pull requests welcomed to bring this up to parity.\n\n### `separator`\n\nA separator is a (typically non-numeric) character inserted between groups of digits to make\nit easier for humans to parse the number when reading. Different separators may\nbe desirable in different contexts.\n\n- `_`: Separate numeric groups with an underscore\n- `,`: Separate numeric groups with a comma\n- ` ` (space char): Separate numeric groups with a space\n\nBy default, numeric groups are not separated. It is not possible to explicitly\nspecify that numeric groups are not separated when using a format string.\nHowever, this can be specified when building the formatter via builder.\n\nWyhen using the builder to explicitly set formatter options, it is also possible\nto separate numeric groups with an arbitrary `char`. This can be desirable to\ni.e. support German number formats, which use a `.` to separate numeric groups\nand a `,` as a decimal separator.\n\n### `spacing`\n\nSpacing determines the number of characters in each character group. It is only\nof interest when the separator is set. The default spacing is 3.\n\nApparently some cultures separate numeric digits with a non-constant group size.\nPlease file an issue if this feature is important to you.\n\n### Decimal separator\n\nWhen using the builder to explicitly set formatter options, it is possible to\nset the decimal separator to any `char`. This can be desirable to i.e. support\nGerman number formats, which use a `.` to separate numeric groups and a `,` as a\ndecimal separator.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoriolinus%2Fnum-runtime-fmt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcoriolinus%2Fnum-runtime-fmt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoriolinus%2Fnum-runtime-fmt/lists"}