MCPcopy Index your code
hub / github.com/dureuill/nolife

github.com/dureuill/nolife @v0.4.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.4.0 ↗ · + Follow
43 symbols 85 edges 6 files 17 documented · 40%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Open a scope and then freeze it in time for future access.

License Crates.io Docs dependency status Build

This crate allows constructing structs that contain references and keeping them alive alongside the data they reference, without a lifetime.

This is especially useful for zero-copy parsers that construct elaborate (and possibly costly) representations that borrow the source data.

This crate achieves that by leveraging async functions. At their core, async functions are self-referential structs. this crate simply provides a way to ex-filtrate references outside of the async function, in a controlled manner.

Using this crate

After you identified the data and its borrowed representation that you'd like to access without a lifetime, using this crate will typically encompass a few steps:

// Given the following types:
struct MyData(Vec<u8>);
struct MyParsedData<'a>(&'a mut MyData, /* ... */);

// 1. Define a helper type that will express where the lifetimes of the borrowed representation live.
struct MyParsedDataFamily; // empty type, no lifetime.
impl<'a> nolife::Family<'a> for MyParsedDataFamily {
    type Family = MyParsedData<'a>; // Indicates how the type is tied to the trait's lifetime.
    // you generally want to replace all lifetimes in the struct with the one of the trait.
}

// 2. Define a function that setups the data and its borrowed representation:
fn my_scope(
    data_source: Vec<u8>, // 👈 all parameters that allow to build a `MyData`
) -> impl nolife::TopScope<Family = MyParsedDataFamily> // 👈 use the helper type we declared
{
    nolife::scope!({
        let mut data = MyData(data_source);
        let mut parsed_data = MyParsedData(&mut data); // imagine that this step is costly...
        freeze_forever!(&mut parsed_data) // gives access to the parsed data to the outside.
                       /* 👆 reference to the borrowed data */
    })
}

// 3. Open a `BoxScope` using the previously written async function:
let mut scope = nolife::BoxScope::<MyParsedDataFamily>::new_dyn(my_scope(vec![0, 1, 2]));

// 4. Store the `BoxScope` anywhere you want
struct ContainsScope {
    scope: nolife::BoxScope<MyParsedDataFamily>,
    /* other data */
}

// 5. Lastly, enter the scope to retrieve access to the referenced value.
scope.enter(|parsed_data| { /* do what you need with the parsed data */ });

Kinds of scopes

This crate only provide a single kind of scope at the moment

Scope Allocations Moveable after opening Thread-safe
[BoxScope] 1 (size of the contained Future + 1 pointer to the reference type) Yes No

An RcScope or MutexScope could be future extensions

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Alternative

[yoke] serves a similar use case as this crate, albeit it is expressed in terms of a self-referential struct rather than as an async scope, which is less natural if the intent is to borrow some data.

Extension points exported contracts — how you extend this code

Family (Interface)
Describes a family of types containing a lifetime. This type is typically implemented on a helper type to describe the [1 …
src/lib.rs
Sealed (Interface)
Trait sealed for safety. The trait is only implemented on [`crate::scope::Wrapper`] [1 implementers]
src/scope.rs
TopScope (Interface)
A top-level [`Scope`], always returning [`crate::Never`]. Create one using the [`crate::scope!`] macro. [1 implementers]
src/scope.rs
Scope (Interface)
(no doc) [1 implementers]
src/scope.rs

Core symbols most depended-on inside this repo

enter
called by 15
src/raw_scope.rs
must_panic
called by 7
src/lib.rs
drop
called by 2
src/waker.rs
scope_with_ref
called by 1
src/lib.rs
freeze
called by 1
src/raw_scope.rs
poll
called by 1
src/raw_scope.rs
run
called by 1
src/scope.rs
new_scope
called by 1
src/scope.rs

Shape

Function 17
Method 13
Class 8
Interface 4
Enum 1

Languages

Rust100%

Modules by API surface

src/lib.rs14 symbols
src/raw_scope.rs12 symbols
src/scope.rs6 symbols
src/box_scope.rs6 symbols
src/waker.rs5 symbols

For agents

$ claude mcp add nolife \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page