[-] suffering with closures, references, and async

so I have a personal problem. a problem that can only be solved by passing functions into functions.
here I am going to document the iterations through which this code (d)evolved as code requirements elsewhere changed.
So the original problem is thus: I had some code that needed to coordinate two clients interacting with eachother. the primary structure was a HashMap.
the way in which I wanted to interact with this was that I would give it the `ClientId` of one client and it would then fetch for me the coresponding `other_client` and give me mutable references to both. and given the aforementioned personal problem, I figured I would solve this through passing a function to this structure:
use std::collections::HashMap;

#[derive(Copy, Clone, Hash, Eq, PartialEq)]
struct ClientId(u32);

struct ClientState {
    other_client: ClientId,
    some_data: u32,
}

#[derive(Debug)]
enum StateError {
    Blah,
}

#[derive(Default)]
struct State {
    state: HashMap<ClientId, ClientState>,
}

impl State {
    pub fn new_client(&mut self, client1: ClientId, client2: ClientId) {
        self.state.insert(client1, ClientState {
            other_client: client2,
            some_data: 0,
        });
        self.state.insert(client2, ClientState {
            other_client: client1,
            some_data: 0,
        });
    }

    pub fn with<T, F>(&mut self, client: ClientId, func: F) -> Result<T, StateError>
    where
        F: Fn(&mut ClientState, &mut ClientState) -> T
    {
        let c1 = self.state.get_mut(&client).ok_or(StateError::Blah)?;
        let c2 = self.state.get_mut(&c1.other_client).ok_or(StateError::Blah)?;

        Ok(func(c1, c2))
    }
}

fn main() {
    let mut state = State::default();
    state.new_client(ClientId(1), ClientId(2));

    state.with(ClientId(1), |this, other| {
        this.some_data = 23;
        other.some_data = 5;
    }).unwrap();

    println!("c1 {}", state.state.get(&ClientId(1)).unwrap().borrow().some_data);
    println!("c2 {}", state.state.get(&ClientId(2)).unwrap().borrow().some_data);
}
cool great got the basic idea going lets see how it works
error[E0499]: cannot borrow `self.state` as mutable more than once at a time
  --> src/main.rs:37:18
   |
36 |         let c1 = self.state.get_mut(&client).ok_or(StateError::Blah)?;
   |                  --------------------------- first mutable borrow occurs here
37 |         let c2 = self.state.get_mut(&c1.other_client).ok_or(StateError::Blah)?;
   |                  ^^^^^^^^^^^^^^^^^^^----------------^
   |                  |                  |
   |                  |                  first borrow later used here
   |                  second mutable borrow occurs here
jokes on me of course it doesn't work those there consecutive `get_mut`s are just not gonna work luckily we have this rad `RefCell` thing to put in there to make this work:
use std::collections::HashMap;
use std::cell::RefCell;

#[derive(Copy, Clone, Hash, Eq, PartialEq)]
struct ClientId(u32);

struct ClientState {
    other_client: ClientId,
    some_data: u32,
}

#[derive(Debug)]
enum StateError {
    Blah,
}

#[derive(Default)]
struct State {
    state: HashMap<ClientId, RefCell<ClientState>>,
}

impl State {
    pub fn new_client(&mut self, client1: ClientId, client2: ClientId) {
        self.state.insert(client1, RefCell::new(ClientState {
            other_client: client2,
            some_data: 0,
        }));
        self.state.insert(client2, RefCell::new(ClientState {
            other_client: client1,
            some_data: 0,
        }));
    }

    pub fn with<T, F>(&mut self, client: ClientId, func: F) -> Result<T, StateError>
    where
        F: Fn(&mut ClientState, &mut ClientState) -> T
    {
        let mut c1 = self.state.get(&client).ok_or(StateError::Blah)?.borrow_mut();
        let mut c2 = self.state.get(&c1.other_client).ok_or(StateError::Blah)?.borrow_mut();

        Ok(func(&mut *c1, &mut *c2))
    }
}

fn main() {
    let mut state = State::default();
    state.new_client(ClientId(1), ClientId(2));

    state.with(ClientId(1), |this, other| {
        this.some_data = 23;
        other.some_data = 5;
    }).unwrap();

    println!("c1 {}", state.state.get(&ClientId(1)).unwrap().borrow().some_data);
    println!("c2 {}", state.state.get(&ClientId(2)).unwrap().borrow().some_data);
}
$ cargo run
   Compiling sufferingwithwith v0.1.0 (/home/jake/projects/sharnoth.com/0005)
    Finished dev [unoptimized + debuginfo] target(s) in 0.19s
     Running `target/debug/sufferingwithwith`
c1 23
c2 5
look at it go.


and this was great, perfect, ideal. until suddenly `F` needed to be async.
use std::collections::HashMap;
use std::cell::RefCell;

#[derive(Copy, Clone, Hash, Eq, PartialEq)]
struct ClientId(u32);

struct ClientState {
    other_client: ClientId,
    some_data: u32,
}

#[derive(Debug)]
enum StateError {
    Blah,
}

#[derive(Default)]
struct State {
    state: HashMap<ClientId, RefCell<ClientState>>,
}

impl State {
    pub fn new_client(&mut self, client1: ClientId, client2: ClientId) {
        self.state.insert(client1, RefCell::new(ClientState {
            other_client: client2,
            some_data: 0,
        }));
        self.state.insert(client2, RefCell::new(ClientState {
            other_client: client1,
            some_data: 0,
        }));
    }

    pub fn with<T, F>(&mut self, client: ClientId, func: F) -> Result<T, StateError>
    where
        F: Fn(&mut ClientState, &mut ClientState) -> T
    {
        let mut c1 = self.state.get(&client).ok_or(StateError::Blah)?.borrow_mut();
        let mut c2 = self.state.get(&c1.other_client).ok_or(StateError::Blah)?.borrow_mut();

        Ok(func(&mut *c1, &mut *c2))
    }
}

#[async_std::main]
async fn main() {
    let mut state = State::default();
    state.new_client(ClientId(1), ClientId(2));

    state.with(ClientId(1), |this, other| async {
        this.some_data = 23;
        other.some_data = 5;
    }).unwrap().await;

    println!("c1 {}", state.state.get(&ClientId(1)).unwrap().borrow().some_data);
    println!("c2 {}", state.state.get(&ClientId(2)).unwrap().borrow().some_data);
}
error: lifetime may not live long enough
  --> src/main.rs:50:43
   |
50 |       state.with(ClientId(1), |this, other| async {
   |  ______________________________----_______-_^
   | |                              |          |
   | |                              |          return type of closure `impl Future` contains a lifetime `'2`
   | |                              has type `&'1 mut ClientState`
51 | |         this.some_data = 23;
52 | |         other.some_data = 5;
53 | |     }).unwrap().await;
   | |_____^ returning this value requires that `'1` must outlive `'2`

error: lifetime may not live long enough
  --> src/main.rs:50:43
   |
50 |       state.with(ClientId(1), |this, other| async {
   |  ____________________________________------_^
   | |                                    |    |
   | |                                    |    return type of closure `impl Future` contains a lifetime `'4`
   | |                                    has type `&'3 mut ClientState`
51 | |         this.some_data = 23;
52 | |         other.some_data = 5;
53 | |     }).unwrap().await;
   | |_____^ returning this value requires that `'3` must outlive `'4`
   |
   = note: requirement occurs because of a mutable reference to `u32`
   = note: mutable references are invariant over their type parameter
   = help: see  for more information about variance

error: could not compile `sufferingwithwith` due to 2 previous errors
and now the suffering begins

now this error totally makes sense. `state` is lending out `this` and `other` which get captured by this async block which may not be `.await`ed until after `state` stops existing.
lets throw some lifetimes in here and see if it helps:
use std::collections::HashMap;
use std::cell::RefCell;

#[derive(Copy, Clone, Hash, Eq, PartialEq)]
struct ClientId(u32);

struct ClientState {
    other_client: ClientId,
    some_data: u32,
}

#[derive(Debug)]
enum StateError {
    Blah,
}

#[derive(Default)]
struct State {
    state: HashMap<ClientId, RefCell<ClientState>>,
}

impl State {
    pub fn new_client(&mut self, client1: ClientId, client2: ClientId) {
        self.state.insert(client1, RefCell::new(ClientState {
            other_client: client2,
            some_data: 0,
        }));
        self.state.insert(client2, RefCell::new(ClientState {
            other_client: client1,
            some_data: 0,
        }));
    }

    pub fn with<'a, T, F>(&'a mut self, client: ClientId, func: F) -> Result<T, StateError>
    where
        F: Fn(&'a mut ClientState, &'a mut ClientState) -> T
    {
        let mut c1 = self.state.get(&client).ok_or(StateError::Blah)?.borrow_mut();
        let mut c2 = self.state.get(&c1.other_client).ok_or(StateError::Blah)?.borrow_mut();

        Ok(func(&mut *c1, &mut *c2))
    }
}

#[async_std::main]
async fn main() {
    let mut state = State::default();
    state.new_client(ClientId(1), ClientId(2));

    state.with(ClientId(1), |this, other| async {
        this.some_data = 23;
        other.some_data = 5;
    }).unwrap().await;

    println!("c1 {}", state.state.get(&ClientId(1)).unwrap().borrow().some_data);
    println!("c2 {}", state.state.get(&ClientId(2)).unwrap().borrow().some_data);
}
error[E0597]: `c1` does not live long enough
  --> src/main.rs:41:23
   |
34 |     pub fn with<'a, T, F>(&'a mut self, client: ClientId, func: F) -> Result
   |                 -- lifetime `'a` defined here
...
41 |         Ok(func(&mut *c1, &mut *c2))
   |            -----------^^-----------
   |            |          |
   |            |          borrowed value does not live long enough
   |            argument requires that `c1` is borrowed for `'a`
42 |     }
   |     - `c1` dropped here while still borrowed

error[E0597]: `c2` does not live long enough
  --> src/main.rs:41:33
   |
34 |     pub fn with<'a, T, F>(&'a mut self, client: ClientId, func: F) -> Result
   |                 -- lifetime `'a` defined here
...
41 |         Ok(func(&mut *c1, &mut *c2))
   |            ---------------------^^-
   |            |                    |
   |            |                    borrowed value does not live long enough
   |            argument requires that `c2` is borrowed for `'a`
42 |     }
   |     - `c2` dropped here while still borrowed
literally useless

throwing shit at the wall, maybe a second lifetime 'b that is less than 'a:
use std::collections::HashMap;
use std::cell::RefCell;

#[derive(Copy, Clone, Hash, Eq, PartialEq)]
struct ClientId(u32);

struct ClientState {
    other_client: ClientId,
    some_data: u32,
}

#[derive(Debug)]
enum StateError {
    Blah,
}

#[derive(Default)]
struct State {
    state: HashMap<ClientId, RefCell<ClientState>>,
}

impl State {
    pub fn new_client(&mut self, client1: ClientId, client2: ClientId) {
        self.state.insert(client1, RefCell::new(ClientState {
            other_client: client2,
            some_data: 0,
        }));
        self.state.insert(client2, RefCell::new(ClientState {
            other_client: client1,
            some_data: 0,
        }));
    }

    pub fn with<'a, 'b, T, F>(&'a mut self, client: ClientId, func: F) -> Result<T, StateError>
    where
        'a: 'b,
        F: Fn(&'b mut ClientState, &'b mut ClientState) -> T
    {
        let mut c1 = self.state.get(&client).ok_or(StateError::Blah)?.borrow_mut();
        let mut c2 = self.state.get(&c1.other_client).ok_or(StateError::Blah)?.borrow_mut();

        Ok(func(&mut *c1, &mut *c2))
    }
}

#[async_std::main]
async fn main() {
    let mut state = State::default();
    state.new_client(ClientId(1), ClientId(2));

    state.with(ClientId(1), |this, other| async {
        this.some_data = 23;
        other.some_data = 5;
    }).unwrap().await;

    println!("c1 {}", state.state.get(&ClientId(1)).unwrap().borrow().some_data);
    println!("c2 {}", state.state.get(&ClientId(2)).unwrap().borrow().some_data);
}
error[E0597]: `c1` does not live long enough
  --> src/main.rs:42:23
   |
34 |     pub fn with<'a, 'b, T, F>(&'a mut self, client: ClientId, func: F) -> Result
   |                     -- lifetime `'b` defined here
...
42 |         Ok(func(&mut *c1, &mut *c2))
   |            -----------^^-----------
   |            |          |
   |            |          borrowed value does not live long enough
   |            argument requires that `c1` is borrowed for `'b`
43 |     }
   |     - `c1` dropped here while still borrowed

error[E0597]: `c2` does not live long enough
  --> src/main.rs:42:33
   |
34 |     pub fn with<'a, 'b, T, F>(&'a mut self, client: ClientId, func: F) -> Result
   |                     -- lifetime `'b` defined here
...
42 |         Ok(func(&mut *c1, &mut *c2))
   |            ---------------------^^-
   |            |                    |
   |            |                    borrowed value does not live long enough
   |            argument requires that `c2` is borrowed for `'b`
43 |     }
   |     - `c2` dropped here while still borrowed

why did I think that would do anything.

its at this point that I notice all except one of my actual-code-that-caused-me-to-write-this `with` calls were using an async block internally. maybe I can just make `with` async and move on with my life
use std::collections::HashMap;
use std::cell::RefCell;
use std::future::Future;

#[derive(Copy, Clone, Hash, Eq, PartialEq)]
struct ClientId(u32);

struct ClientState {
    other_client: ClientId,
    some_data: u32,
}

#[derive(Debug)]
enum StateError {
    Blah,
}

#[derive(Default)]
struct State {
    state: HashMap<ClientId, RefCell<ClientState>>,
}

impl State {
    pub fn new_client(&mut self, client1: ClientId, client2: ClientId) {
        self.state.insert(client1, RefCell::new(ClientState {
            other_client: client2,
            some_data: 0,
        }));
        self.state.insert(client2, RefCell::new(ClientState {
            other_client: client1,
            some_data: 0,
        }));
    }

    pub async fn with<'a, T, F, Fut>(&'a mut self, client: ClientId, func: F) -> Result<T, StateError>
    where
        F: Fn(&'a mut ClientState, &'a mut ClientState) -> Fut,
        Fut: Future<Output=T>,
    {
        let mut c1 = self.state.get(&client).ok_or(StateError::Blah)?.borrow_mut();
        let mut c2 = self.state.get(&c1.other_client).ok_or(StateError::Blah)?.borrow_mut();

        Ok(func(&mut *c1, &mut *c2).await)
    }
}

#[async_std::main]
async fn main() {
    let mut state = State::default();
    state.new_client(ClientId(1), ClientId(2));

    state.with(ClientId(1), |this, other| async {
        this.some_data = 23;
        other.some_data = 5;
    }).await.unwrap();

    println!("c1 {}", state.state.get(&ClientId(1)).unwrap().borrow().some_data);
    println!("c2 {}", state.state.get(&ClientId(2)).unwrap().borrow().some_data);
}
error[E0597]: `c1` does not live long enough
  --> src/main.rs:43:23
   |
35 |     pub async fn with<'a, T, F, Fut>(&'a mut self, client: ClientId, func: F) -> Result
   |                       -- lifetime `'a` defined here
...
43 |         Ok(func(&mut *c1, &mut *c2).await)
   |            -----------^^-----------
   |            |          |
   |            |          borrowed value does not live long enough
   |            argument requires that `c1` is borrowed for `'a`
44 |     }
   |     - `c1` dropped here while still borrowed

error[E0597]: `c2` does not live long enough
  --> src/main.rs:43:33
   |
35 |     pub async fn with<'a, T, F, Fut>(&'a mut self, client: ClientId, func: F) -> Result
   |                       -- lifetime `'a` defined here
...
43 |         Ok(func(&mut *c1, &mut *c2).await)
   |            ---------------------^^-
   |            |                    |
   |            |                    borrowed value does not live long enough
   |            argument requires that `c2` is borrowed for `'a`
44 |     }
   |     - `c2` dropped here while still borrowed
I suppose if I actually sat to think about this before just throwing code at my computer I would have realized this would never have solved anything. the result is still a future that needs to be `.await`ed outside of this function scope.

so how do I make my resulting borrowed clients live longer than this function? idk lets try Arc I'm getting desperate
use std::collections::HashMap;
use std::cell::RefCell;
use std::future::Future;

use async_std::sync::Arc;

#[derive(Copy, Clone, Hash, Eq, PartialEq)]
struct ClientId(u32);

struct ClientState {
    other_client: ClientId,
    some_data: u32,
}

#[derive(Debug)]
enum StateError {
    Blah,
}

#[derive(Default)]
struct State {
    state: HashMap<ClientId, Arc<RefCell<ClientState>>>,
}

impl State {
    pub fn new_client(&mut self, client1: ClientId, client2: ClientId) {
        self.state.insert(client1, Arc::new(RefCell::new(ClientState {
            other_client: client2,
            some_data: 0,
        })));
        self.state.insert(client2, Arc::new(RefCell::new(ClientState {
            other_client: client1,
            some_data: 0,
        })));
    }

    pub async fn with<'a, T, F, Fut>(&'a mut self, client: ClientId, func: F) -> Result<T, StateError>
    where
        F: Fn(&'a mut ClientState, &'a mut ClientState) -> Fut,
        Fut: Future<Output=T>,
    {
        let c1 = self.state.get(&client).ok_or(StateError::Blah)?.clone();
        let c2 = self.state.get(&c1.borrow().other_client).ok_or(StateError::Blah)?.clone();

        let mut c1b = c1.borrow_mut();
        let mut c2b = c2.borrow_mut();

        Ok(func(&mut *c1b, &mut *c2b).await)
    }
}

#[async_std::main]
async fn main() {
    let mut state = State::default();
    state.new_client(ClientId(1), ClientId(2));

    state.with(ClientId(1), |this, other| async {
        this.some_data = 23;
        other.some_data = 5;
    }).await.unwrap();

    println!("c1 {}", state.state.get(&ClientId(1)).unwrap().borrow().some_data);
    println!("c2 {}", state.state.get(&ClientId(2)).unwrap().borrow().some_data);
}
error[E0597]: `c1` does not live long enough
  --> src/main.rs:45:23
   |
37 |     pub async fn with<'a, T, F, Fut>(&'a mut self, client: ClientId, func: F) -> Result
   |                       -- lifetime `'a` defined here
...
45 |         let mut c1b = c1.borrow_mut();
   |                       ^^^^^^^^^^^^^^^ borrowed value does not live long enough
...
48 |         Ok(func(&mut *c1b, &mut *c2b).await)
   |            -------------------------- argument requires that `c1` is borrowed for `'a`
49 |     }
   |     - `c1` dropped here while still borrowed

error[E0597]: `c2` does not live long enough
  --> src/main.rs:46:23
   |
37 |     pub async fn with<'a, T, F, Fut>(&'a mut self, client: ClientId, func: F) -> Result
   |                       -- lifetime `'a` defined here
...
46 |         let mut c2b = c2.borrow_mut();
   |                       ^^^^^^^^^^^^^^^ borrowed value does not live long enough
47 |
48 |         Ok(func(&mut *c1b, &mut *c2b).await)
   |            -------------------------- argument requires that `c2` is borrowed for `'a`
49 |     }
   |     - `c2` dropped here while still borrowed

error[E0597]: `c1b` does not live long enough
  --> src/main.rs:48:23
   |
37 |     pub async fn with<'a, T, F, Fut>(&'a mut self, client: ClientId, func: F) -> Result
   |                       -- lifetime `'a` defined here
...
48 |         Ok(func(&mut *c1b, &mut *c2b).await)
   |            -----------^^^------------
   |            |          |
   |            |          borrowed value does not live long enough
   |            argument requires that `c1b` is borrowed for `'a`
49 |     }
   |     - `c1b` dropped here while still borrowed

error[E0597]: `c2b` does not live long enough
  --> src/main.rs:48:34
   |
37 |     pub async fn with<'a, T, F, Fut>(&'a mut self, client: ClientId, func: F) -> Result
   |                       -- lifetime `'a` defined here
...
48 |         Ok(func(&mut *c1b, &mut *c2b).await)
   |            ----------------------^^^-
   |            |                     |
   |            |                     borrowed value does not live long enough
   |            argument requires that `c2b` is borrowed for `'a`
49 |     }
   |     - `c2b` dropped here while still borrowed
yeah the same problem the borrowing of the refcell does not last long enough for the actual running of the async function.

I'm starting to run out of ideas at this point.a Mutex would face similar problems.I suppose I could solve this problem by passing in the `RefCell` itself to the function but I would prefer to hide the details of the inner workings of with.
use std::collections::HashMap;
use std::cell::RefCell;
use std::future::Future;

#[derive(Copy, Clone, Hash, Eq, PartialEq)]
struct ClientId(u32);

struct ClientState {
    other_client: ClientId,
    some_data: u32,
}

#[derive(Debug)]
enum StateError {
    Blah,
}

#[derive(Default)]
struct State {
    state: HashMap<ClientId, RefCell<ClientState>>,
}

impl State {
    pub fn new_client(&mut self, client1: ClientId, client2: ClientId) {
        self.state.insert(client1, RefCell::new(ClientState {
            other_client: client2,
            some_data: 0,
        }));
        self.state.insert(client2, RefCell::new(ClientState {
            other_client: client1,
            some_data: 0,
        }));
    }

    pub async fn with<'a, T, F, Fut>(&'a mut self, client: ClientId, func: F) -> Result<T, StateError>
    where
        F: Fn(&'a RefCell<ClientState>, &'a RefCell<ClientState>) -> Fut,
        Fut: Future<Output=T>,
    {
        let c1 = self.state.get(&client).ok_or(StateError::Blah)?;
        let c2 = self.state.get(&c1.borrow().other_client).ok_or(StateError::Blah)?;

        Ok(func(c1, c2).await)
    }
}

#[async_std::main]
async fn main() {
    let mut state = State::default();
    state.new_client(ClientId(1), ClientId(2));

    state.with(ClientId(1), |this, other| async {
        this.borrow_mut().some_data = 23;
        other.borrow_mut().some_data = 5;
    }).await.unwrap();

    println!("c1 {}", state.state.get(&ClientId(1)).unwrap().borrow().some_data);
    println!("c2 {}", state.state.get(&ClientId(2)).unwrap().borrow().some_data);
}
$ cargo run
   Compiling sufferingwithwith v0.1.0 (/home/jake/projects/sharnoth.com/0005)
    Finished dev [unoptimized + debuginfo] target(s) in 0.02s
     Running `target/debug/sufferingwithwith`
c1 23
c2 5
yeah I really do not like the `borrow_mut`s in the function itself BUT HEY IT WORKS.

in a questionable state of mind I figure "hey what happens if I send the `RefMut`s just directly by value?"
use std::collections::HashMap;
use std::cell::{RefCell, RefMut};
use std::future::Future;

use async_std::sync::{Arc, Mutex};

#[derive(Copy, Clone, Hash, Eq, PartialEq)]
struct ClientId(u32);

struct ClientState {
    other_client: ClientId,
    some_data: u32,
}

#[derive(Debug)]
enum StateError {
    Blah,
}

#[derive(Default)]
struct State {
    state: HashMap<ClientId, RefCell<ClientState>>,
}

impl State {
    pub fn new_client(&mut self, client1: ClientId, client2: ClientId) {
        self.state.insert(client1, RefCell::new(ClientState {
            other_client: client2,
            some_data: 0,
        }));
        self.state.insert(client2, RefCell::new(ClientState {
            other_client: client1,
            some_data: 0,
        }));
    }

    pub async fn with<'a, T, F, Fut>(&'a mut self, client: ClientId, func: F) -> Result<T, StateError>
    where
        F: Fn(RefMut<ClientState>, RefMut<ClientState>) -> Fut,
        Fut: Future<Output=T>,
    {
        let c1 = self.state.get(&client).ok_or(StateError::Blah)?;
        let c2 = self.state.get(&c1.borrow().other_client).ok_or(StateError::Blah)?;

        let c1b = c1.borrow_mut();
        let c2b = c2.borrow_mut();

        Ok(func(c1b, c2b).await)
    }
}

#[async_std::main]
async fn main() {
    let mut state = State::default();
    state.new_client(ClientId(1), ClientId(2));

    state.with(ClientId(1), |mut this, mut other| async move {
        this.some_data = 23;
        other.some_data = 5;
    }).await.unwrap();

    println!("c1 {}", state.state.get(&ClientId(1)).unwrap().borrow().some_data);
    println!("c2 {}", state.state.get(&ClientId(2)).unwrap().borrow().some_data);
}
error: lifetime may not live long enough
  --> src/main.rs:57:51
   |
57 |       state.with(ClientId(1), |mut this, mut other| async move {
   |  ______________________________--------___________-_^
   | |                              |                  |
   | |                              |                  return type of closure `impl Future` contains a lifetime `'2`
   | |                              has type `RefMut<'1, ClientState>`
58 | |         this.some_data = 23;
59 | |         other.some_data = 5;
60 | |     }).await.unwrap();
   | |_____^ returning this value requires that `'1` must outlive `'2`

error: lifetime may not live long enough
  --> src/main.rs:57:51
   |
57 |       state.with(ClientId(1), |mut this, mut other| async move {
   |  ________________________________________----------_^
   | |                                        |        |
   | |                                        |        return type of closure `impl Future` contains a lifetime `'4`
   | |                                        has type `RefMut<'3, ClientState>`
58 | |         this.some_data = 23;
59 | |         other.some_data = 5;
60 | |     }).await.unwrap();
   | |_____^ returning this value requires that `'3` must outlive `'4`
oh nevermind me just being dumb over here ignoring that naturally those structures would have lifetimes built into them.

anyway, it seems the core problems I am having is that references to outside data inside async closures is just not gonna work.so lets try some stupid shit and see which I hate least.
removing from hashmap to run the function then re-add after:
use std::collections::HashMap;
use std::cell::{RefCell, RefMut};
use std::future::Future;

use async_std::sync::{Arc, Mutex};

#[derive(Copy, Clone, Hash, Eq, PartialEq)]
struct ClientId(u32);

struct ClientState {
    other_client: ClientId,
    some_data: u32,
}

#[derive(Debug)]
enum StateError {
    Blah,
}

#[derive(Default)]
struct State {
    state: HashMap<ClientId, ClientState>,
}

impl State {
    pub fn new_client(&mut self, client1: ClientId, client2: ClientId) {
        self.state.insert(client1, ClientState {
            other_client: client2,
            some_data: 0,
        });
        self.state.insert(client2, ClientState {
            other_client: client1,
            some_data: 0,
        });
    }

    pub async fn with<'a, T, F, Fut>(&'a mut self, client: ClientId, func: F) -> Result<T, StateError>
    where
        F: Fn(&'a mut ClientState, &'a mut ClientState) -> Fut,
        Fut: Future<Output=T>,
    {
        let mut c1 = self.state.remove(&client).ok_or(StateError::Blah)?;
        let mut c2 = self.state.remove(&c1.other_client).ok_or(StateError::Blah)?;

        let result = func(&mut c1, &mut c2).await;

        let c1_client_id = c2.other_client;
        let c2_client_id = c1.other_client;
        self.state.insert(c1_client_id, c1);
        self.state.insert(c2_client_id, c2);

        Ok(result)
    }
}

#[async_std::main]
async fn main() {
    let mut state = State::default();
    state.new_client(ClientId(1), ClientId(2));

    state.with(ClientId(1), |this, other| async move {
        this.some_data = 23;
        other.some_data = 5;
    }).await.unwrap();

    println!("c1 {}", state.state.get(&ClientId(1)).unwrap().some_data);
    println!("c2 {}", state.state.get(&ClientId(2)).unwrap().some_data);
}
error[E0597]: `c1` does not live long enough
  --> src/main.rs:45:27
   |
37 |     pub async fn with<'a, T, F, Fut>(&'a mut self, client: ClientId, func: F) -> Result
   |                       -- lifetime `'a` defined here
...
45 |         let result = func(&mut c1, &mut c2).await;
   |                      -----^^^^^^^----------
   |                      |    |
   |                      |    borrowed value does not live long enough
   |                      argument requires that `c1` is borrowed for `'a`
...
53 |     }
   |     - `c1` dropped here while still borrowed

error[E0597]: `c2` does not live long enough
  --> src/main.rs:45:36
   |
37 |     pub async fn with<'a, T, F, Fut>(&'a mut self, client: ClientId, func: F) -> Result
   |                       -- lifetime `'a` defined here
...
45 |         let result = func(&mut c1, &mut c2).await;
   |                      --------------^^^^^^^-
   |                      |             |
   |                      |             borrowed value does not live long enough
   |                      argument requires that `c2` is borrowed for `'a`
...
53 |     }
   |     - `c2` dropped here while still borrowed

error[E0503]: cannot use `c2.other_client` because it was mutably borrowed
  --> src/main.rs:47:28
   |
37 |     pub async fn with<'a, T, F, Fut>(&'a mut self, client: ClientId, func: F) -> Result
   |                       -- lifetime `'a` defined here
...
45 |         let result = func(&mut c1, &mut c2).await;
   |                      ----------------------
   |                      |             |
   |                      |             borrow of `c2` occurs here
   |                      argument requires that `c2` is borrowed for `'a`
46 |
47 |         let c1_client_id = c2.other_client;
   |                            ^^^^^^^^^^^^^^^ use of borrowed `c2`

error[E0503]: cannot use `c1.other_client` because it was mutably borrowed
  --> src/main.rs:48:28
   |
37 |     pub async fn with<'a, T, F, Fut>(&'a mut self, client: ClientId, func: F) -> Result
   |                       -- lifetime `'a` defined here
...
45 |         let result = func(&mut c1, &mut c2).await;
   |                      ----------------------
   |                      |    |
   |                      |    borrow of `c1` occurs here
   |                      argument requires that `c1` is borrowed for `'a`
...
48 |         let c2_client_id = c1.other_client;
   |                            ^^^^^^^^^^^^^^^ use of borrowed `c1`

error[E0505]: cannot move out of `c1` because it is borrowed
  --> src/main.rs:49:41
   |
37 |     pub async fn with<'a, T, F, Fut>(&'a mut self, client: ClientId, func: F) -> Result
   |                       -- lifetime `'a` defined here
...
45 |         let result = func(&mut c1, &mut c2).await;
   |                      ----------------------
   |                      |    |
   |                      |    borrow of `c1` occurs here
   |                      argument requires that `c1` is borrowed for `'a`
...
49 |         self.state.insert(c1_client_id, c1);
   |                                         ^^ move out of `c1` occurs here

error[E0505]: cannot move out of `c2` because it is borrowed
  --> src/main.rs:50:41
   |
37 |     pub async fn with<'a, T, F, Fut>(&'a mut self, client: ClientId, func: F) -> Result
   |                       -- lifetime `'a` defined here
...
45 |         let result = func(&mut c1, &mut c2).await;
   |                      ----------------------
   |                      |             |
   |                      |             borrow of `c2` occurs here
   |                      argument requires that `c2` is borrowed for `'a`
...
50 |         self.state.insert(c2_client_id, c2);
   |                                         ^^ move out of `c2` occurs here

hahahah man jokes on me I have no idea what I am doing anymore.

ok so references here are infinite forever suffering how about I just pass the state by value and try and make that work in some capacity. so to pass by value then I need to like return the data back out:
use std::collections::HashMap;
use std::future::Future;

#[derive(Copy, Clone, Hash, Eq, PartialEq)]
struct ClientId(u32);

#[derive(Clone)]
struct ClientState {
    other_client: ClientId,
    some_data: u32,
}

#[derive(Debug)]
enum StateError {
    Blah,
}

#[derive(Default)]
struct State {
    state: HashMap<ClientId, ClientState>,
}

impl State {
    pub fn new_client(&mut self, client1: ClientId, client2: ClientId) {
        self.state.insert(client1, ClientState {
            other_client: client2,
            some_data: 0,
        });
        self.state.insert(client2, ClientState {
            other_client: client1,
            some_data: 0,
        });
    }

    pub async fn with<T, F, Fut>(&mut self, client: ClientId, func: F) -> Result<T, StateError>
    where
        F: Fn(ClientState, ClientState) -> Fut,
        Fut: Future<Output=(ClientState, ClientState, T)>,
    {
        let c1 = self.state.get(&client).ok_or(StateError::Blah)?;
        let c2 = self.state.get(&c1.other_client).ok_or(StateError::Blah)?;

        let (c1, c2, result) = func(c1.clone(), c2.clone()).await;

        let c1_client_id = c2.other_client;
        let c2_client_id = c1.other_client;
        self.state.insert(c1_client_id, c1);
        self.state.insert(c2_client_id, c2);

        Ok(result)
    }
}

#[async_std::main]
async fn main() {
    let mut state = State::default();
    state.new_client(ClientId(1), ClientId(2));

    state.with(ClientId(1), |mut this, mut other| async move {
        this.some_data = 23;
        other.some_data = 5;

        (this, other, ())
    }).await.unwrap();

    println!("c1 {}", state.state.get(&ClientId(1)).unwrap().some_data);
    println!("c2 {}", state.state.get(&ClientId(2)).unwrap().some_data);
}

$ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.02s
     Running `target/debug/sufferingwithwith`
c1 23
c2 5
I'm not sure if I dislike this more or less than the explicit borrow_mut()/lock() in the closure.I do think this version is susceptible to weird timing issues like the other one was.

so after some googling I find a possibly promising `FutureBoxLocal` future where I can specify a lifetime lets see how that goes
use std::collections::HashMap;
use std::cell::RefCell;

use futures::future::{Future, FutureExt, LocalBoxFuture};

#[derive(Copy, Clone, Hash, Eq, PartialEq)]
struct ClientId(u32);

struct ClientState {
    other_client: ClientId,
    some_data: u32,
}

#[derive(Debug)]
enum StateError {
    Blah,
}

#[derive(Default)]
struct State {
    state: HashMap<ClientId, RefCell<ClientState>>,
}

impl State {
    pub fn new_client(&mut self, client1: ClientId, client2: ClientId) {
        self.state.insert(client1, RefCell::new(ClientState {
            other_client: client2,
            some_data: 0,
        }));
        self.state.insert(client2, RefCell::new(ClientState {
            other_client: client1,
            some_data: 0,
        }));
    }

    pub fn with<'a, 'b, T, F, Fut>(&'a mut self, client: ClientId, func: F) -> Result<LocalBoxFuture<'a, T>, StateError>
    where
        'a: 'b,
        F: 'a + FnOnce(&'b mut ClientState, &'b mut ClientState) -> Fut,
        Fut: Future<Output=T> + 'b
    {
        let mut c1 = self.state.get(&client).ok_or(StateError::Blah)?.borrow_mut();
        let mut c2 = self.state.get(&c1.other_client).ok_or(StateError::Blah)?.borrow_mut();

        Ok(async move {
            func(&mut *c1, &mut *c2).await
        }
        .boxed_local())
    }
}

#[async_std::main]
async fn main() {
    let mut state = State::default();
    state.new_client(ClientId(1), ClientId(2));

    state.with(ClientId(1), |this, other| async {
        this.some_data = 23;
        other.some_data = 5;
    }).unwrap().await;

    println!("c1 {}", state.state.get(&ClientId(1)).unwrap().borrow().some_data);
    println!("c2 {}", state.state.get(&ClientId(2)).unwrap().borrow().some_data);
}
error[E0597]: `c1` does not live long enough
  --> src/main.rs:46:24
   |
36 |     pub fn with<'a, 'b, T, F, Fut>(&'a mut self, client: ClientId, func: F) -> Result, StateError>
   |                     -- lifetime `'b` defined here
...
46 |             func(&mut *c1, &mut *c2).await
   |             -----------^^-----------
   |             |          |
   |             |          borrowed value does not live long enough
   |             argument requires that `c1` is borrowed for `'b`
47 |         }
   |         - `c1` dropped here while still borrowed

error[E0597]: `c2` does not live long enough
  --> src/main.rs:46:34
   |
36 |     pub fn with<'a, 'b, T, F, Fut>(&'a mut self, client: ClientId, func: F) -> Result, StateError>
   |                     -- lifetime `'b` defined here
...
46 |             func(&mut *c1, &mut *c2).await
   |             ---------------------^^-
   |             |                    |
   |             |                    borrowed value does not live long enough
   |             argument requires that `c2` is borrowed for `'b`
47 |         }
   |         - `c2` dropped here while still borrowed
nope that sure didn't help!

you know just for completions sake lets just do the MutexGuard version of that RefCellimplementation above oh wait look at those docs theres a lifetime parameter for MutexGuard<'a, T> (and apparently for RefCell which I totally did not notice which may have made my life easier a while ago). maybe that will save the day
use std::collections::HashMap;
use async_std::sync::{Mutex, MutexGuard};
use futures::future::Future;

#[derive(Copy, Clone, Hash, Eq, PartialEq)]
struct ClientId(u32);

struct ClientState {
    other_client: ClientId,
    some_data: u32,
}

#[derive(Debug)]
enum StateError {
    Blah,
}

#[derive(Default)]
struct State {
    state: HashMap<ClientId, Mutex<ClientState>>,
}

impl State {
    pub fn new_client(&mut self, client1: ClientId, client2: ClientId) {
        self.state.insert(client1, Mutex::new(ClientState {
            other_client: client2,
            some_data: 0,
        }));
        self.state.insert(client2, Mutex::new(ClientState {
            other_client: client1,
            some_data: 0,
        }));
    }

    pub async fn with<'a, T, F, Fut>(&'a mut self, client: ClientId, func: F) -> Result<T, StateError>
    where
        F: FnOnce(MutexGuard<'a, ClientState>, MutexGuard<'a, ClientState>) -> Fut + 'a,
        Fut: Future<Output=T>,
    {
        let c1 = self.state.get(&client).ok_or(StateError::Blah)?.lock().await;
        let c2 = self.state.get(&c1.other_client).ok_or(StateError::Blah)?.lock().await;

        Ok(func(c1, c2).await)
    }
}

#[async_std::main]
async fn main() {
    let mut state = State::default();
    state.new_client(ClientId(1), ClientId(2));

    state.with(ClientId(1), |mut this, mut other| Box::pin(async move {
        this.some_data = 23;
        other.some_data = 5;
    })).await.unwrap();

    println!("c1 {}", state.state.get(&ClientId(1)).unwrap().lock().await.some_data);
    println!("c2 {}", state.state.get(&ClientId(2)).unwrap().lock().await.some_data);
}
$ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.02s
     Running `target/debug/sufferingwithwith`
c1 23
c2 5
oh. huh. cool.
[-] On effort-free 4 way photon blasts in psogc

In PSO time attack there is a category for starting the quest with the highest level shifta/deband that could be achieved through a photon blast. In 4 player games this ends up being level 81. The problem is that it takes time to get this before each run.
So here I am trying to make it a bit more streamlined.
I'm specifically targetting psogc on actual hardware so things like trainers and memory editors you can use on blue burst (or psogc through dolphin) are not an option. That leaves trying to use a network proxy to spoof packets.

I`ll be using my own psogc proxy I`ve been working on: darkbridge
Idea: I can pretend someone else is casting level 81 sd on me.
First, how do techs work?
Casting foie 1 causes my client to send these 3 packets:
60 00 0C 00 8D 02 00 00 00 00 00 00
60 00 0C 00 47 02 00 00 00 00 00 00
60 00 0C 00 48 02 00 00 00 00 00 00
60 basically means echo it to all other people in the room, 0C is the length of the packet.
60 00 0C 00 8D 02 00 00 00 00 00 00
60 00 0C 00 47 02 00 00 00 00 00 00
60 00 0C 00 48 02 00 00 00 00 00 00
So these are the bytes we care about.
8D, 47, and 48 are subcommand identifers and 02 is the length (in u32s). The rest is the payload data except its all zeros and not helpful at all.
Lets try foie 2:
60 00 0C 00 8D 02 00 00 00 00 00 00
60 00 0C 00 47 02 00 00 00 00 01 00
60 00 0C 00 48 02 00 00 00 00 01 00
Found the tech level!
what happens if we cast shifta 1?
60 00 0C 00 8D 02 00 00 00 00 00 00
60 00 0C 00 47 02 00 00 0D 00 00 00
60 00 0C 00 48 02 00 00 0D 00 00 00
And shifta 30:
60 00 0C 00 8D 02 00 00 0F 00 00 00
60 00 10 00 47 03 00 00 0D 00 0E 01 01 00 00 00
60 00 0C 00 48 02 00 00 0D 00 0E 00
...wait what?
hex(30-1) = 1D, but in the level there is 0E and this new 0F in command 8D.
Well turns out 0E + 0F = 1D, but this doesn't explain why it got split up over two bytes.
And 47 has some additional data...
Shifta 1 only targets yourself, but shifta 30 can target other players. So this is just saying which other players it affected. The first 01 is the number of targets followed by a u32 specifying the client id of the target. So if you hit 3 other players with shifta the packet would be:
60 00 18 00 47 05 00 00 06 00 0E 03 01 00 00 00 02 00 00 00 03 00 00 00
But back to that splitting up of the tech level. What happens if we just max out the level to FF and send us that packet?
jake@sharnoth $ cat s30.txt
raw client 60 00 8D 02 01 00 FF 00 00 00
raw client 60 00 47 03 01 00 0D 00 FF 01 00 00 00 00
raw client 60 00 48 02 01 00 0D 00 FF 00
jake@sharnoth $ cat s30.txt > /tmp/darkbridge
This packet is crafted so it seems like the other player in the game is casting shifta on us. In red is the client id of the other player and in yellow is the client id of yourself.
Note we omit the length portion of the packet here as the command calculates it automatically.
On cast my atp goes from 616 to 916. The shifta buff algorithm is approximately (.0128 * (techlvl - 1) + 1.1) * base atp.
(.0128*(31 - 1) + 1.1)*616 = 914. so level 31 shifta?
Maybe its a signed int and it overflew, lets try 7F:
jake@sharnoth $ cat s30.txt
raw client 60 00 8D 02 01 00 7F 00 00 00
raw client 60 00 47 03 01 00 0D 00 7F 01 00 00 00 00
raw client 60 00 48 02 01 00 0D 00 7F 00
jake@sharnoth $ cat s30.txt > /tmp/darkbridge
Aaaaaaaaaand the shifta isn't even a high enough level to affect me? Maybe there is an upper cap of 81 shifta or something:
jake@sharnoth $ cat s30.txt
raw client 60 00 8D 02 01 00 28 00 00 00
raw client 60 00 47 03 01 00 0D 00 28 01 00 00 00 00
raw client 60 00 48 02 01 00 0D 00 28 00
jake@sharnoth $ cat s30.txt > /tmp/darkbridge
Same result, it is too low level to affect me.
what is going on? Okay, lets increment from values we know are correct 0F and 0E.
jake@sharnoth $ cat s30.txt
raw client 60 00 8D 02 01 00 0F 00 00 00
raw client 60 00 47 03 01 00 0D 00 0F 01 00 00 00 00
raw client 60 00 48 02 01 00 0D 00 0F 00
jake@sharnoth $ cat s30.txt > /tmp/darkbridge
616 -> 796: shifta level...16? (.0128*(16 - 1) + 1.1)*616 = 795.87. Does 0E + 1 overflow to 0?
lets increment the other variable:
jake@sharnoth $ cat s30.txt
raw client 60 00 8D 02 01 00 10 00 00 00
raw client 60 00 47 03 01 00 0D 00 0E 01 00 00 00 00
raw client 60 00 48 02 01 00 0D 00 0E 00
jake@sharnoth $ cat s30.txt > /tmp/darkbridge
616 -> 908, level 30. huh.
And if I just change the first one...?
jake@sharnoth $ cat s30.txt
raw client 60 00 8D 02 01 00 20 00 00 00
raw client 60 00 47 03 01 00 0D 00 0E 01 00 00 00 00
raw client 60 00 48 02 01 00 0D 00 0E 00
jake@sharnoth $ cat s30.txt > /tmp/darkbridge
30 again

It looks like the level of techs that can be cast through this method is capped to reasonable values.

In conclusion: techs are dumb
Full vod of my researching this at: https://www.youtube.com/watch?v=2P0RXrYhe3M except since I suck at streaming the audio of the person I was talking to during all of this isn't there so it looks like I'm just talking to myself like a lunatic
[-] New site! (again)

So in my infinite free time I figured I should actually do something with this site.
Maybe.
Well at the very least I`ve filled out the projects page and made it look a bit nicer.
P.S. I can no longer reach dh through ssh (rip)
[-] I have no idea what I am doing

Rewrote site already because I was bored and it was easier than actually putting content on here.
Also added some sort of forum to discuss whatever I end up using this site for (ha ha ha).
[-] So I made this site for some reason

Well I bought this site for uh, some reason
Initially, the plan I think was to copy all the stuff over from Digital Haze before it was highjacked since I still seem to have ssh access to all the old data but everything there is quite outdated and useless (except the photos).
3DS Homebrew is starting to be a thing, might bother getting a 3Ds to make a vn3ds or something.
Or, I`ll embrace the DH philosophy of NO CONTENT and just use this server for email and irc bouncing.