Selfie

Cargo Documentation

A lightweight self-referential struct library. Macro-free, allocation-free, and #![no_std].

This crate is experimental and not yet ready for production use!

This crate is an experiment to create simple and allocation-free self-referential structs, which I need in realtime audio contexts.

While this library is small and extensively tested under MIRI, and I believe it to be safe, it has not yet been peer-reviewed or seen decent real-world usage.

If you are willing to experiment with it, please do! Soundness and usability reviews and PRs are also more than welcome: self-referential structs are a complex problem, and the only part I feel confidently smart about is the library's name.

Advantages

There are other self-referential struct libraries out there, but these didn't quite fit my needs:

Disadvantages

Examples

Caching String subslices

```rust use core::pin::Pin; use selfie::{refs::Ref, Selfie};

let data: Pin = Pin::new("Hello, world!".to_owned()); let selfie: Selfie> = Selfie::new(data, |s| &s[0..5]);

asserteq!("Hello", selfie.referential()); asserteq!("Hello, world!", selfie.owned()); ```

Using custom referential types

```rust use std::pin::Pin; use selfie::{refs::RefType, Selfie};

[derive(Copy, Clone)]

struct MyReferentialType<'a>(&'a str);

struct MyReferentialTypeStandIn;

impl<'a> RefType<'a> for MyReferentialTypeStandIn { type Ref = MyReferentialType<'a>; }

// MyReferentialType can now be used in Selfies! let data = Pin::new("Hello, world!".to_owned()); let selfie: Selfie = Selfie::new(data, |str| MyReferentialType(&str[0..5]));

assert_eq!("Hello", selfie.referential().0); ```

Mutable self-referential

```rust use core::pin::Pin; use selfie::{refs::Mut, SelfieMut};

let data: Pin = Pin::new("Hello, world!".toowned()); let mut selfie: SelfieMut> = SelfieMut::new(data, |s| &mut Pin::intoinner(s)[0..5]);

selfie.withreferentialmut(|s| s.makeasciiuppercase()); selfie.withreferential(|s| asserteq!("HELLO", *s));

// By dropping the referential part, we get back the access to the owned data let data: String = Pin::intoinner(selfie.intoowned()); assert_eq!("HELLO, world!", &data); ```

Cascading Selfies

```rust use std::pin::Pin; use selfie::refs::{Ref, SelfieRef}; use selfie::Selfie;

let data = Pin::new("Hello, world!".to_owned()); let selfie: Selfie, Ref>> = Selfie::new(data, |str| { let substr = Pin::new(&str[0..5]); Selfie::new(substr, |str| &str[3..]) });

asserteq!("Hello, world!", selfie.owned()); selfie.withreferential(|r| { asserteq!("Hello", r.owned()); asserteq!("lo", r.referential()); }); ```