{"id":16376654,"url":"https://github.com/udoprog/nondestructive","last_synced_at":"2025-03-16T15:33:59.430Z","repository":{"id":143078880,"uuid":"614678544","full_name":"udoprog/nondestructive","owner":"udoprog","description":"Nondestructive editing of various formats","archived":false,"fork":false,"pushed_at":"2024-09-11T12:37:25.000Z","size":261,"stargazers_count":11,"open_issues_count":3,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-10-12T03:25:30.925Z","etag":null,"topics":["editing","parser","rust","yaml"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/udoprog.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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-03-16T04:48:58.000Z","updated_at":"2024-10-02T00:52:26.000Z","dependencies_parsed_at":"2023-12-16T15:46:29.548Z","dependency_job_id":"dc84e5ce-68ba-419c-8cd3-045eeac7c756","html_url":"https://github.com/udoprog/nondestructive","commit_stats":null,"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/udoprog%2Fnondestructive","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/udoprog%2Fnondestructive/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/udoprog%2Fnondestructive/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/udoprog%2Fnondestructive/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/udoprog","download_url":"https://codeload.github.com/udoprog/nondestructive/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221665670,"owners_count":16860295,"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":["editing","parser","rust","yaml"],"created_at":"2024-10-11T03:25:35.572Z","updated_at":"2024-10-27T10:52:51.864Z","avatar_url":"https://github.com/udoprog.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# nondestructive\n\n[\u003cimg alt=\"github\" src=\"https://img.shields.io/badge/github-udoprog/nondestructive-8da0cb?style=for-the-badge\u0026logo=github\" height=\"20\"\u003e](https://github.com/udoprog/nondestructive)\n[\u003cimg alt=\"crates.io\" src=\"https://img.shields.io/crates/v/nondestructive.svg?style=for-the-badge\u0026color=fc8d62\u0026logo=rust\" height=\"20\"\u003e](https://crates.io/crates/nondestructive)\n[\u003cimg alt=\"docs.rs\" src=\"https://img.shields.io/badge/docs.rs-nondestructive-66c2a5?style=for-the-badge\u0026logoColor=white\u0026logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K\" height=\"20\"\u003e](https://docs.rs/nondestructive)\n[\u003cimg alt=\"build status\" src=\"https://img.shields.io/github/actions/workflow/status/udoprog/nondestructive/ci.yml?branch=main\u0026style=for-the-badge\" height=\"20\"\u003e](https://github.com/udoprog/nondestructive/actions?query=branch%3Amain)\n\nNondestructive editing tries to preserve as much as possible of the existing\nstructure, while allowing the document to be modified in place.\n\n**This project is as of yet, incomplete!**\n\nSee the corresponding module for detailed documentation on how to use:\n\n* [YAML support][yaml].\n\n\u003cbr\u003e\n\n## Working with documents\n\nA document is deserialized into a large object from which all access and\nmutation must occur. This makes the API a bit harder to use than your\ntypical serialization library but is necessary to ensure that it has access\nto all the necessary data to perform nondestructive editing.\n\nOne particular complication is that each method which provides mutable\naccess to the document needs to have two variations: `as_\u003csomething\u003e_mut`\nand `into_\u003csomething\u003e_mut`. If we look at [`ValueMut::as_mapping_mut`] and\n[`ValueMut::into_mapping_mut`] the difference is that the latter consumes\n`self` and returns a [`ValueMut`] with its associated lifetime.\n\n\u003cbr\u003e\n\n```rust\nuse anyhow::Context;\nuse nondestructive::yaml;\n\nlet mut doc = yaml::from_slice(\n    r\"\n    greeting: Hello World!\n    \"\n)?;\n\n// Access through the document:\nassert_eq!(\n    doc.as_ref().as_mapping().and_then(|m| m.get(\"greeting\")?.as_str()),\n    Some(\"Hello World!\")\n);\n\n// Mutation through the document:\nlet mut mapping = doc.as_mut().into_mapping_mut().context(\"missing root mapping\")?;\nmapping.insert_str(\"greeting2\", \"Hello Rust!\");\n\nassert_eq!(\n    doc.to_string(),\n    r\"\n    greeting: Hello World!\n    greeting2: Hello Rust!\n    \"\n);\n```\n\n\u003cbr\u003e\n\nIf we were to change the line which uses `into_mapping_mut` we would get a\nlifetime error:\n\n\u003cbr\u003e\n\n```text\nerror[E0716]: temporary value dropped while borrowed\n  --\u003e src\\lib.rs:43:19\n   |\n20 | let mut mapping = doc.as_mut().as_mapping_mut().context(\"missing root mapping\")?;\n   |                   ^^^^^^^^^^^^                                                  - temporary value is freed at the end of this statement\n   |                   |\n   |                   creates a temporary value which is freed while still in use\n21 | mapping.insert_str(\"greeting2\", \"Hello Rust!\");\n   | ---------------------------------------------- borrow later used here\n   |\nhelp: consider using a `let` binding to create a longer lived value\n   |\n20 + let binding = doc.as_mut();\n21 ~ let mut mapping = binding.as_mapping_mut().context(\"missing root mapping\")?;\n   |\n```\n\nWe could follow the recommendation and assign it to a local variable,\nhowever that wouldn't be possible if we were using combinators such as\n[`Option::and_then`].\n\n\u003cbr\u003e\n\nAnother important aspect of working with documents is that we can address\nvalues *globally* through [identifiers][Id]. This makes it easier to store\ndesired modifications before applying them.\n\n```rust\nuse anyhow::Context;\nuse nondestructive::yaml;\n\nlet mut doc = yaml::from_slice(\n    r\"\n    - 10\n    - 24\n    - 30\n    \"\n)?;\n\nlet mut edits = Vec::new();\n\n// Build a collection of edits:\nfor value in doc.as_ref().as_sequence().context(\"missing sequence\")? {\n    let Some(n) = value.as_u32() else {\n        continue;\n    };\n\n    if n % 10 == 0 {\n        edits.push((value.id(), n / 10));\n    }\n}\n\n// Apply stored edits:\nfor (id, new_number) in edits {\n    doc.value_mut(id).set_u32(new_number);\n}\n\nassert_eq!(\n    doc.to_string(),\n    r\"\n    - 1\n    - 24\n    - 3\n    \"\n);\n```\n\n\u003cbr\u003e\n\n## Examples\n\nThis provides a broader view of the available API, and the difference\nbetween accessors and mutators.\n\n\u003cbr\u003e\n\n```rust\nuse anyhow::Context;\nuse nondestructive::yaml;\n\nlet mut doc = yaml::from_slice(\n    r\"\n    name: Descartes\n    country: Grece\n    \"\n)?;\n\nlet mapping = doc.as_ref().as_mapping().context(\"missing mapping\")?;\nlet name = mapping.get(\"name\").context(\"missing name\")?;\nassert_eq!(name.as_str(), Some(\"Descartes\"));\n\nlet mut mapping = doc.as_mut().into_mapping_mut().context(\"missing mapping\")?;\nlet mut name = mapping.get_mut(\"name\").context(\"missing name\")?;\nname.set_string(\"Plato\");\n\nlet mut country = mapping.get_mut(\"country\").context(\"missing country\")?;\ncountry.set_string(\"Greece\");\n\nassert_eq!(\n    doc.to_string(),\n    r\"\n    name: Plato\n    country: Greece\n    \"\n);\n```\n\n[`Option::and_then`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.and_then\n[`ValueMut::as_mapping_mut`]: https://docs.rs/nondestructive/latest/nondestructive/yaml/struct.ValueMut.html#method.as_mapping_mut\n[`ValueMut::into_mapping_mut`]: https://docs.rs/nondestructive/latest/nondestructive/yaml/struct.ValueMut.html#method.into_mapping_mut\n[`ValueMut`]: https://docs.rs/nondestructive/latest/nondestructive/yaml/struct.ValueMut.html\n[Id]: https://docs.rs/nondestructive/latest/nondestructive/yaml/struct.Id.html\n[yaml]: https://docs.rs/nondestructive/latest/nondestructive/yaml/index.html\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fudoprog%2Fnondestructive","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fudoprog%2Fnondestructive","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fudoprog%2Fnondestructive/lists"}