use replace_with to replace the enum variant in-place without cloning

This commit is contained in:
Quaternions 2025-01-13 23:11:43 -08:00
parent 844c7a08e1
commit c6ff11dd3e

View File

@ -28,15 +28,16 @@ enum BufferState{
Buffered(SessionTime,MouseState<PhysicsTimeInner>), Buffered(SessionTime,MouseState<PhysicsTimeInner>),
} }
impl BufferState{ impl BufferState{
fn next_state(&self,ins:DoubleTimedUnbufferedInstruction,physics_timeline:&mut std::collections::VecDeque<TimedPhysicsInstruction>)->(Self,Option<TimedInstruction<OtherInstruction,PhysicsTimeInner>>){ fn next_state(self,ins:DoubleTimedUnbufferedInstruction,physics_timeline:&mut std::collections::VecDeque<TimedPhysicsInstruction>)->(Option<TimedInstruction<OtherInstruction,PhysicsTimeInner>>,Self){
match self{ let next_state=match self{
BufferState::Unbuffered=>{ BufferState::Unbuffered=>{
if let PhysicsUnbufferedInstruction::MoveMouse(pos)=ins.instruction.instruction{ if let PhysicsUnbufferedInstruction::MoveMouse(pos)=ins.instruction.instruction{
return (BufferState::Initializing(ins.time,MouseState{pos,time:ins.instruction.time}),None); return (None,BufferState::Initializing(ins.time,MouseState{pos,time:ins.instruction.time}));
} }
BufferState::Unbuffered
}, },
BufferState::Initializing(time,mouse_state)=>{ BufferState::Initializing(time,mouse_state)=>{
let timeout=*time+MOUSE_TIMEOUT; let timeout=time+MOUSE_TIMEOUT;
if timeout<ins.time{ if timeout<ins.time{
// duplicate the current mouse // duplicate the current mouse
physics_timeline.push_front(TimedInstruction{ physics_timeline.push_front(TimedInstruction{
@ -48,7 +49,7 @@ impl BufferState{
MouseInstruction::SetNextMouse(MouseState{pos:mouse_state.pos,time:ins.instruction.time}) MouseInstruction::SetNextMouse(MouseState{pos:mouse_state.pos,time:ins.instruction.time})
), ),
}); });
return (BufferState::Unbuffered,None); return (None,BufferState::Unbuffered);
} }
if let PhysicsUnbufferedInstruction::MoveMouse(pos)=ins.instruction.instruction{ if let PhysicsUnbufferedInstruction::MoveMouse(pos)=ins.instruction.instruction{
let next_mouse_state=MouseState{pos,time:ins.instruction.time}; let next_mouse_state=MouseState{pos,time:ins.instruction.time};
@ -56,17 +57,18 @@ impl BufferState{
time:mouse_state.time, time:mouse_state.time,
instruction:PhysicsInputInstruction::Mouse( instruction:PhysicsInputInstruction::Mouse(
MouseInstruction::ReplaceMouse{ MouseInstruction::ReplaceMouse{
s0:mouse_state.clone(), s0:mouse_state,
s1:next_mouse_state.clone(), s1:next_mouse_state.clone(),
} }
), ),
}); });
return (BufferState::Buffered(ins.time,next_mouse_state),None); return (None,BufferState::Buffered(ins.time,next_mouse_state));
} }
BufferState::Initializing(time,mouse_state)
}, },
BufferState::Buffered(time,mouse_state)=>{ BufferState::Buffered(time,mouse_state)=>{
// TODO: deduplicate code with above case // TODO: deduplicate code with above case
let timeout=*time+MOUSE_TIMEOUT; let timeout=time+MOUSE_TIMEOUT;
if timeout<ins.time{ if timeout<ins.time{
// duplicate the current mouse // duplicate the current mouse
physics_timeline.push_front(TimedInstruction{ physics_timeline.push_front(TimedInstruction{
@ -78,7 +80,7 @@ impl BufferState{
MouseInstruction::SetNextMouse(MouseState{pos:mouse_state.pos,time:ins.instruction.time}) MouseInstruction::SetNextMouse(MouseState{pos:mouse_state.pos,time:ins.instruction.time})
), ),
}); });
return (BufferState::Unbuffered,None); return (None,BufferState::Unbuffered);
} }
if let PhysicsUnbufferedInstruction::MoveMouse(pos)=ins.instruction.instruction{ if let PhysicsUnbufferedInstruction::MoveMouse(pos)=ins.instruction.instruction{
let next_mouse_state=MouseState{pos,time:ins.instruction.time}; let next_mouse_state=MouseState{pos,time:ins.instruction.time};
@ -88,10 +90,11 @@ impl BufferState{
MouseInstruction::SetNextMouse(next_mouse_state.clone()) MouseInstruction::SetNextMouse(next_mouse_state.clone())
), ),
}); });
return (BufferState::Buffered(ins.time,next_mouse_state),None); return (None,BufferState::Buffered(ins.time,next_mouse_state));
} }
BufferState::Buffered(time,mouse_state)
}, },
} };
let instruction_out=match ins.instruction.instruction{ let instruction_out=match ins.instruction.instruction{
PhysicsUnbufferedInstruction::MoveMouse(_)=>None, PhysicsUnbufferedInstruction::MoveMouse(_)=>None,
PhysicsUnbufferedInstruction::Other(other_instruction)=>Some(TimedInstruction{ PhysicsUnbufferedInstruction::Other(other_instruction)=>Some(TimedInstruction{
@ -99,7 +102,7 @@ impl BufferState{
instruction:other_instruction, instruction:other_instruction,
}), }),
}; };
(self.clone(),instruction_out) (instruction_out,next_state)
} }
} }
pub struct MouseInterpolator{ pub struct MouseInterpolator{
@ -139,9 +142,10 @@ impl MouseInterpolator{
// a mouse event is buffered, and exists within the last 10ms // a mouse event is buffered, and exists within the last 10ms
// case 3: stop // case 3: stop
// a mouse event is buffered, but no mouse events have transpired within 10ms // a mouse event is buffered, but no mouse events have transpired within 10ms
// TODO: remove clone // replace_with allows the enum variant to safely be replaced from behind a mutable reference
let ins_inner; let ins_inner=replace_with::replace_with_or_abort_and_return(&mut self.buffer_state,|buffer_state|{
(self.buffer_state,ins_inner)=self.buffer_state.next_state(ins,&mut self.physics_timeline); buffer_state.next_state(ins,&mut self.physics_timeline)
});
if let Some(ins)=ins_inner{ if let Some(ins)=ins_inner{
self.physics_timeline.push_back(TimedInstruction{ self.physics_timeline.push_back(TimedInstruction{
time:ins.time, time:ins.time,
@ -196,26 +200,27 @@ impl MouseInterpolator{
match ins{ match ins{
// could check if self.is_first_ready() // could check if self.is_first_ready()
StepInstruction::Pop=>self.physics_timeline.pop_front(), StepInstruction::Pop=>self.physics_timeline.pop_front(),
StepInstruction::Timeout=>match &self.buffer_state{ StepInstruction::Timeout=>replace_with::replace_with_or_abort_and_return(&mut self.buffer_state,|buffer_state|{
BufferState::Unbuffered=>None, match buffer_state{
BufferState::Initializing(time,mouse_state) BufferState::Unbuffered=>(None,BufferState::Unbuffered),
|BufferState::Buffered(time,mouse_state)=>{ BufferState::Initializing(_time,mouse_state)
// convert to BufferState::Unbuffered |BufferState::Buffered(_time,mouse_state)=>{
// use the first instruction which should be a mouse instruction // convert to BufferState::Unbuffered
// to push a ReplaceMouse instruction // use the first instruction which should be a mouse instruction
// duplicate the current mouse // to push a ReplaceMouse instruction
self.buffer_state=BufferState::Unbuffered; // duplicate the current mouse
Some(TimedInstruction{ (Some(TimedInstruction{
// This should be simulation_timer.time(timeout) // This should be simulation_timer.time(timeout)
// but the timer is not accessible from this scope // but the timer is not accessible from this scope
// and it's just here to say that the mouse isn't moving anyways. // and it's just here to say that the mouse isn't moving anyways.
time:mouse_state.time, time:mouse_state.time,
instruction:PhysicsInputInstruction::Mouse( instruction:PhysicsInputInstruction::Mouse(
MouseInstruction::SetNextMouse(MouseState{pos:mouse_state.pos,time:mouse_state.time}) MouseInstruction::SetNextMouse(MouseState{pos:mouse_state.pos,time:mouse_state.time})
), ),
}) }),BufferState::Unbuffered)
}, },
}, }
}),
} }
} }
} }