steamworks/steam/
remote_storage.rs

1use crate::steam::SteamResult;
2use crate::string_ext::FromUtf8NulTruncating;
3use crate::{AppId, Client, SteamId};
4use futures::Future;
5use snafu::{ResultExt, ensure};
6use std::ffi::CString;
7use steamworks_sys as sys;
8
9#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
10pub struct UgcHandle(sys::UGCHandle_t);
11
12impl UgcHandle {
13    pub fn download_to_location(
14        self,
15        client: Client,
16        location: impl Into<Vec<u8>>,
17        priority: u32,
18    ) -> impl Future<Output = Result<DownloadUGCResult, UgcDownloadToLocationError>> + Send {
19        let location = CString::new(location.into());
20        async move {
21            let location = location.context(NulSnafu)?;
22
23            let response: sys::RemoteStorageDownloadUGCResult_t = unsafe {
24                let handle = sys::SteamAPI_ISteamRemoteStorage_UGCDownloadToLocation(
25                    *client.0.remote_storage,
26                    self.0,
27                    location.as_ptr(),
28                    priority,
29                );
30
31                client.register_for_call_result(handle).await
32            };
33
34            {
35                let result = SteamResult::from_inner(response.m_eResult);
36
37                ensure!(
38                    result == SteamResult::OK,
39                    UGCDownloadToLocationSnafu {
40                        steam_result: result,
41                    }
42                );
43            }
44
45            Ok(DownloadUGCResult {
46                app_id: response.m_nAppID.into(),
47                size_in_bytes: response.m_nSizeInBytes,
48                filename: String::from_utf8_nul_truncating(&response.m_pchFileName[..]).expect(
49                    "Filename returned in RemoteStorageDownloadUGCResult_t was not valid UTF-8",
50                ),
51                steam_id_owner: SteamId::new(response.m_ulSteamIDOwner),
52            })
53        }
54    }
55
56    pub(crate) fn from_inner(handle: sys::UGCHandle_t) -> Option<Self> {
57        if handle == sys::k_UGCHandleInvalid {
58            None
59        } else {
60            Some(UgcHandle(handle))
61        }
62    }
63}
64
65#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
66pub struct DownloadUGCResult {
67    app_id: AppId,
68    size_in_bytes: i32,
69    filename: String,
70    steam_id_owner: SteamId,
71}
72
73#[derive(Debug, snafu::Snafu)]
74pub enum UgcDownloadToLocationError {
75    /// The location provided contains nul byte(s)
76    #[snafu(display("The location provided contained nul byte(s): {}", source))]
77    Nul { source: std::ffi::NulError },
78
79    /// `UGCDownloadToLocation()` failed
80    #[snafu(display("UGCDownloadToLocation() failed: {}", steam_result))]
81    UGCDownloadToLocation { steam_result: SteamResult },
82}