{"id":20384931,"url":"https://github.com/d-e-s-o/cell","last_synced_at":"2025-04-12T09:26:08.820Z","repository":{"id":57545320,"uuid":"151266275","full_name":"d-e-s-o/cell","owner":"d-e-s-o","description":"A replacement of std::cell::RefCell adding advanced support for mapping borrows.","archived":false,"fork":false,"pushed_at":"2021-06-28T14:45:19.000Z","size":62,"stargazers_count":8,"open_issues_count":1,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-26T04:24:04.756Z","etag":null,"topics":["cell","rust","rust-crate","rust-library","std"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/d-e-s-o.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-10-02T14:15:05.000Z","updated_at":"2022-01-09T16:41:56.000Z","dependencies_parsed_at":"2022-09-16T23:21:59.664Z","dependency_job_id":null,"html_url":"https://github.com/d-e-s-o/cell","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d-e-s-o%2Fcell","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d-e-s-o%2Fcell/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d-e-s-o%2Fcell/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d-e-s-o%2Fcell/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/d-e-s-o","download_url":"https://codeload.github.com/d-e-s-o/cell/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248448103,"owners_count":21105236,"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":["cell","rust","rust-crate","rust-library","std"],"created_at":"2024-11-15T02:30:40.373Z","updated_at":"2025-04-12T09:26:08.783Z","avatar_url":"https://github.com/d-e-s-o.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![pipeline](https://gitlab.com/d-e-s-o/cell/badges/master/pipeline.svg)](https://gitlab.com/d-e-s-o/cell/commits/master)\n[![crates.io](https://img.shields.io/crates/v/cell.svg)](https://crates.io/crates/cell)\n[![Docs](https://docs.rs/cell/badge.svg)](https://docs.rs/cell)\n[![rustc](https://img.shields.io/badge/rustc-1.35+-blue.svg)](https://blog.rust-lang.org/2019/05/23/Rust-1.35.0.html)\n\ncell\n====\n\n- [Documentation][docs-rs]\n- [Changelog](CHANGELOG.md)\n\n**cell** is a crate providing a revised `RefCell` implementation with\nadditional mapping capabilities. It can be used as a drop-in replacement\nfor `std::cell::RefCell` where this additional functionality is required.\n\n### *Warning:*\n----------------------------------------------------------------------\n\u003e **cell** was found to contain [a subtle unsafety][cell-issue-5], a\n\u003e work around for which is not known with current versions of Rust.\n\u003e Usage of the crate is therefore discouraged.\n----------------------------------------------------------------------\n\n\nThe Problem\n-----------\n\nA borrowed [`RefCell`][rust-ref-cell] is represented as a\n[`Ref`][rust-ref]. Such a `Ref` contains a reference to the data\ncontained in the `RefCell`. To extend the borrow to a different member\nin the original data, the [`map`][rust-ref-map] method can be used.\nUsing this method a new `Ref` object can be created that contains a\n**reference** to a member in the borrowed data.\n\nWhile having a direct reference to such a data member is appropriate in\nmany cases, there are some where this is insufficient, and an actual\nobject that contains such a reference is required.\n\n#### Example\n\nThe most prominent example is an iterator. While an iterator internally\nkeeps a reference to the object being iterated over, it is more than\njust a reference to it: it contains state about the progress of the\niteration.\n\nIf such an iterator is to be exposed for an object contained in a\n`RefCell` that is currently borrowed, the `Ref::map` function is\ninsufficient:\n\n```rust\nstruct RefStrings(RefCell\u003cVec\u003cString\u003e\u003e);\n\nimpl RefStrings {\n    fn iter(\u0026self) -\u003e Ref\u003cIter\u003cString\u003e\u003e {\n        Ref::map(self.0.borrow(), |x| x.iter())\n    }\n}\n```\n\n```\nerror[E0308]: mismatched types\n |  Ref::map(self.0.borrow(), |x| x.iter())\n |                                ^^^^^^^^ expected reference, found struct `std::slice::Iter`\n |\n = note: expected type `\u0026_`\n            found type `std::slice::Iter\u003c'_, std::string::String\u003e`\n```\n(Note that required lifetimes have been elided in the example for brevity)\n\n\nA Solution\n----------\n\nThis crate provides alternative `RefCell` and `Ref` implementations that\nsolve this problem by introduction of another mapping method: `map_val`.\nThis method returns a `RefVal` object. `RefVal` is a new type that is\nsimilar to `Ref` but, instead of embedding a reference to its `T` (a\ntype parameter), it embeds a value of it. `T` in turn would contain the\nactual reference to the borrowed object.\n\nIn the above example the only changes that need to happen are the\nreplacement of `std::cell::RefCell` with `cell::RefCell`, that of\n`std::cell::Ref` with `cell::Ref`, and the usage of `Ref::map` instead\nof `Ref::map_val`.\n\n```patch\n--- test.rs\n+++ test.rs\n@@ -1,13 +1,14 @@\n-use std::cell::Ref;\n-use std::cell::RefCell;\n+use cell::Ref;\n+use cell::RefCell;\n+use cell::RefVal;\n use std::slice::Iter;\n\n\n struct RefStrings(RefCell\u003cVec\u003cString\u003e\u003e);\n\n impl RefStrings {\n-    fn iter\u003c't, 's: 't\u003e(\u0026's self) -\u003e Ref\u003c't, Iter\u003cString\u003e\u003e {\n-        Ref::map(self.0.borrow(), |x| x.iter())\n+    fn iter\u003c't, 's: 't\u003e(\u0026's self) -\u003e RefVal\u003c't, Iter\u003cString\u003e\u003e {\n+        Ref::map_val(self.0.borrow(), |x| x.iter())\n     }\n }\n\n```\n\nSimilar functionality exists for mutable borrow with `RefValMut`.\n\n\n#### Alternative Implementations\n\nThe possibility of providing this functionality by means of a trait has\nbeen investigated but no viable solution has been identified. The main\nproblem stems from the fact that we require access to `Ref` internals in\norder to provide this functionality. Such a trait would alleviate the\nneed for providing alternative `RefCell` and `Ref` implementations.\n\nNo other solutions for this problem have been found, but the discussion\naround possible alternatives is still open as part of Rust [issue\n#54776][rust-issue-54776].\n\n\n[cell-issue-5]: https://github.com/d-e-s-o/cell/issues/5\n[docs-rs]: https://docs.rs/crate/cell\n[rust-ref-cell]: https://doc.rust-lang.org/std/cell/struct.RefCell.html\n[rust-ref]: https://doc.rust-lang.org/std/cell/struct.Ref.html\n[rust-ref-map]: https://doc.rust-lang.org/std/cell/struct.Ref.html#method.map\n[rust-issue-54776]: https://github.com/rust-lang/rust/issues/54776\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fd-e-s-o%2Fcell","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fd-e-s-o%2Fcell","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fd-e-s-o%2Fcell/lists"}