{"id":21736379,"url":"https://github.com/kyza/internal","last_synced_at":"2025-03-21T00:27:39.379Z","repository":{"id":203382830,"uuid":"709403828","full_name":"Kyza/internal","owner":"Kyza","description":"Internal fields in Rust.","archived":false,"fork":false,"pushed_at":"2024-01-13T04:30:16.000Z","size":17,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"trunk","last_synced_at":"2025-02-28T03:52:03.520Z","etag":null,"topics":["features","internal","macro","private","proc-macro","proc-macro-attributes","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","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/Kyza.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":"2023-10-24T16:41:44.000Z","updated_at":"2024-01-14T12:52:16.000Z","dependencies_parsed_at":null,"dependency_job_id":"d1f0072a-51f0-434d-9cef-07ddbccd2926","html_url":"https://github.com/Kyza/internal","commit_stats":null,"previous_names":["kyza/internal"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kyza%2Finternal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kyza%2Finternal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kyza%2Finternal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kyza%2Finternal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Kyza","download_url":"https://codeload.github.com/Kyza/internal/tar.gz/refs/heads/trunk","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244715168,"owners_count":20497979,"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":["features","internal","macro","private","proc-macro","proc-macro-attributes","rust"],"created_at":"2024-11-26T05:18:31.906Z","updated_at":"2025-03-21T00:27:39.360Z","avatar_url":"https://github.com/Kyza.png","language":"Rust","readme":"# internal\n\nPrivate fields were a mistake.\n\n## What?\n\nOk, maybe that's a bit of an exaggeration.\n\nPrivate fields aren't bad; they have a purpose:\n\n1. To allow library developers to make breaking changes to things without \n   making major [semver](https://semver.org/) jumps.\n2. To prevent consumers from accidentally causing UB.\n3. To enable compiler optimizations.\n\nBut there's a better way.\n\nThe main problem with private fields is, well, it makes things private. \nIt's too easy to lock potentially useful functionality away from your users.\n\nA solution to that problem is internal fields, but Rust doesn't have that \nfeature. This crate brings it to Rust via a proc macro and a feature flag.\n\n### How do internal fields work?\n\nBy default, internal fields can't be accessed, but they can be enabled and \nused when absolutely necessary.\n\nIt's a balanced solution to both ease of library development and freedom \nof library usage. It's easy to tell what could change, but nobody's \nlimited or burdened. On top of all this, the compiler can still take \nadvantage of performance improvements when internal fields aren't accessed.\n\nThe `internal` crate does it \"the Rust way\" by exposing the fields only \nwhen the `\"internal\"` feature for the library is enabled. It also adds a \ndoc comment warning to the top of all internal fields to make it clear \nwhen something is internal.\n\n## Usage\n\n```bash\ncargo add internal\n```\n\nTo mark something as internal, use the `internal` proc macro. It \neffectively replaces private fields because those are useless when \ninternal fields exist.\n\nThe macro works recursively to mark everything under it that's private as \ninternal instead. So if you define `#[internal] mod stuff {...}`, anything \ninside and including `stuff` that's private will become internal. If you \nwere to make `stuff` public, it would always be public itself, but still \napply internal recursively.\n\n### `your_lib`\n\n```rs\nuse internal::internal;\n\n#[internal]\nfn internal_fn(arg: InternalStruct) {\n\t// ...\n}\n\n#[internal]\n#[derive(Clone)]\nstruct InternalStruct {\n\tfield: PrivateThing\n}\n\n#[internal]\nmod internal_mod {\n   pub struct PublicStruct {\n      internal_field: PublicThing\n   }\n}\n```\n\n### `consumer`\n\n```toml\n# Cargo.toml\n\nyour_lib = { features = [\"internal\"] }\n```\n```rs\n// mod.rs\n\n// If the `internal` feature is explicitly enabled,\n// anything marked as internal will become public.\nuse your_lib::{internal_fn, InternalStruct, internal_mod};\n\ninternal_fn(InternalStruct {\n\tfield: ...\n});\n\n// Everything gets publicized recursively.\nprivate_mod::PublicStruct {\n\tinternal_field: ...\n}\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkyza%2Finternal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkyza%2Finternal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkyza%2Finternal/lists"}