From d3fd9ff69ae1c419bf7be3c82d4b706f7cc47ead Mon Sep 17 00:00:00 2001 From: Alex Parrill Date: Sat, 8 Jun 2019 17:51:35 -0400 Subject: Fix QueryResults possibly outliving the steam client by limiting it to the callback Strictly speaking, the query result can live for as long as the steam client, but since the Arc> that keeps the client alive isn't `Send`, we can't move it into the callback that captures the results. --- src/ugc.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/ugc.rs b/src/ugc.rs index b38dd2c..7982c75 100644 --- a/src/ugc.rs +++ b/src/ugc.rs @@ -1,10 +1,11 @@ use super::*; +use std::error; use std::ffi::{CStr, CString}; -use std::mem; use std::fmt; -use std::error; +use std::marker; +use std::mem; pub struct UGC { pub(crate) ugc: *mut sys::ISteamUGC, @@ -357,7 +358,7 @@ impl UserListQuery { /// Runs the query pub fn fetch(mut self, mut cb: F) - where F: FnMut(Result) + 'static + Send + where F: for<'a> FnMut(Result,SteamError>) + 'static + Send { let ugc = self.ugc; let inner = Arc::clone(&self.inner); @@ -383,6 +384,7 @@ impl UserListQuery { num_results_returned: v.m_unNumResultsReturned, num_results_total: v.m_unTotalMatchingResults, was_cached: v.m_bCachedData, + _phantom: Default::default(), }; cb(Ok(result)); }); @@ -415,21 +417,22 @@ impl UserListQuery { } /// Query results -pub struct QueryResults { +pub struct QueryResults<'a> { ugc: *mut sys::ISteamUGC, handle: sys::UGCQueryHandle_t, num_results_returned: u32, num_results_total: u32, was_cached: bool, + _phantom: marker::PhantomData<&'a sys::ISteamUGC>, } -impl Drop for QueryResults { +impl<'a> Drop for QueryResults<'a> { fn drop(&mut self) { unsafe { sys::SteamAPI_ISteamUGC_ReleaseQueryUGCRequest(self.ugc, self.handle); } } } -impl QueryResults { +impl<'a> QueryResults<'a> { /// Were these results retreived from a cache? pub fn was_cached(&self) -> bool { self.was_cached @@ -496,7 +499,7 @@ impl QueryResults { } /// Returns an iterator that runs over all the fetched results - pub fn iter<'a>(&'a self) -> impl Iterator + 'a { + pub fn iter<'b>(&'b self) -> impl Iterator + 'b { (0..self.returned_results()) .map(move |i| self.get(i).unwrap()) } -- cgit v1.2.3