{"id":33938701,"url":"https://github.com/danieldulaney/appendlist","last_synced_at":"2026-04-07T04:31:39.772Z","repository":{"id":57491355,"uuid":"193388283","full_name":"danieldulaney/appendlist","owner":"danieldulaney","description":"An append-only list data structure","archived":false,"fork":false,"pushed_at":"2023-07-02T19:15:51.000Z","size":33,"stargazers_count":6,"open_issues_count":2,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-01-02T08:14:29.234Z","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":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/danieldulaney.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":"2019-06-23T19:38:06.000Z","updated_at":"2025-10-12T00:27:41.000Z","dependencies_parsed_at":"2022-08-30T04:00:23.327Z","dependency_job_id":null,"html_url":"https://github.com/danieldulaney/appendlist","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/danieldulaney/appendlist","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danieldulaney%2Fappendlist","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danieldulaney%2Fappendlist/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danieldulaney%2Fappendlist/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danieldulaney%2Fappendlist/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/danieldulaney","download_url":"https://codeload.github.com/danieldulaney/appendlist/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danieldulaney%2Fappendlist/sbom","scorecard":{"id":319542,"data":{"date":"2025-08-11","repo":{"name":"github.com/danieldulaney/appendlist","commit":"92ae07a454fe1e907f5eebf359636a9ef2ba10d4"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"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":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"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":"Code-Review","score":0,"reason":"Found 0/18 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":"Dangerous-Workflow","score":-1,"reason":"no workflows found","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":"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":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"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":"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":"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":"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":"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":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: 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 'master'"],"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 17 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-18T01:02:51.843Z","repository_id":57491355,"created_at":"2025-08-18T01:02:51.843Z","updated_at":"2025-08-18T01:02:51.843Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31500397,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-07T03:10:19.677Z","status":"ssl_error","status_checked_at":"2026-04-07T03:10:13.982Z","response_time":105,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5: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":[],"created_at":"2025-12-12T15:03:31.173Z","updated_at":"2026-04-07T04:31:39.761Z","avatar_url":"https://github.com/danieldulaney.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# AppendList: An append-only list that preserves references to its elements\n\n[![Build Status](https://travis-ci.com/danieldulaney/appendlist.svg?branch=master)](https://travis-ci.com/danieldulaney/appendlist)\n\nThis list lets you add new things to the end, even if you're holding a reference\nto something already inside it. It also avoids reallocations.\n\nWhen should you use it?\n\n- You need to insert into a list while its other elements are borrowed\n- You have so much data that `Vec` reallocations are significant\n\nWhen shouldn't you use it?\n\n- You are storing indices into a list, rather than actual references (just use\n  `Vec\u003cT\u003e`)\n- `Vec` reallocations don't matter very much (normally the case!)\n\nWhat are some features?\n\n- A `push(\u0026self, item: T)` method (you'd expect `push(\u0026mut self, item: T)`)\n- Non-amortized constant-time insertions and indexes (normally insertions are\n  *amortized* constant-time, like `Vec`, or indexing is linear-time, like `LinkedList`)\n- You can hold onto references in the list\n- Only 2 lines of unsafe code\n\n## What does this let me do?\n\nThis example fails to compile because `second_element` has a reference into\n`list` when `list.push()` is called.\n\n```rust compile_fail\nlet list: Vec\u003cu32\u003e = (1..=10).collect();\n\nlet second_element = \u0026list[1];\n\nlist.push(11); // Push needs \u0026mut self, but list is already borrowed\n\nassert_eq!(*second_element, 2); // Fails to compile\n```\n\nBut if you just swap in `AppendList` for `Vec`, everything works!\n\n```rust\nuse appendlist::AppendList;\n\nlet list: AppendList\u003cu32\u003e = (1..=10).collect();\n\nlet second_element = \u0026list[1];\n\nlist.push(11); // Push only needs \u0026self, so this works fine\n\nassert_eq!(*second_element, 2); // All OK!\n```\n\n## What's all this about reallocations?\n\nIn general, `Vec`s are pretty cool, and you should use them by default. But they\nhave a weakness: when you create\none, it gets created with a finite amount of space. When it runs out of space,\nit needs to reallocate: grab a new hunk of memory (usually twice as big as\nthe current one) and copy everything over, then release the old memory.\n\nReallocations take O(n) time to do: you need to copy all n elements in the list.\nBut you don't have to do them very often: only O(log n) reallocations are needed\nto do n insertions (for the current `Vec` implementation). In fact, the\nreallocations are rare enough that if you spread\nthem out across all the insertions, they just add a constant extra time.\nThis is why the Rust docs say that `Vec` has \"O(1) *amortized*\npush\" -- it generally takes constant time to push and it occasionally takes linear\ntime, but if you spread out those expensive pushes over all the cheap pushes,\nit's still constant.\n\nReallocations have another issue: any reference to an element inside the `Vec`\nis invalidated. If you have a reference to one of the elements when it gets\ncopied over, your reference has no way of knowing its new location and will\nstill point to the old location, which is now invalid memory. Using that reference\nwould be a use-after-free bug, so Rust forces you to have no references into a\n`Vec` before you push another element on, just in case that push would reallocate.\n\nThe `AppendList` solves both issues by keeping a `Vec` of chunks of data. When\nyou push a new element on, it goes to the end of the current chunk. If the chunk\nis full, rather than reallocate it, `AppendList` creates a whole new chunk that\nstarts off empty. Each\nchunk is double the size of the last chunk, so only O(log n) allocations are\nneeded, and each one takes constant time (for most allocators) rather than linear\ntime. By eliminating reallocations, an `AppendList` gives you a couple of benefits\ncompared to `Vec`:\n\n- You can keep your references while pushing\n- You don't have to pay the occasional linear reallocate-and-copy cost\n\nHowever, it also comes with some drawbacks:\n\n- Indexing takes longer (you have to index into a chunk, then into your item)\n- CPU cache behavior might be somewhat worse near a chunk boundary (because the\n  next chunk isn't generally contiguous)\n\n## So should I use this crate?\n\nProbably not.\n\nIn general, you should just use a `Vec` and keep track of indices rather than\nreferences. But if keeping references is very important, then this is your solution.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanieldulaney%2Fappendlist","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdanieldulaney%2Fappendlist","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanieldulaney%2Fappendlist/lists"}