From 6d908790964cb7416e7704d34ccbcb1197bcecf5 Mon Sep 17 00:00:00 2001 From: Jackson Coxson Date: Wed, 20 Aug 2025 18:27:38 -0600 Subject: [PATCH] Implement clone for RsdHandshake --- cpp/include/idevice++/rsd.hpp | 12 +++++++----- cpp/src/rsd.cpp | 18 ++++++++++++++++++ ffi/src/rsd.rs | 17 +++++++++++++++++ idevice/src/services/rsd.rs | 1 + 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/cpp/include/idevice++/rsd.hpp b/cpp/include/idevice++/rsd.hpp index b3898ec..1231a87 100644 --- a/cpp/include/idevice++/rsd.hpp +++ b/cpp/include/idevice++/rsd.hpp @@ -37,11 +37,13 @@ class RsdHandshake { std::optional service_info(const std::string& name, FfiError& err) const; // RAII / moves - ~RsdHandshake() noexcept = default; - RsdHandshake(RsdHandshake&&) noexcept = default; - RsdHandshake& operator=(RsdHandshake&&) noexcept = default; - RsdHandshake(const RsdHandshake&) = delete; - RsdHandshake& operator=(const RsdHandshake&) = delete; + ~RsdHandshake() noexcept = default; + RsdHandshake(RsdHandshake&&) noexcept = default; + RsdHandshake& operator=(RsdHandshake&&) noexcept = default; + + // Enable Copying + RsdHandshake(const RsdHandshake& other); + RsdHandshake& operator=(const RsdHandshake& other); RsdHandshakeHandle* raw() const noexcept { return handle_.get(); } static RsdHandshake adopt(RsdHandshakeHandle* h) noexcept { return RsdHandshake(h); } diff --git a/cpp/src/rsd.cpp b/cpp/src/rsd.cpp index 3575c6f..0511c54 100644 --- a/cpp/src/rsd.cpp +++ b/cpp/src/rsd.cpp @@ -61,6 +61,24 @@ static std::vector to_cpp_and_free(CRsdServiceArray* arr) { return out; } +RsdHandshake::RsdHandshake(const RsdHandshake& other) { + if (other.handle_) { + // Call the Rust FFI to clone the underlying handle + handle_.reset(rsd_handshake_clone(other.handle_.get())); + } + // If other.handle_ is null, our new handle_ will also be null, which is correct. +} + +RsdHandshake& RsdHandshake::operator=(const RsdHandshake& other) { + // Check for self-assignment + if (this != &other) { + // Create a temporary copy, then swap ownership + RsdHandshake temp(other); + std::swap(handle_, temp.handle_); + } + return *this; +} + // ---------- factory ---------- std::optional RsdHandshake::from_socket(ReadWrite&& rw, FfiError& err) { RsdHandshakeHandle* out = nullptr; diff --git a/ffi/src/rsd.rs b/ffi/src/rsd.rs index 9ab2bcb..0ac757f 100644 --- a/ffi/src/rsd.rs +++ b/ffi/src/rsd.rs @@ -10,6 +10,7 @@ use idevice::rsd::RsdHandshake; use crate::{IdeviceFfiError, RUNTIME, ReadWriteOpaque, ffi_err}; /// Opaque handle to an RsdHandshake +#[derive(Clone)] pub struct RsdHandshakeHandle(pub RsdHandshake); /// C-compatible representation of an RSD service @@ -370,6 +371,22 @@ pub unsafe extern "C" fn rsd_get_service_info( null_mut() } +/// Clones an RSD handshake +/// +/// # Safety +/// Pass a valid pointer allocated by this library +#[unsafe(no_mangle)] +pub unsafe extern "C" fn rsd_handshake_clone( + handshake: *mut RsdHandshakeHandle, +) -> *mut RsdHandshakeHandle { + if handshake.is_null() { + return null_mut(); + } + let handshake = unsafe { &mut *handshake }; + let new_handshake = handshake.clone(); + Box::into_raw(Box::new(new_handshake)) +} + /// Frees a string returned by RSD functions /// /// # Arguments diff --git a/idevice/src/services/rsd.rs b/idevice/src/services/rsd.rs index 9c41982..4013816 100644 --- a/idevice/src/services/rsd.rs +++ b/idevice/src/services/rsd.rs @@ -23,6 +23,7 @@ pub struct RsdService { pub service_version: Option, } +#[derive(Debug, Clone)] pub struct RsdHandshake { pub services: HashMap, pub protocol_version: usize,