nsi 0.9.0

Nodal Scene Interface for (offline) 3D renderers – ɴsɪ.
Documentation
# Pin Enforcement Fix for NSI Reference Type

## Problem Summary

The `Reference` type claimed to require pinning but didn't actually enforce it. Users could pass `Pin::new(&data)` which doesn't guarantee the data won't move.

## Solution Implemented

### 1. Trait-Based Type Safety

Created a `StableDeref` trait that is only implemented for types that guarantee stable addresses:

```rust
pub trait StableDeref<'a> {
    fn stable_deref(&self) -> *const c_void;
}

// Only implemented for:
impl<'a, T: ?Sized> StableDeref<'a> for &'a Box<T> { ... }
impl<'a, T: ?Sized> StableDeref<'a> for &'a Arc<T> { ... }
impl<'a, T: ?Sized> StableDeref<'a> for &'a Pin<Box<T>> { ... }
```

### 2. Updated Reference API

The `Reference::new()` method now only accepts types that implement `StableDeref`:

```rust
impl<'a> Reference<'a> {
    pub fn new<S: StableDeref<'a>>(data: S) -> Self {
        let ptr = data.stable_deref();
        Self { data: ptr, _marker: PhantomData }
    }
}
```

### 3. Safe Macro Usage

The `reference!` macro now requires heap-allocated data:

```rust
// Before (unsafe - data could move):
let data = vec![1, 2, 3];
let reference = nsi::reference!("data", Pin::new(&data));

// After (safe - Box ensures stable address):
let data = Box::new(vec![1, 2, 3]);
let reference = nsi::reference!("data", &data);
```

### 4. Escape Hatch for Advanced Users

Added `reference_stable!` macro for users who need to reference other stable data:

```rust
// For static data or other guaranteed-stable addresses
static DATA: [u8; 3] = [1, 2, 3];
let reference = nsi::reference_stable!("data", &DATA);
```

## Benefits

1. **Compile-time safety**: Invalid references are now caught at compile time
2. **Clear API**: Users must explicitly choose heap allocation or use the unsafe variant
3. **No false guarantees**: The API now accurately reflects what it enforces
4. **Backwards compatible**: Existing code using Box/Arc continues to work

## Migration Guide

For existing code:

```rust
// Old (unsafe):
let data = MyStruct { ... };
nsi::reference!("data", Pin::new(&data))

// New (safe):
let data = Box::new(MyStruct { ... });
nsi::reference!("data", &data)

// Or use Arc for shared ownership:
let data = Arc::new(MyStruct { ... });
nsi::reference!("data", &data)

// Or explicitly use unsafe for stack data:
let data = MyStruct { ... };
nsi::reference_stable!("data", &data) // Must ensure data doesn't move!
```

## Conclusion

The Pin enforcement is now properly implemented through the type system. Users cannot accidentally create invalid references, and the API clearly communicates its requirements.