mirror of
https://github.com/jkcoxson/idevice.git
synced 2026-03-02 14:36:16 +01:00
Remove cpp 17 features and implement Rust into CPP
This commit is contained in:
@@ -1,43 +1,50 @@
|
||||
// Jackson Coxson
|
||||
|
||||
#include <idevice++/adapter_stream.hpp>
|
||||
#include <idevice++/option.hpp>
|
||||
|
||||
namespace IdeviceFFI {
|
||||
|
||||
bool AdapterStream::close(FfiError& err) {
|
||||
if (!h_)
|
||||
return true;
|
||||
if (IdeviceFfiError* e = ::adapter_close(h_)) {
|
||||
err = FfiError(e);
|
||||
return false;
|
||||
}
|
||||
h_ = nullptr;
|
||||
return true;
|
||||
Result<void, FfiError> AdapterStream::close() {
|
||||
if (!h_)
|
||||
return Ok();
|
||||
|
||||
FfiError e(::adapter_close(h_));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
h_ = nullptr;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
bool AdapterStream::send(const uint8_t* data, size_t len, FfiError& err) {
|
||||
if (!h_)
|
||||
return false;
|
||||
if (IdeviceFfiError* e = ::adapter_send(h_, data, len)) {
|
||||
err = FfiError(e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
Result<void, FfiError> AdapterStream::send(const uint8_t *data, size_t len) {
|
||||
if (!h_)
|
||||
return Err(FfiError::NotConnected());
|
||||
FfiError e(::adapter_send(h_, data, len));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return Ok();
|
||||
}
|
||||
|
||||
bool AdapterStream::recv(std::vector<uint8_t>& out, FfiError& err, size_t max_hint) {
|
||||
if (!h_)
|
||||
return false;
|
||||
if (max_hint == 0)
|
||||
max_hint = 2048;
|
||||
out.resize(max_hint);
|
||||
size_t actual = 0;
|
||||
if (IdeviceFfiError* e = ::adapter_recv(h_, out.data(), &actual, out.size())) {
|
||||
err = FfiError(e);
|
||||
return false;
|
||||
}
|
||||
out.resize(actual);
|
||||
return true;
|
||||
Result<std::vector<uint8_t>, FfiError> AdapterStream::recv(size_t max_hint) {
|
||||
if (!h_)
|
||||
return Err(FfiError::NotConnected());
|
||||
|
||||
if (max_hint == 0)
|
||||
max_hint = 2048;
|
||||
|
||||
std::vector<uint8_t> out(max_hint);
|
||||
size_t actual = 0;
|
||||
|
||||
FfiError e(::adapter_recv(h_, out.data(), &actual, out.size()));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
out.resize(actual);
|
||||
return Ok(std::move(out));
|
||||
}
|
||||
|
||||
} // namespace IdeviceFFI
|
||||
|
||||
@@ -5,193 +5,177 @@
|
||||
namespace IdeviceFFI {
|
||||
|
||||
// ---- Factories ----
|
||||
std::optional<AppService>
|
||||
AppService::connect_rsd(Adapter& adapter, RsdHandshake& rsd, FfiError& err) {
|
||||
AppServiceHandle* out = nullptr;
|
||||
if (IdeviceFfiError* e = ::app_service_connect_rsd(adapter.raw(), rsd.raw(), &out)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
return AppService::adopt(out);
|
||||
Result<AppService, FfiError> AppService::connect_rsd(Adapter &adapter,
|
||||
RsdHandshake &rsd) {
|
||||
AppServiceHandle *out = nullptr;
|
||||
if (IdeviceFfiError *e =
|
||||
::app_service_connect_rsd(adapter.raw(), rsd.raw(), &out)) {
|
||||
return Err(FfiError(e));
|
||||
}
|
||||
return Ok(AppService::adopt(out));
|
||||
}
|
||||
|
||||
std::optional<AppService> AppService::from_readwrite_ptr(ReadWriteOpaque* consumed, FfiError& err) {
|
||||
AppServiceHandle* out = nullptr;
|
||||
if (IdeviceFfiError* e = ::app_service_new(consumed, &out)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
return AppService::adopt(out);
|
||||
Result<AppService, FfiError>
|
||||
AppService::from_readwrite_ptr(ReadWriteOpaque *consumed) {
|
||||
AppServiceHandle *out = nullptr;
|
||||
if (IdeviceFfiError *e = ::app_service_new(consumed, &out)) {
|
||||
return Err(FfiError(e));
|
||||
}
|
||||
return Ok(AppService::adopt(out));
|
||||
}
|
||||
|
||||
std::optional<AppService> AppService::from_readwrite(ReadWrite&& rw, FfiError& err) {
|
||||
// Rust consumes the stream regardless of result → release BEFORE call
|
||||
return from_readwrite_ptr(rw.release(), err);
|
||||
Result<AppService, FfiError> AppService::from_readwrite(ReadWrite &&rw) {
|
||||
// Rust consumes the stream regardless of result → release BEFORE call
|
||||
return from_readwrite_ptr(rw.release());
|
||||
}
|
||||
|
||||
// ---- Helpers to copy/free C arrays ----
|
||||
static std::vector<AppInfo> copy_and_free_app_list(AppListEntryC* arr, size_t n) {
|
||||
std::vector<AppInfo> out;
|
||||
out.reserve(n);
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
const auto& c = arr[i];
|
||||
AppInfo a;
|
||||
a.is_removable = c.is_removable != 0;
|
||||
if (c.name)
|
||||
a.name = c.name;
|
||||
a.is_first_party = c.is_first_party != 0;
|
||||
if (c.path)
|
||||
a.path = c.path;
|
||||
if (c.bundle_identifier)
|
||||
a.bundle_identifier = c.bundle_identifier;
|
||||
a.is_developer_app = c.is_developer_app != 0;
|
||||
if (c.bundle_version)
|
||||
a.bundle_version = std::string(c.bundle_version);
|
||||
a.is_internal = c.is_internal != 0;
|
||||
a.is_hidden = c.is_hidden != 0;
|
||||
a.is_app_clip = c.is_app_clip != 0;
|
||||
if (c.version)
|
||||
a.version = std::string(c.version);
|
||||
out.emplace_back(std::move(a));
|
||||
}
|
||||
::app_service_free_app_list(arr, n);
|
||||
return out;
|
||||
static std::vector<AppInfo> copy_and_free_app_list(AppListEntryC *arr,
|
||||
size_t n) {
|
||||
std::vector<AppInfo> out;
|
||||
out.reserve(n);
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
const auto &c = arr[i];
|
||||
AppInfo a;
|
||||
a.is_removable = c.is_removable != 0;
|
||||
if (c.name)
|
||||
a.name = c.name;
|
||||
a.is_first_party = c.is_first_party != 0;
|
||||
if (c.path)
|
||||
a.path = c.path;
|
||||
if (c.bundle_identifier)
|
||||
a.bundle_identifier = c.bundle_identifier;
|
||||
a.is_developer_app = c.is_developer_app != 0;
|
||||
if (c.bundle_version)
|
||||
a.bundle_version = std::string(c.bundle_version);
|
||||
a.is_internal = c.is_internal != 0;
|
||||
a.is_hidden = c.is_hidden != 0;
|
||||
a.is_app_clip = c.is_app_clip != 0;
|
||||
if (c.version)
|
||||
a.version = std::string(c.version);
|
||||
out.emplace_back(std::move(a));
|
||||
}
|
||||
::app_service_free_app_list(arr, n);
|
||||
return out;
|
||||
}
|
||||
|
||||
static std::vector<ProcessToken> copy_and_free_process_list(ProcessTokenC* arr, size_t n) {
|
||||
std::vector<ProcessToken> out;
|
||||
out.reserve(n);
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
ProcessToken p;
|
||||
p.pid = arr[i].pid;
|
||||
if (arr[i].executable_url)
|
||||
p.executable_url = std::string(arr[i].executable_url);
|
||||
out.emplace_back(std::move(p));
|
||||
}
|
||||
::app_service_free_process_list(arr, n);
|
||||
return out;
|
||||
static std::vector<ProcessToken> copy_and_free_process_list(ProcessTokenC *arr,
|
||||
size_t n) {
|
||||
std::vector<ProcessToken> out;
|
||||
out.reserve(n);
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
ProcessToken p;
|
||||
p.pid = arr[i].pid;
|
||||
if (arr[i].executable_url)
|
||||
p.executable_url = std::string(arr[i].executable_url);
|
||||
out.emplace_back(std::move(p));
|
||||
}
|
||||
::app_service_free_process_list(arr, n);
|
||||
return out;
|
||||
}
|
||||
|
||||
// ---- API impls ----
|
||||
std::optional<std::vector<AppInfo>> AppService::list_apps(bool app_clips,
|
||||
bool removable,
|
||||
bool hidden,
|
||||
bool internal,
|
||||
bool default_apps,
|
||||
FfiError& err) const {
|
||||
AppListEntryC* arr = nullptr;
|
||||
size_t n = 0;
|
||||
if (IdeviceFfiError* e = ::app_service_list_apps(handle_.get(),
|
||||
app_clips ? 1 : 0,
|
||||
removable ? 1 : 0,
|
||||
hidden ? 1 : 0,
|
||||
internal ? 1 : 0,
|
||||
default_apps ? 1 : 0,
|
||||
&arr,
|
||||
&n)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
return copy_and_free_app_list(arr, n);
|
||||
Result<std::vector<AppInfo>, FfiError>
|
||||
AppService::list_apps(bool app_clips, bool removable, bool hidden,
|
||||
bool internal, bool default_apps) const {
|
||||
AppListEntryC *arr = nullptr;
|
||||
size_t n = 0;
|
||||
if (IdeviceFfiError *e = ::app_service_list_apps(
|
||||
handle_.get(), app_clips ? 1 : 0, removable ? 1 : 0, hidden ? 1 : 0,
|
||||
internal ? 1 : 0, default_apps ? 1 : 0, &arr, &n)) {
|
||||
|
||||
return Err(FfiError(e));
|
||||
}
|
||||
return Ok(copy_and_free_app_list(arr, n));
|
||||
}
|
||||
|
||||
std::optional<LaunchResponse> AppService::launch(const std::string& bundle_id,
|
||||
const std::vector<std::string>& argv,
|
||||
bool kill_existing,
|
||||
bool start_suspended,
|
||||
FfiError& err) {
|
||||
std::vector<const char*> c_argv;
|
||||
c_argv.reserve(argv.size());
|
||||
for (auto& s : argv)
|
||||
c_argv.push_back(s.c_str());
|
||||
Result<LaunchResponse, FfiError>
|
||||
AppService::launch(const std::string &bundle_id,
|
||||
const std::vector<std::string> &argv, bool kill_existing,
|
||||
bool start_suspended) {
|
||||
std::vector<const char *> c_argv;
|
||||
c_argv.reserve(argv.size());
|
||||
for (auto &s : argv)
|
||||
c_argv.push_back(s.c_str());
|
||||
|
||||
LaunchResponseC* resp = nullptr;
|
||||
if (IdeviceFfiError* e = ::app_service_launch_app(handle_.get(),
|
||||
bundle_id.c_str(),
|
||||
c_argv.empty() ? nullptr : c_argv.data(),
|
||||
c_argv.size(),
|
||||
kill_existing ? 1 : 0,
|
||||
start_suspended ? 1 : 0,
|
||||
NULL, // TODO: stdio handling
|
||||
&resp)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
LaunchResponseC *resp = nullptr;
|
||||
if (IdeviceFfiError *e = ::app_service_launch_app(
|
||||
handle_.get(), bundle_id.c_str(),
|
||||
c_argv.empty() ? nullptr : c_argv.data(), c_argv.size(),
|
||||
kill_existing ? 1 : 0, start_suspended ? 1 : 0,
|
||||
NULL, // TODO: stdio handling
|
||||
&resp)) {
|
||||
return Err(FfiError(e));
|
||||
}
|
||||
|
||||
LaunchResponse out;
|
||||
out.process_identifier_version = resp->process_identifier_version;
|
||||
out.pid = resp->pid;
|
||||
if (resp->executable_url)
|
||||
out.executable_url = resp->executable_url;
|
||||
if (resp->audit_token && resp->audit_token_len > 0) {
|
||||
out.audit_token.assign(resp->audit_token, resp->audit_token + resp->audit_token_len);
|
||||
}
|
||||
::app_service_free_launch_response(resp);
|
||||
return out;
|
||||
LaunchResponse out;
|
||||
out.process_identifier_version = resp->process_identifier_version;
|
||||
out.pid = resp->pid;
|
||||
if (resp->executable_url)
|
||||
out.executable_url = resp->executable_url;
|
||||
if (resp->audit_token && resp->audit_token_len > 0) {
|
||||
out.audit_token.assign(resp->audit_token,
|
||||
resp->audit_token + resp->audit_token_len);
|
||||
}
|
||||
::app_service_free_launch_response(resp);
|
||||
return Ok(std::move(out));
|
||||
}
|
||||
|
||||
std::optional<std::vector<ProcessToken>> AppService::list_processes(FfiError& err) const {
|
||||
ProcessTokenC* arr = nullptr;
|
||||
size_t n = 0;
|
||||
if (IdeviceFfiError* e = ::app_service_list_processes(handle_.get(), &arr, &n)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
return copy_and_free_process_list(arr, n);
|
||||
Result<std::vector<ProcessToken>, FfiError> AppService::list_processes() const {
|
||||
ProcessTokenC *arr = nullptr;
|
||||
size_t n = 0;
|
||||
if (IdeviceFfiError *e =
|
||||
::app_service_list_processes(handle_.get(), &arr, &n)) {
|
||||
return Err(FfiError(e));
|
||||
}
|
||||
return Ok(copy_and_free_process_list(arr, n));
|
||||
}
|
||||
|
||||
bool AppService::uninstall(const std::string& bundle_id, FfiError& err) {
|
||||
if (IdeviceFfiError* e = ::app_service_uninstall_app(handle_.get(), bundle_id.c_str())) {
|
||||
err = FfiError(e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
Result<void, FfiError> AppService::uninstall(const std::string &bundle_id) {
|
||||
if (IdeviceFfiError *e =
|
||||
::app_service_uninstall_app(handle_.get(), bundle_id.c_str())) {
|
||||
return Err(FfiError(e));
|
||||
}
|
||||
return Ok();
|
||||
}
|
||||
|
||||
std::optional<SignalResponse>
|
||||
AppService::send_signal(uint32_t pid, uint32_t signal, FfiError& err) {
|
||||
SignalResponseC* c = nullptr;
|
||||
if (IdeviceFfiError* e = ::app_service_send_signal(handle_.get(), pid, signal, &c)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
SignalResponse out;
|
||||
out.pid = c->pid;
|
||||
if (c->executable_url)
|
||||
out.executable_url = std::string(c->executable_url);
|
||||
out.device_timestamp_ms = c->device_timestamp;
|
||||
out.signal = c->signal;
|
||||
::app_service_free_signal_response(c);
|
||||
return out;
|
||||
Result<SignalResponse, FfiError> AppService::send_signal(uint32_t pid,
|
||||
uint32_t signal) {
|
||||
SignalResponseC *c = nullptr;
|
||||
if (IdeviceFfiError *e =
|
||||
::app_service_send_signal(handle_.get(), pid, signal, &c)) {
|
||||
return Err(FfiError(e));
|
||||
}
|
||||
SignalResponse out;
|
||||
out.pid = c->pid;
|
||||
if (c->executable_url)
|
||||
out.executable_url = std::string(c->executable_url);
|
||||
out.device_timestamp_ms = c->device_timestamp;
|
||||
out.signal = c->signal;
|
||||
::app_service_free_signal_response(c);
|
||||
return Ok(std::move(out));
|
||||
}
|
||||
|
||||
std::optional<IconData> AppService::fetch_icon(const std::string& bundle_id,
|
||||
float width,
|
||||
float height,
|
||||
float scale,
|
||||
bool allow_placeholder,
|
||||
FfiError& err) {
|
||||
IconDataC* c = nullptr;
|
||||
if (IdeviceFfiError* e = ::app_service_fetch_app_icon(handle_.get(),
|
||||
bundle_id.c_str(),
|
||||
width,
|
||||
height,
|
||||
scale,
|
||||
allow_placeholder ? 1 : 0,
|
||||
&c)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
IconData out;
|
||||
if (c->data && c->data_len) {
|
||||
out.data.assign(c->data, c->data + c->data_len);
|
||||
}
|
||||
out.icon_width = c->icon_width;
|
||||
out.icon_height = c->icon_height;
|
||||
out.minimum_width = c->minimum_width;
|
||||
out.minimum_height = c->minimum_height;
|
||||
::app_service_free_icon_data(c);
|
||||
return out;
|
||||
Result<IconData, FfiError> AppService::fetch_icon(const std::string &bundle_id,
|
||||
float width, float height,
|
||||
float scale,
|
||||
bool allow_placeholder) {
|
||||
IconDataC *c = nullptr;
|
||||
if (IdeviceFfiError *e = ::app_service_fetch_app_icon(
|
||||
handle_.get(), bundle_id.c_str(), width, height, scale,
|
||||
allow_placeholder ? 1 : 0, &c)) {
|
||||
return Err(FfiError(e));
|
||||
}
|
||||
IconData out;
|
||||
if (c->data && c->data_len) {
|
||||
out.data.assign(c->data, c->data + c->data_len);
|
||||
}
|
||||
out.icon_width = c->icon_width;
|
||||
out.icon_height = c->icon_height;
|
||||
out.minimum_width = c->minimum_width;
|
||||
out.minimum_height = c->minimum_height;
|
||||
::app_service_free_icon_data(c);
|
||||
return Ok(std::move(out));
|
||||
}
|
||||
|
||||
} // namespace IdeviceFFI
|
||||
|
||||
@@ -6,114 +6,115 @@ namespace IdeviceFFI {
|
||||
|
||||
// ---- Factories ----
|
||||
|
||||
std::optional<CoreDeviceProxy> CoreDeviceProxy::connect(Provider& provider, FfiError& err) {
|
||||
CoreDeviceProxyHandle* out = nullptr;
|
||||
if (IdeviceFfiError* e = ::core_device_proxy_connect(provider.raw(), &out)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
return CoreDeviceProxy::adopt(out);
|
||||
Result<CoreDeviceProxy, FfiError> CoreDeviceProxy::connect(Provider &provider) {
|
||||
CoreDeviceProxyHandle *out = nullptr;
|
||||
FfiError e(::core_device_proxy_connect(provider.raw(), &out));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return Ok(CoreDeviceProxy::adopt(out));
|
||||
}
|
||||
|
||||
std::optional<CoreDeviceProxy> CoreDeviceProxy::from_socket(Idevice&& socket, FfiError& err) {
|
||||
CoreDeviceProxyHandle* out = nullptr;
|
||||
Result<CoreDeviceProxy, FfiError>
|
||||
CoreDeviceProxy::from_socket(Idevice &&socket) {
|
||||
CoreDeviceProxyHandle *out = nullptr;
|
||||
|
||||
// Rust consumes the socket regardless of result → release BEFORE call
|
||||
IdeviceHandle* raw = socket.release();
|
||||
// Rust consumes the socket regardless of result → release BEFORE call
|
||||
IdeviceHandle *raw = socket.release();
|
||||
|
||||
if (IdeviceFfiError* e = ::core_device_proxy_new(raw, &out)) {
|
||||
// socket is already consumed on error; do NOT touch it
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
return CoreDeviceProxy::adopt(out);
|
||||
FfiError e(::core_device_proxy_new(raw, &out));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return Ok(CoreDeviceProxy::adopt(out));
|
||||
}
|
||||
|
||||
// ---- IO ----
|
||||
|
||||
bool CoreDeviceProxy::send(const uint8_t* data, size_t len, FfiError& err) {
|
||||
if (IdeviceFfiError* e = ::core_device_proxy_send(handle_.get(), data, len)) {
|
||||
err = FfiError(e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
Result<void, FfiError> CoreDeviceProxy::send(const uint8_t *data, size_t len) {
|
||||
FfiError e(::core_device_proxy_send(handle_.get(), data, len));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return Ok();
|
||||
}
|
||||
|
||||
bool CoreDeviceProxy::recv(std::vector<uint8_t>& out, FfiError& err) {
|
||||
if (out.empty())
|
||||
out.resize(4096); // a reasonable default; caller can pre-size
|
||||
size_t actual = 0;
|
||||
if (IdeviceFfiError* e =
|
||||
::core_device_proxy_recv(handle_.get(), out.data(), &actual, out.size())) {
|
||||
err = FfiError(e);
|
||||
return false;
|
||||
}
|
||||
out.resize(actual);
|
||||
return true;
|
||||
Result<void, FfiError> CoreDeviceProxy::recv(std::vector<uint8_t> &out) {
|
||||
if (out.empty())
|
||||
out.resize(4096); // a reasonable default; caller can pre-size
|
||||
size_t actual = 0;
|
||||
FfiError e(
|
||||
::core_device_proxy_recv(handle_.get(), out.data(), &actual, out.size()));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
out.resize(actual);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
// ---- Handshake ----
|
||||
|
||||
std::optional<CoreClientParams> CoreDeviceProxy::get_client_parameters(FfiError& err) const {
|
||||
uint16_t mtu = 0;
|
||||
char* addr_c = nullptr;
|
||||
char* mask_c = nullptr;
|
||||
Result<CoreClientParams, FfiError>
|
||||
CoreDeviceProxy::get_client_parameters() const {
|
||||
uint16_t mtu = 0;
|
||||
char *addr_c = nullptr;
|
||||
char *mask_c = nullptr;
|
||||
|
||||
if (IdeviceFfiError* e =
|
||||
::core_device_proxy_get_client_parameters(handle_.get(), &mtu, &addr_c, &mask_c)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
FfiError e(::core_device_proxy_get_client_parameters(handle_.get(), &mtu,
|
||||
&addr_c, &mask_c));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
CoreClientParams params;
|
||||
params.mtu = mtu;
|
||||
if (addr_c) {
|
||||
params.address = addr_c;
|
||||
::idevice_string_free(addr_c);
|
||||
}
|
||||
if (mask_c) {
|
||||
params.netmask = mask_c;
|
||||
::idevice_string_free(mask_c);
|
||||
}
|
||||
return params;
|
||||
CoreClientParams params;
|
||||
params.mtu = mtu;
|
||||
if (addr_c) {
|
||||
params.address = addr_c;
|
||||
::idevice_string_free(addr_c);
|
||||
}
|
||||
if (mask_c) {
|
||||
params.netmask = mask_c;
|
||||
::idevice_string_free(mask_c);
|
||||
}
|
||||
return Ok(std::move(params));
|
||||
}
|
||||
|
||||
std::optional<std::string> CoreDeviceProxy::get_server_address(FfiError& err) const {
|
||||
char* addr_c = nullptr;
|
||||
if (IdeviceFfiError* e = ::core_device_proxy_get_server_address(handle_.get(), &addr_c)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
std::string s;
|
||||
if (addr_c) {
|
||||
s = addr_c;
|
||||
::idevice_string_free(addr_c);
|
||||
}
|
||||
return s;
|
||||
Result<std::string, FfiError> CoreDeviceProxy::get_server_address() const {
|
||||
char *addr_c = nullptr;
|
||||
FfiError e(::core_device_proxy_get_server_address(handle_.get(), &addr_c));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
std::string s;
|
||||
if (addr_c) {
|
||||
s = addr_c;
|
||||
::idevice_string_free(addr_c);
|
||||
}
|
||||
return Ok(s);
|
||||
}
|
||||
|
||||
std::optional<uint16_t> CoreDeviceProxy::get_server_rsd_port(FfiError& err) const {
|
||||
uint16_t port = 0;
|
||||
if (IdeviceFfiError* e = ::core_device_proxy_get_server_rsd_port(handle_.get(), &port)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
return port;
|
||||
Result<uint16_t, FfiError> CoreDeviceProxy::get_server_rsd_port() const {
|
||||
uint16_t port = 0;
|
||||
FfiError e(::core_device_proxy_get_server_rsd_port(handle_.get(), &port));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return Ok(port);
|
||||
}
|
||||
|
||||
// ---- Adapter creation (consumes *this) ----
|
||||
|
||||
std::optional<Adapter> CoreDeviceProxy::create_tcp_adapter(FfiError& err) && {
|
||||
AdapterHandle* out = nullptr;
|
||||
Result<Adapter, FfiError> CoreDeviceProxy::create_tcp_adapter() && {
|
||||
AdapterHandle *out = nullptr;
|
||||
|
||||
// Rust consumes the proxy regardless of result → release BEFORE call
|
||||
CoreDeviceProxyHandle* raw = this->release();
|
||||
// Rust consumes the proxy regardless of result → release BEFORE call
|
||||
CoreDeviceProxyHandle *raw = this->release();
|
||||
|
||||
if (IdeviceFfiError* e = ::core_device_proxy_create_tcp_adapter(raw, &out)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
return Adapter::adopt(out);
|
||||
FfiError e(::core_device_proxy_create_tcp_adapter(raw, &out));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return Ok(Adapter::adopt(out));
|
||||
}
|
||||
|
||||
} // namespace IdeviceFFI
|
||||
|
||||
@@ -6,136 +6,138 @@
|
||||
namespace IdeviceFFI {
|
||||
|
||||
// ---- helpers ----
|
||||
static std::optional<std::string> take_cstring(char* p) {
|
||||
if (!p)
|
||||
return std::nullopt;
|
||||
std::string s(p);
|
||||
::idevice_string_free(p);
|
||||
return s;
|
||||
static Option<std::string> take_cstring(char *p) {
|
||||
if (!p)
|
||||
return None;
|
||||
std::string s(p);
|
||||
::idevice_string_free(p);
|
||||
return Some(s);
|
||||
}
|
||||
|
||||
// ---- DebugCommand ----
|
||||
std::optional<DebugCommand> DebugCommand::make(const std::string& name,
|
||||
const std::vector<std::string>& argv) {
|
||||
std::vector<const char*> c_argv;
|
||||
c_argv.reserve(argv.size());
|
||||
for (auto& a : argv)
|
||||
c_argv.push_back(a.c_str());
|
||||
Option<DebugCommand> DebugCommand::make(const std::string &name,
|
||||
const std::vector<std::string> &argv) {
|
||||
std::vector<const char *> c_argv;
|
||||
c_argv.reserve(argv.size());
|
||||
for (auto &a : argv)
|
||||
c_argv.push_back(a.c_str());
|
||||
|
||||
auto* h = ::debugserver_command_new(
|
||||
name.c_str(),
|
||||
c_argv.empty() ? nullptr : const_cast<const char* const*>(c_argv.data()),
|
||||
c_argv.size());
|
||||
if (!h)
|
||||
return std::nullopt;
|
||||
return DebugCommand(h);
|
||||
auto *h = ::debugserver_command_new(
|
||||
name.c_str(),
|
||||
c_argv.empty() ? nullptr : const_cast<const char *const *>(c_argv.data()),
|
||||
c_argv.size());
|
||||
if (!h)
|
||||
return None;
|
||||
return Some(DebugCommand(h));
|
||||
}
|
||||
|
||||
// ---- DebugProxy factories ----
|
||||
std::optional<DebugProxy>
|
||||
DebugProxy::connect_rsd(Adapter& adapter, RsdHandshake& rsd, FfiError& err) {
|
||||
::DebugProxyHandle* out = nullptr;
|
||||
if (IdeviceFfiError* e = ::debug_proxy_connect_rsd(adapter.raw(), rsd.raw(), &out)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
return DebugProxy(out);
|
||||
Result<DebugProxy, FfiError> DebugProxy::connect_rsd(Adapter &adapter,
|
||||
RsdHandshake &rsd) {
|
||||
::DebugProxyHandle *out = nullptr;
|
||||
FfiError e(::debug_proxy_connect_rsd(adapter.raw(), rsd.raw(), &out));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return Ok(DebugProxy(out));
|
||||
}
|
||||
|
||||
std::optional<DebugProxy> DebugProxy::from_readwrite_ptr(::ReadWriteOpaque* consumed,
|
||||
FfiError& err) {
|
||||
::DebugProxyHandle* out = nullptr;
|
||||
if (IdeviceFfiError* e = ::debug_proxy_new(consumed, &out)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
return DebugProxy(out);
|
||||
Result<DebugProxy, FfiError>
|
||||
DebugProxy::from_readwrite_ptr(::ReadWriteOpaque *consumed) {
|
||||
::DebugProxyHandle *out = nullptr;
|
||||
FfiError e(::debug_proxy_new(consumed, &out));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return Ok(DebugProxy(out));
|
||||
}
|
||||
|
||||
std::optional<DebugProxy> DebugProxy::from_readwrite(ReadWrite&& rw, FfiError& err) {
|
||||
// Rust consumes the pointer regardless of outcome; release before calling
|
||||
return from_readwrite_ptr(rw.release(), err);
|
||||
Result<DebugProxy, FfiError> DebugProxy::from_readwrite(ReadWrite &&rw) {
|
||||
// Rust consumes the pointer regardless of outcome; release before calling
|
||||
return from_readwrite_ptr(rw.release());
|
||||
}
|
||||
|
||||
// ---- DebugProxy API ----
|
||||
std::optional<std::string> DebugProxy::send_command(const std::string& name,
|
||||
const std::vector<std::string>& argv,
|
||||
FfiError& err) {
|
||||
auto cmd = DebugCommand::make(name, argv);
|
||||
if (!cmd) {
|
||||
// treat as invalid arg
|
||||
err.code = -1;
|
||||
err.message = "debugserver_command_new failed";
|
||||
return std::nullopt;
|
||||
}
|
||||
Result<Option<std::string>, FfiError>
|
||||
DebugProxy::send_command(const std::string &name,
|
||||
const std::vector<std::string> &argv) {
|
||||
auto cmdRes = DebugCommand::make(name, argv);
|
||||
if (cmdRes.is_none()) {
|
||||
// treat as invalid arg
|
||||
FfiError err;
|
||||
err.code = -1;
|
||||
err.message = "debugserver_command_new failed";
|
||||
return Err(err);
|
||||
}
|
||||
auto cmd = std::move(cmdRes).unwrap();
|
||||
|
||||
char* resp_c = nullptr;
|
||||
if (IdeviceFfiError* e = ::debug_proxy_send_command(handle_, cmd->raw(), &resp_c)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
return take_cstring(resp_c); // may be null → std::nullopt
|
||||
char *resp_c = nullptr;
|
||||
FfiError e(::debug_proxy_send_command(handle_, cmd.raw(), &resp_c));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
return Ok(take_cstring(resp_c));
|
||||
}
|
||||
|
||||
std::optional<std::string> DebugProxy::read_response(FfiError& err) {
|
||||
char* resp_c = nullptr;
|
||||
if (IdeviceFfiError* e = ::debug_proxy_read_response(handle_, &resp_c)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
return take_cstring(resp_c);
|
||||
Result<Option<std::string>, FfiError> DebugProxy::read_response() {
|
||||
char *resp_c = nullptr;
|
||||
FfiError e(::debug_proxy_read_response(handle_, &resp_c));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return Ok(take_cstring(resp_c));
|
||||
}
|
||||
|
||||
bool DebugProxy::send_raw(const std::vector<uint8_t>& data, FfiError& err) {
|
||||
if (IdeviceFfiError* e = ::debug_proxy_send_raw(handle_, data.data(), data.size())) {
|
||||
err = FfiError(e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
Result<void, FfiError> DebugProxy::send_raw(const std::vector<uint8_t> &data) {
|
||||
FfiError e(::debug_proxy_send_raw(handle_, data.data(), data.size()));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return Ok();
|
||||
}
|
||||
|
||||
std::optional<std::string> DebugProxy::read(std::size_t len, FfiError& err) {
|
||||
char* resp_c = nullptr;
|
||||
if (IdeviceFfiError* e = ::debug_proxy_read(handle_, len, &resp_c)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
return take_cstring(resp_c);
|
||||
Result<Option<std::string>, FfiError> DebugProxy::read(std::size_t len) {
|
||||
char *resp_c = nullptr;
|
||||
FfiError e(::debug_proxy_read(handle_, len, &resp_c));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return Ok(take_cstring(resp_c));
|
||||
}
|
||||
|
||||
std::optional<std::string> DebugProxy::set_argv(const std::vector<std::string>& argv,
|
||||
FfiError& err) {
|
||||
std::vector<const char*> c_argv;
|
||||
c_argv.reserve(argv.size());
|
||||
for (auto& a : argv)
|
||||
c_argv.push_back(a.c_str());
|
||||
Result<Option<std::string>, FfiError>
|
||||
DebugProxy::set_argv(const std::vector<std::string> &argv) {
|
||||
std::vector<const char *> c_argv;
|
||||
c_argv.reserve(argv.size());
|
||||
for (auto &a : argv)
|
||||
c_argv.push_back(a.c_str());
|
||||
|
||||
char* resp_c = nullptr;
|
||||
if (IdeviceFfiError* e = ::debug_proxy_set_argv(
|
||||
handle_,
|
||||
c_argv.empty() ? nullptr : const_cast<const char* const*>(c_argv.data()),
|
||||
c_argv.size(),
|
||||
&resp_c)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
return take_cstring(resp_c);
|
||||
char *resp_c = nullptr;
|
||||
FfiError e(::debug_proxy_set_argv(
|
||||
handle_,
|
||||
c_argv.empty() ? nullptr : const_cast<const char *const *>(c_argv.data()),
|
||||
c_argv.size(), &resp_c));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return Ok(take_cstring(resp_c));
|
||||
}
|
||||
|
||||
bool DebugProxy::send_ack(FfiError& err) {
|
||||
if (IdeviceFfiError* e = ::debug_proxy_send_ack(handle_)) {
|
||||
err = FfiError(e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
Result<void, FfiError> DebugProxy::send_ack() {
|
||||
FfiError e(::debug_proxy_send_ack(handle_));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return Ok();
|
||||
}
|
||||
|
||||
bool DebugProxy::send_nack(FfiError& err) {
|
||||
if (IdeviceFfiError* e = ::debug_proxy_send_nack(handle_)) {
|
||||
err = FfiError(e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
Result<void, FfiError> DebugProxy::send_nack() {
|
||||
FfiError e(::debug_proxy_send_nack(handle_));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return Ok();
|
||||
}
|
||||
|
||||
} // namespace IdeviceFFI
|
||||
|
||||
@@ -1,35 +1,39 @@
|
||||
// Jackson Coxson
|
||||
|
||||
#include <idevice++/diagnosticsservice.hpp>
|
||||
#include <cstring>
|
||||
#include <idevice++/diagnosticsservice.hpp>
|
||||
#include <idevice++/option.hpp>
|
||||
|
||||
namespace IdeviceFFI {
|
||||
|
||||
// Local helper: take ownership of a C string and convert to std::string
|
||||
static std::optional<std::string> take_cstring(char* p) {
|
||||
if (!p)
|
||||
return std::nullopt;
|
||||
static Option<std::string> take_cstring(char* p) {
|
||||
if (!p) {
|
||||
return None;
|
||||
}
|
||||
|
||||
std::string s(p);
|
||||
::idevice_string_free(p);
|
||||
return s;
|
||||
return Some(std::move(s));
|
||||
}
|
||||
|
||||
// -------- SysdiagnoseStream --------
|
||||
std::optional<std::vector<uint8_t>> SysdiagnoseStream::next_chunk(FfiError& err) {
|
||||
if (!h_)
|
||||
return std::nullopt;
|
||||
Result<Option<std::vector<uint8_t>>, FfiError> SysdiagnoseStream::next_chunk() {
|
||||
if (!h_) {
|
||||
return Err(FfiError::NotConnected());
|
||||
}
|
||||
|
||||
uint8_t* data = nullptr;
|
||||
std::size_t len = 0;
|
||||
|
||||
if (IdeviceFfiError* e = ::sysdiagnose_stream_next(h_, &data, &len)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(::sysdiagnose_stream_next(h_, &data, &len));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
if (!data || len == 0) {
|
||||
// End of stream
|
||||
return std::nullopt;
|
||||
return Ok(Option<std::vector<uint8_t>>(None));
|
||||
}
|
||||
|
||||
// Copy into a C++ buffer
|
||||
@@ -38,52 +42,52 @@ std::optional<std::vector<uint8_t>> SysdiagnoseStream::next_chunk(FfiError& err)
|
||||
|
||||
idevice_data_free(data, len);
|
||||
|
||||
return out;
|
||||
return Ok(Some(out));
|
||||
}
|
||||
|
||||
// -------- DiagnosticsService --------
|
||||
std::optional<DiagnosticsService>
|
||||
DiagnosticsService::connect_rsd(Adapter& adapter, RsdHandshake& rsd, FfiError& err) {
|
||||
Result<DiagnosticsService, FfiError> DiagnosticsService::connect_rsd(Adapter& adapter,
|
||||
RsdHandshake& rsd) {
|
||||
::DiagnosticsServiceHandle* out = nullptr;
|
||||
if (IdeviceFfiError* e = ::diagnostics_service_connect_rsd(adapter.raw(), rsd.raw(), &out)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(::diagnostics_service_connect_rsd(adapter.raw(), rsd.raw(), &out));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return DiagnosticsService(out);
|
||||
return Ok(DiagnosticsService(out));
|
||||
}
|
||||
|
||||
std::optional<DiagnosticsService> DiagnosticsService::from_stream_ptr(::ReadWriteOpaque* consumed,
|
||||
FfiError& err) {
|
||||
Result<DiagnosticsService, FfiError>
|
||||
DiagnosticsService::from_stream_ptr(::ReadWriteOpaque* consumed) {
|
||||
::DiagnosticsServiceHandle* out = nullptr;
|
||||
if (IdeviceFfiError* e = ::diagnostics_service_new(consumed, &out)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(::diagnostics_service_new(consumed, &out));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return DiagnosticsService(out);
|
||||
return Ok(DiagnosticsService(out));
|
||||
}
|
||||
|
||||
std::optional<SysdiagnoseCapture> DiagnosticsService::capture_sysdiagnose(bool dry_run,
|
||||
FfiError& err) {
|
||||
if (!h_)
|
||||
return std::nullopt;
|
||||
Result<SysdiagnoseCapture, FfiError> DiagnosticsService::capture_sysdiagnose(bool dry_run) {
|
||||
if (!h_) {
|
||||
return Err(FfiError::NotConnected());
|
||||
}
|
||||
|
||||
char* filename_c = nullptr;
|
||||
std::size_t expected_len = 0;
|
||||
::SysdiagnoseStreamHandle* stream_h = nullptr;
|
||||
|
||||
if (IdeviceFfiError* e = ::diagnostics_service_capture_sysdiagnose(
|
||||
h_, dry_run ? true : false, &filename_c, &expected_len, &stream_h)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(::diagnostics_service_capture_sysdiagnose(
|
||||
h_, dry_run ? true : false, &filename_c, &expected_len, &stream_h));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
auto fname = take_cstring(filename_c).value_or(std::string{});
|
||||
auto fname = take_cstring(filename_c).unwrap_or(std::string{});
|
||||
SysdiagnoseStream stream(stream_h);
|
||||
|
||||
SysdiagnoseCapture cap{/*preferred_filename*/ std::move(fname),
|
||||
/*expected_length*/ expected_len,
|
||||
/*stream*/ std::move(stream)};
|
||||
return cap;
|
||||
return Ok(std::move(cap));
|
||||
}
|
||||
|
||||
} // namespace IdeviceFFI
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <idevice++/bindings.hpp>
|
||||
#include <idevice++/ffi.hpp>
|
||||
#include <idevice.h>
|
||||
#include <string>
|
||||
|
||||
namespace IdeviceFFI {
|
||||
@@ -14,4 +15,18 @@ FfiError::FfiError(const IdeviceFfiError* err)
|
||||
|
||||
FfiError::FfiError() : code(0), message("") {
|
||||
}
|
||||
|
||||
FfiError FfiError::NotConnected() {
|
||||
FfiError err;
|
||||
err.code = -11; // from idevice/lib.rs
|
||||
err.message = "No established socket connection";
|
||||
return err;
|
||||
}
|
||||
FfiError FfiError::InvalidArgument() {
|
||||
FfiError err;
|
||||
err.code = -57; // from idevice/lib.rs
|
||||
err.message = "No established socket connection";
|
||||
return err;
|
||||
}
|
||||
|
||||
} // namespace IdeviceFFI
|
||||
|
||||
@@ -4,53 +4,50 @@
|
||||
|
||||
namespace IdeviceFFI {
|
||||
|
||||
std::optional<Idevice>
|
||||
Idevice::create(IdeviceSocketHandle* socket, const std::string& label, FfiError& err) {
|
||||
Result<Idevice, FfiError> Idevice::create(IdeviceSocketHandle* socket, const std::string& label) {
|
||||
IdeviceHandle* h = nullptr;
|
||||
if (IdeviceFfiError* e = idevice_new(socket, label.c_str(), &h)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(idevice_new(socket, label.c_str(), &h));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return Idevice(h);
|
||||
return Ok(Idevice(h));
|
||||
}
|
||||
|
||||
std::optional<Idevice> Idevice::create_tcp(const sockaddr* addr,
|
||||
socklen_t addr_len,
|
||||
const std::string& label,
|
||||
FfiError& err) {
|
||||
Result<Idevice, FfiError>
|
||||
Idevice::create_tcp(const sockaddr* addr, socklen_t addr_len, const std::string& label) {
|
||||
IdeviceHandle* h = nullptr;
|
||||
if (IdeviceFfiError* e = idevice_new_tcp_socket(addr, addr_len, label.c_str(), &h)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(idevice_new_tcp_socket(addr, addr_len, label.c_str(), &h));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return Idevice(h);
|
||||
return Ok(Idevice(h));
|
||||
}
|
||||
|
||||
std::optional<std::string> Idevice::get_type(FfiError& err) const {
|
||||
char* cstr = nullptr;
|
||||
if (IdeviceFfiError* e = idevice_get_type(handle_.get(), &cstr)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
Result<std::string, FfiError> Idevice::get_type() const {
|
||||
char* cstr = nullptr;
|
||||
FfiError e(idevice_get_type(handle_.get(), &cstr));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
std::string out(cstr);
|
||||
idevice_string_free(cstr);
|
||||
return out;
|
||||
return Ok(out);
|
||||
}
|
||||
|
||||
bool Idevice::rsd_checkin(FfiError& err) {
|
||||
if (IdeviceFfiError* e = idevice_rsd_checkin(handle_.get())) {
|
||||
err = FfiError(e);
|
||||
return false;
|
||||
Result<void, FfiError> Idevice::rsd_checkin() {
|
||||
FfiError e(idevice_rsd_checkin(handle_.get()));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
bool Idevice::start_session(const PairingFile& pairing_file, FfiError& err) {
|
||||
if (IdeviceFfiError* e = idevice_start_session(handle_.get(), pairing_file.raw())) {
|
||||
err = FfiError(e);
|
||||
return false;
|
||||
Result<void, FfiError> Idevice::start_session(const PairingFile& pairing_file) {
|
||||
FfiError e(idevice_start_session(handle_.get(), pairing_file.raw()));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
} // namespace IdeviceFFI
|
||||
|
||||
@@ -4,29 +4,29 @@
|
||||
|
||||
namespace IdeviceFFI {
|
||||
|
||||
std::optional<LocationSimulation> LocationSimulation::create(RemoteServer& server, FfiError& err) {
|
||||
Result<LocationSimulation, FfiError> LocationSimulation::create(RemoteServer& server) {
|
||||
LocationSimulationHandle* out = nullptr;
|
||||
if (IdeviceFfiError* e = ::location_simulation_new(server.raw(), &out)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(::location_simulation_new(server.raw(), &out));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return LocationSimulation::adopt(out);
|
||||
return Ok(LocationSimulation::adopt(out));
|
||||
}
|
||||
|
||||
bool LocationSimulation::clear(FfiError& err) {
|
||||
if (IdeviceFfiError* e = ::location_simulation_clear(handle_.get())) {
|
||||
err = FfiError(e);
|
||||
return false;
|
||||
Result<void, FfiError> LocationSimulation::clear() {
|
||||
FfiError e(::location_simulation_clear(handle_.get()));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
bool LocationSimulation::set(double latitude, double longitude, FfiError& err) {
|
||||
if (IdeviceFfiError* e = ::location_simulation_set(handle_.get(), latitude, longitude)) {
|
||||
err = FfiError(e);
|
||||
return false;
|
||||
Result<void, FfiError> LocationSimulation::set(double latitude, double longitude) {
|
||||
FfiError e(::location_simulation_set(handle_.get(), latitude, longitude));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
} // namespace IdeviceFFI
|
||||
|
||||
@@ -7,60 +7,51 @@
|
||||
|
||||
namespace IdeviceFFI {
|
||||
|
||||
std::optional<Lockdown> Lockdown::connect(Provider& provider, FfiError& err) {
|
||||
Result<Lockdown, FfiError> Lockdown::connect(Provider& provider) {
|
||||
LockdowndClientHandle* out = nullptr;
|
||||
|
||||
if (IdeviceFfiError* e = ::lockdownd_connect(provider.raw(), &out)) {
|
||||
// Rust freed the provider on error -> abandon our ownership to avoid double free.
|
||||
FfiError e(::lockdownd_connect(provider.raw(), &out));
|
||||
if (e) {
|
||||
provider.release();
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
return Err(e);
|
||||
}
|
||||
// Success: provider is NOT consumed; keep ownership.
|
||||
return Lockdown::adopt(out);
|
||||
return Ok(Lockdown::adopt(out));
|
||||
}
|
||||
|
||||
std::optional<Lockdown> Lockdown::from_socket(Idevice&& socket, FfiError& err) {
|
||||
Result<Lockdown, FfiError> Lockdown::from_socket(Idevice&& socket) {
|
||||
LockdowndClientHandle* out = nullptr;
|
||||
|
||||
if (IdeviceFfiError* e = ::lockdownd_new(socket.raw(), &out)) {
|
||||
// Error: Rust did NOT consume the socket (it returns early for invalid args),
|
||||
// so keep ownership; report error.
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(::lockdownd_new(socket.raw(), &out));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
// Success: Rust consumed the socket -> abandon our ownership.
|
||||
socket.release();
|
||||
return Lockdown::adopt(out);
|
||||
return Ok(Lockdown::adopt(out));
|
||||
}
|
||||
|
||||
bool Lockdown::start_session(const PairingFile& pf, FfiError& err) {
|
||||
if (IdeviceFfiError* e = ::lockdownd_start_session(handle_.get(), pf.raw())) {
|
||||
err = FfiError(e);
|
||||
return false;
|
||||
Result<void, FfiError> Lockdown::start_session(const PairingFile& pf) {
|
||||
FfiError e(::lockdownd_start_session(handle_.get(), pf.raw()));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
std::optional<std::pair<uint16_t, bool>> Lockdown::start_service(const std::string& identifier,
|
||||
FfiError& err) {
|
||||
Result<std::pair<uint16_t, bool>, FfiError> Lockdown::start_service(const std::string& identifier) {
|
||||
uint16_t port = 0;
|
||||
bool ssl = false;
|
||||
if (IdeviceFfiError* e =
|
||||
::lockdownd_start_service(handle_.get(), identifier.c_str(), &port, &ssl)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(::lockdownd_start_service(handle_.get(), identifier.c_str(), &port, &ssl));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return std::make_pair(port, ssl);
|
||||
return Ok(std::make_pair(port, ssl));
|
||||
}
|
||||
|
||||
std::optional<plist_t> Lockdown::get_value(const char* key, const char* domain, FfiError& err) {
|
||||
plist_t out = nullptr;
|
||||
if (IdeviceFfiError* e = ::lockdownd_get_value(handle_.get(), key, domain, &out)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
Result<plist_t, FfiError> Lockdown::get_value(const char* key, const char* domain) {
|
||||
plist_t out = nullptr;
|
||||
FfiError e(::lockdownd_get_value(handle_.get(), key, domain, &out));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return out; // caller now owns `out` and must free with the plist API
|
||||
return Ok(out);
|
||||
}
|
||||
|
||||
} // namespace IdeviceFFI
|
||||
|
||||
@@ -8,46 +8,46 @@ namespace IdeviceFFI {
|
||||
|
||||
// Deleter definition (out-of-line)
|
||||
void PairingFileDeleter::operator()(IdevicePairingFile* p) const noexcept {
|
||||
if (p)
|
||||
if (p) {
|
||||
idevice_pairing_file_free(p);
|
||||
}
|
||||
}
|
||||
|
||||
// Static member definitions
|
||||
std::optional<PairingFile> PairingFile::read(const std::string& path, FfiError& err) {
|
||||
Result<PairingFile, FfiError> PairingFile::read(const std::string& path) {
|
||||
IdevicePairingFile* ptr = nullptr;
|
||||
if (IdeviceFfiError* e = idevice_pairing_file_read(path.c_str(), &ptr)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(idevice_pairing_file_read(path.c_str(), &ptr));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return PairingFile(ptr);
|
||||
return Ok(PairingFile(ptr));
|
||||
}
|
||||
|
||||
std::optional<PairingFile>
|
||||
PairingFile::from_bytes(const uint8_t* data, size_t size, FfiError& err) {
|
||||
Result<PairingFile, FfiError> PairingFile::from_bytes(const uint8_t* data, size_t size) {
|
||||
IdevicePairingFile* raw = nullptr;
|
||||
if (IdeviceFfiError* e = idevice_pairing_file_from_bytes(data, size, &raw)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(idevice_pairing_file_from_bytes(data, size, &raw));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return PairingFile(raw);
|
||||
return Ok(PairingFile(raw));
|
||||
}
|
||||
|
||||
std::optional<std::vector<uint8_t>> PairingFile::serialize(FfiError& err) const {
|
||||
Result<std::vector<uint8_t>, FfiError> PairingFile::serialize() const {
|
||||
if (!ptr_) {
|
||||
return std::nullopt;
|
||||
return Err(FfiError::InvalidArgument());
|
||||
}
|
||||
|
||||
uint8_t* data = nullptr;
|
||||
size_t size = 0;
|
||||
|
||||
if (IdeviceFfiError* e = idevice_pairing_file_serialize(ptr_.get(), &data, &size)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(idevice_pairing_file_serialize(ptr_.get(), &data, &size));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
std::vector<uint8_t> out(data, data + size);
|
||||
idevice_data_free(data, size);
|
||||
return out;
|
||||
return Ok(out);
|
||||
}
|
||||
|
||||
} // namespace IdeviceFFI
|
||||
|
||||
@@ -6,58 +6,53 @@
|
||||
|
||||
namespace IdeviceFFI {
|
||||
|
||||
std::optional<Provider> Provider::tcp_new(const idevice_sockaddr* ip,
|
||||
PairingFile&& pairing,
|
||||
const std::string& label,
|
||||
FfiError& err) {
|
||||
Result<Provider, FfiError>
|
||||
Provider::tcp_new(const idevice_sockaddr* ip, PairingFile&& pairing, const std::string& label) {
|
||||
IdeviceProviderHandle* out = nullptr;
|
||||
|
||||
// Call with exact types; do NOT cast to void*
|
||||
if (IdeviceFfiError* e = idevice_tcp_provider_new(
|
||||
ip, static_cast<IdevicePairingFile*>(pairing.raw()), label.c_str(), &out)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(idevice_tcp_provider_new(
|
||||
ip, static_cast<IdevicePairingFile*>(pairing.raw()), label.c_str(), &out));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
// Success: Rust consumed the pairing file -> abandon our ownership
|
||||
pairing.release(); // implement as: ptr_.release() in PairingFile
|
||||
pairing.release();
|
||||
|
||||
return Provider::adopt(out);
|
||||
return Ok(Provider::adopt(out));
|
||||
}
|
||||
|
||||
std::optional<Provider> Provider::usbmuxd_new(UsbmuxdAddr&& addr,
|
||||
uint32_t tag,
|
||||
const std::string& udid,
|
||||
uint32_t device_id,
|
||||
const std::string& label,
|
||||
FfiError& err) {
|
||||
Result<Provider, FfiError> Provider::usbmuxd_new(UsbmuxdAddr&& addr,
|
||||
uint32_t tag,
|
||||
const std::string& udid,
|
||||
uint32_t device_id,
|
||||
const std::string& label) {
|
||||
IdeviceProviderHandle* out = nullptr;
|
||||
|
||||
if (IdeviceFfiError* e = usbmuxd_provider_new(static_cast<UsbmuxdAddrHandle*>(addr.raw()),
|
||||
tag,
|
||||
udid.c_str(),
|
||||
device_id,
|
||||
label.c_str(),
|
||||
&out)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(usbmuxd_provider_new(static_cast<UsbmuxdAddrHandle*>(addr.raw()),
|
||||
tag,
|
||||
udid.c_str(),
|
||||
device_id,
|
||||
label.c_str(),
|
||||
&out));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
// Success: Rust consumed the addr -> abandon our ownership
|
||||
addr.release(); // implement as: ptr_.release() in UsbmuxdAddr
|
||||
|
||||
return Provider::adopt(out);
|
||||
addr.release();
|
||||
return Ok(Provider::adopt(out));
|
||||
}
|
||||
|
||||
std::optional<PairingFile> Provider::get_pairing_file(FfiError& err) {
|
||||
Result<PairingFile, FfiError> Provider::get_pairing_file() {
|
||||
|
||||
IdevicePairingFile* out = nullptr;
|
||||
if (IdeviceFfiError* e = idevice_provider_get_pairing_file(handle_.get(), &out)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(idevice_provider_get_pairing_file(handle_.get(), &out));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
return PairingFile(out);
|
||||
|
||||
return Ok(PairingFile(out));
|
||||
}
|
||||
|
||||
} // namespace IdeviceFFI
|
||||
|
||||
@@ -4,27 +4,26 @@
|
||||
|
||||
namespace IdeviceFFI {
|
||||
|
||||
std::optional<RemoteServer> RemoteServer::from_socket(ReadWrite&& rw, FfiError& err) {
|
||||
Result<RemoteServer, FfiError> RemoteServer::from_socket(ReadWrite&& rw) {
|
||||
RemoteServerHandle* out = nullptr;
|
||||
|
||||
// Rust consumes the stream regardless of result, release BEFORE the call
|
||||
ReadWriteOpaque* raw = rw.release();
|
||||
|
||||
if (IdeviceFfiError* e = ::remote_server_new(raw, &out)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(::remote_server_new(raw, &out));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return RemoteServer::adopt(out);
|
||||
return Ok(RemoteServer::adopt(out));
|
||||
}
|
||||
|
||||
std::optional<RemoteServer>
|
||||
RemoteServer::connect_rsd(Adapter& adapter, RsdHandshake& rsd, FfiError& err) {
|
||||
Result<RemoteServer, FfiError> RemoteServer::connect_rsd(Adapter& adapter, RsdHandshake& rsd) {
|
||||
RemoteServerHandle* out = nullptr;
|
||||
if (IdeviceFfiError* e = ::remote_server_connect_rsd(adapter.raw(), rsd.raw(), &out)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(::remote_server_connect_rsd(adapter.raw(), rsd.raw(), &out));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return RemoteServer::adopt(out);
|
||||
return Ok(RemoteServer::adopt(out));
|
||||
}
|
||||
|
||||
} // namespace IdeviceFFI
|
||||
|
||||
@@ -7,10 +7,12 @@ namespace IdeviceFFI {
|
||||
// ---------- helpers to copy/free CRsdService ----------
|
||||
static RsdService to_cpp_and_free(CRsdService* c) {
|
||||
RsdService s;
|
||||
if (c->name)
|
||||
if (c->name) {
|
||||
s.name = c->name;
|
||||
if (c->entitlement)
|
||||
}
|
||||
if (c->entitlement) {
|
||||
s.entitlement = c->entitlement;
|
||||
}
|
||||
s.port = c->port;
|
||||
s.uses_remote_xpc = c->uses_remote_xpc;
|
||||
s.service_version = c->service_version;
|
||||
@@ -20,8 +22,9 @@ static RsdService to_cpp_and_free(CRsdService* c) {
|
||||
auto** arr = c->features;
|
||||
s.features.reserve(c->features_count);
|
||||
for (size_t i = 0; i < c->features_count; ++i) {
|
||||
if (arr[i])
|
||||
if (arr[i]) {
|
||||
s.features.emplace_back(arr[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,8 +36,9 @@ static RsdService to_cpp_and_free(CRsdService* c) {
|
||||
static std::vector<RsdService> to_cpp_and_free(CRsdServiceArray* arr) {
|
||||
std::vector<RsdService> out;
|
||||
if (!arr || !arr->services || arr->count == 0) {
|
||||
if (arr)
|
||||
if (arr) {
|
||||
rsd_free_services(arr);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
out.reserve(arr->count);
|
||||
@@ -51,8 +55,9 @@ static std::vector<RsdService> to_cpp_and_free(CRsdServiceArray* arr) {
|
||||
auto** feats = begin[i].features;
|
||||
out.back().features.reserve(begin[i].features_count);
|
||||
for (size_t j = 0; j < begin[i].features_count; ++j) {
|
||||
if (feats[j])
|
||||
if (feats[j]) {
|
||||
out.back().features.emplace_back(feats[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,68 +85,67 @@ RsdHandshake& RsdHandshake::operator=(const RsdHandshake& other) {
|
||||
}
|
||||
|
||||
// ---------- factory ----------
|
||||
std::optional<RsdHandshake> RsdHandshake::from_socket(ReadWrite&& rw, FfiError& err) {
|
||||
Result<RsdHandshake, FfiError> RsdHandshake::from_socket(ReadWrite&& rw) {
|
||||
RsdHandshakeHandle* out = nullptr;
|
||||
|
||||
// Rust consumes the socket regardless of result ⇒ release BEFORE call.
|
||||
ReadWriteOpaque* raw = rw.release();
|
||||
|
||||
if (IdeviceFfiError* e = rsd_handshake_new(raw, &out)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(rsd_handshake_new(raw, &out));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return RsdHandshake::adopt(out);
|
||||
return Ok(RsdHandshake::adopt(out));
|
||||
}
|
||||
|
||||
// ---------- queries ----------
|
||||
std::optional<size_t> RsdHandshake::protocol_version(FfiError& err) const {
|
||||
size_t v = 0;
|
||||
if (IdeviceFfiError* e = rsd_get_protocol_version(handle_.get(), &v)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
Result<size_t, FfiError> RsdHandshake::protocol_version() const {
|
||||
size_t v = 0;
|
||||
FfiError e(rsd_get_protocol_version(handle_.get(), &v));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return v;
|
||||
return Ok(v);
|
||||
}
|
||||
|
||||
std::optional<std::string> RsdHandshake::uuid(FfiError& err) const {
|
||||
char* c = nullptr;
|
||||
if (IdeviceFfiError* e = rsd_get_uuid(handle_.get(), &c)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
Result<std::string, FfiError> RsdHandshake::uuid() const {
|
||||
char* c = nullptr;
|
||||
FfiError e(rsd_get_uuid(handle_.get(), &c));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
std::string out;
|
||||
if (c) {
|
||||
out = c;
|
||||
rsd_free_string(c);
|
||||
}
|
||||
return out;
|
||||
return Ok(out);
|
||||
}
|
||||
|
||||
std::optional<std::vector<RsdService>> RsdHandshake::services(FfiError& err) const {
|
||||
Result<std::vector<RsdService>, FfiError> RsdHandshake::services() const {
|
||||
CRsdServiceArray* arr = nullptr;
|
||||
if (IdeviceFfiError* e = rsd_get_services(handle_.get(), &arr)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(rsd_get_services(handle_.get(), &arr));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return to_cpp_and_free(arr);
|
||||
return Ok(to_cpp_and_free(arr));
|
||||
}
|
||||
|
||||
std::optional<bool> RsdHandshake::service_available(const std::string& name, FfiError& err) const {
|
||||
bool avail = false;
|
||||
if (IdeviceFfiError* e = rsd_service_available(handle_.get(), name.c_str(), &avail)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
Result<bool, FfiError> RsdHandshake::service_available(const std::string& name) const {
|
||||
bool avail = false;
|
||||
FfiError e(rsd_service_available(handle_.get(), name.c_str(), &avail));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return avail;
|
||||
return Ok(avail);
|
||||
}
|
||||
|
||||
std::optional<RsdService> RsdHandshake::service_info(const std::string& name, FfiError& err) const {
|
||||
Result<RsdService, FfiError> RsdHandshake::service_info(const std::string& name) const {
|
||||
CRsdService* svc = nullptr;
|
||||
if (IdeviceFfiError* e = rsd_get_service_info(handle_.get(), name.c_str(), &svc)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(rsd_get_service_info(handle_.get(), name.c_str(), &svc));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return to_cpp_and_free(svc);
|
||||
return Ok(to_cpp_and_free(svc));
|
||||
}
|
||||
|
||||
} // namespace IdeviceFFI
|
||||
|
||||
@@ -28,16 +28,16 @@ bool TcpObjectStackEater::read(OwnedBuffer& out, FfiError& err) const {
|
||||
}
|
||||
|
||||
// ---------- TcpStackFromCallback ----------
|
||||
std::optional<TcpObjectStack>
|
||||
TcpObjectStack::create(const std::string& our_ip, const std::string& their_ip, FfiError& err) {
|
||||
Result<TcpObjectStack, FfiError> TcpObjectStack::create(const std::string& our_ip,
|
||||
const std::string& their_ip) {
|
||||
::TcpFeedObject* feeder_h = nullptr;
|
||||
::TcpEatObject* eater_h = nullptr;
|
||||
::AdapterHandle* adapter_h = nullptr;
|
||||
|
||||
if (IdeviceFfiError* e = ::idevice_tcp_stack_into_sync_objects(
|
||||
our_ip.c_str(), their_ip.c_str(), &feeder_h, &eater_h, &adapter_h)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(::idevice_tcp_stack_into_sync_objects(
|
||||
our_ip.c_str(), their_ip.c_str(), &feeder_h, &eater_h, &adapter_h));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
auto impl = std::make_unique<Impl>();
|
||||
@@ -47,7 +47,7 @@ TcpObjectStack::create(const std::string& our_ip, const std::string& their_ip, F
|
||||
|
||||
TcpObjectStack out;
|
||||
out.impl_ = std::move(impl);
|
||||
return out;
|
||||
return Ok(std::move(out));
|
||||
}
|
||||
|
||||
TcpObjectStackFeeder& TcpObjectStack::feeder() {
|
||||
@@ -65,49 +65,54 @@ const TcpObjectStackEater& TcpObjectStack::eater() const {
|
||||
}
|
||||
|
||||
Adapter& TcpObjectStack::adapter() {
|
||||
if (!impl_ || !impl_->adapter) {
|
||||
if (!impl_ || impl_->adapter.is_some()) {
|
||||
static Adapter* never = nullptr;
|
||||
return *never;
|
||||
}
|
||||
return *(impl_->adapter);
|
||||
return (impl_->adapter.unwrap());
|
||||
}
|
||||
const Adapter& TcpObjectStack::adapter() const {
|
||||
if (!impl_ || !impl_->adapter) {
|
||||
if (!impl_ || impl_->adapter.is_none()) {
|
||||
static Adapter* never = nullptr;
|
||||
return *never;
|
||||
}
|
||||
return *(impl_->adapter);
|
||||
return (impl_->adapter.unwrap());
|
||||
}
|
||||
|
||||
// ---------- Release APIs ----------
|
||||
std::optional<TcpObjectStackFeeder> TcpObjectStack::release_feeder() {
|
||||
if (!impl_)
|
||||
return std::nullopt;
|
||||
Option<TcpObjectStackFeeder> TcpObjectStack::release_feeder() {
|
||||
if (!impl_) {
|
||||
return None;
|
||||
}
|
||||
auto has = impl_->feeder.raw() != nullptr;
|
||||
if (!has)
|
||||
return std::nullopt;
|
||||
if (!has) {
|
||||
return None;
|
||||
}
|
||||
TcpObjectStackFeeder out = std::move(impl_->feeder);
|
||||
// impl_->feeder is now empty (h_ == nullptr) thanks to move
|
||||
return std::optional<TcpObjectStackFeeder>(std::move(out));
|
||||
return Some(std::move(out));
|
||||
}
|
||||
|
||||
std::optional<TcpObjectStackEater> TcpObjectStack::release_eater() {
|
||||
if (!impl_)
|
||||
return std::nullopt;
|
||||
Option<TcpObjectStackEater> TcpObjectStack::release_eater() {
|
||||
if (!impl_) {
|
||||
return None;
|
||||
}
|
||||
auto has = impl_->eater.raw() != nullptr;
|
||||
if (!has)
|
||||
return std::nullopt;
|
||||
if (!has) {
|
||||
return None;
|
||||
}
|
||||
TcpObjectStackEater out = std::move(impl_->eater);
|
||||
return std::optional<TcpObjectStackEater>(std::move(out));
|
||||
return Some(std::move(out));
|
||||
}
|
||||
|
||||
std::optional<Adapter> TcpObjectStack::release_adapter() {
|
||||
if (!impl_ || !impl_->adapter)
|
||||
return std::nullopt;
|
||||
Option<Adapter> TcpObjectStack::release_adapter() {
|
||||
if (!impl_ || impl_->adapter.is_none()) {
|
||||
return None;
|
||||
}
|
||||
// Move out and clear our optional
|
||||
auto out = std::move(*(impl_->adapter));
|
||||
auto out = std::move((impl_->adapter.unwrap()));
|
||||
impl_->adapter.reset();
|
||||
return std::optional<Adapter>(std::move(out));
|
||||
return Some(std::move(out));
|
||||
}
|
||||
|
||||
} // namespace IdeviceFFI
|
||||
|
||||
@@ -6,24 +6,23 @@
|
||||
namespace IdeviceFFI {
|
||||
|
||||
// ---------- UsbmuxdAddr ----------
|
||||
std::optional<UsbmuxdAddr>
|
||||
UsbmuxdAddr::tcp_new(const sockaddr* addr, socklen_t addr_len, FfiError& err) {
|
||||
Result<UsbmuxdAddr, FfiError> UsbmuxdAddr::tcp_new(const sockaddr* addr, socklen_t addr_len) {
|
||||
UsbmuxdAddrHandle* h = nullptr;
|
||||
if (IdeviceFfiError* e = idevice_usbmuxd_tcp_addr_new(addr, addr_len, &h)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(idevice_usbmuxd_tcp_addr_new(addr, addr_len, &h));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return UsbmuxdAddr(h);
|
||||
return Ok(UsbmuxdAddr(h));
|
||||
}
|
||||
|
||||
#if defined(__unix__) || defined(__APPLE__)
|
||||
std::optional<UsbmuxdAddr> UsbmuxdAddr::unix_new(const std::string& path, FfiError& err) {
|
||||
Result<UsbmuxdAddr, FfiError> UsbmuxdAddr::unix_new(const std::string& path) {
|
||||
UsbmuxdAddrHandle* h = nullptr;
|
||||
if (IdeviceFfiError* e = idevice_usbmuxd_unix_addr_new(path.c_str(), &h)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(idevice_usbmuxd_unix_addr_new(path.c_str(), &h));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return UsbmuxdAddr(h);
|
||||
return Ok(UsbmuxdAddr(h));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -48,114 +47,109 @@ std::string UsbmuxdConnectionType::to_string() const {
|
||||
}
|
||||
|
||||
// ---------- UsbmuxdDevice ----------
|
||||
std::optional<std::string> UsbmuxdDevice::get_udid() const {
|
||||
Option<std::string> UsbmuxdDevice::get_udid() const {
|
||||
char* c = idevice_usbmuxd_device_get_udid(handle_.get());
|
||||
if (!c)
|
||||
return std::nullopt;
|
||||
if (!c) {
|
||||
return None;
|
||||
}
|
||||
std::string out(c);
|
||||
idevice_string_free(c);
|
||||
return out;
|
||||
return Some(out);
|
||||
}
|
||||
|
||||
std::optional<uint32_t> UsbmuxdDevice::get_id() const {
|
||||
Option<uint32_t> UsbmuxdDevice::get_id() const {
|
||||
uint32_t id = idevice_usbmuxd_device_get_device_id(handle_.get());
|
||||
if (id == 0)
|
||||
return std::nullopt; // adjust if 0 can be valid
|
||||
return id;
|
||||
if (id == 0) {
|
||||
return None;
|
||||
}
|
||||
return Some(id);
|
||||
}
|
||||
|
||||
std::optional<UsbmuxdConnectionType> UsbmuxdDevice::get_connection_type() const {
|
||||
Option<UsbmuxdConnectionType> UsbmuxdDevice::get_connection_type() const {
|
||||
uint8_t t = idevice_usbmuxd_device_get_connection_type(handle_.get());
|
||||
if (t == 0)
|
||||
return std::nullopt;
|
||||
return UsbmuxdConnectionType(t);
|
||||
if (t == 0) {
|
||||
return None;
|
||||
}
|
||||
return Some(UsbmuxdConnectionType(t));
|
||||
}
|
||||
|
||||
// ---------- UsbmuxdConnection ----------
|
||||
std::optional<UsbmuxdConnection> UsbmuxdConnection::tcp_new(const idevice_sockaddr* addr,
|
||||
idevice_socklen_t addr_len,
|
||||
uint32_t tag,
|
||||
FfiError& err) {
|
||||
Result<UsbmuxdConnection, FfiError>
|
||||
UsbmuxdConnection::tcp_new(const idevice_sockaddr* addr, idevice_socklen_t addr_len, uint32_t tag) {
|
||||
UsbmuxdConnectionHandle* h = nullptr;
|
||||
if (IdeviceFfiError* e = idevice_usbmuxd_new_tcp_connection(addr, addr_len, tag, &h)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(idevice_usbmuxd_new_tcp_connection(addr, addr_len, tag, &h));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return UsbmuxdConnection(h);
|
||||
return Ok(UsbmuxdConnection(h));
|
||||
}
|
||||
|
||||
#if defined(__unix__) || defined(__APPLE__)
|
||||
std::optional<UsbmuxdConnection>
|
||||
UsbmuxdConnection::unix_new(const std::string& path, uint32_t tag, FfiError& err) {
|
||||
Result<UsbmuxdConnection, FfiError> UsbmuxdConnection::unix_new(const std::string& path,
|
||||
uint32_t tag) {
|
||||
UsbmuxdConnectionHandle* h = nullptr;
|
||||
if (IdeviceFfiError* e = idevice_usbmuxd_new_unix_socket_connection(path.c_str(), tag, &h)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(idevice_usbmuxd_new_unix_socket_connection(path.c_str(), tag, &h));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return UsbmuxdConnection(h);
|
||||
return Ok(UsbmuxdConnection(h));
|
||||
}
|
||||
#endif
|
||||
|
||||
std::optional<UsbmuxdConnection> UsbmuxdConnection::default_new(uint32_t tag, FfiError& err) {
|
||||
Result<UsbmuxdConnection, FfiError> UsbmuxdConnection::default_new(uint32_t tag) {
|
||||
UsbmuxdConnectionHandle* h = nullptr;
|
||||
if (IdeviceFfiError* e = idevice_usbmuxd_new_default_connection(tag, &h)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(idevice_usbmuxd_new_default_connection(tag, &h));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return UsbmuxdConnection(h);
|
||||
return Ok(UsbmuxdConnection(h));
|
||||
}
|
||||
|
||||
std::optional<std::vector<UsbmuxdDevice>> UsbmuxdConnection::get_devices(FfiError& err) const {
|
||||
Result<std::vector<UsbmuxdDevice>, FfiError> UsbmuxdConnection::get_devices() const {
|
||||
UsbmuxdDeviceHandle** list = nullptr;
|
||||
int count = 0;
|
||||
if (IdeviceFfiError* e = idevice_usbmuxd_get_devices(handle_.get(), &list, &count)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(idevice_usbmuxd_get_devices(handle_.get(), &list, &count));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
std::vector<UsbmuxdDevice> out;
|
||||
out.reserve(count);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
out.emplace_back(UsbmuxdDevice::adopt(list[i]));
|
||||
}
|
||||
return out;
|
||||
return Ok(std::move(out));
|
||||
}
|
||||
|
||||
std::optional<std::string> UsbmuxdConnection::get_buid(FfiError& err) const {
|
||||
char* c = nullptr;
|
||||
if (IdeviceFfiError* e = idevice_usbmuxd_get_buid(handle_.get(), &c)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
Result<std::string, FfiError> UsbmuxdConnection::get_buid() const {
|
||||
char* c = nullptr;
|
||||
FfiError e(idevice_usbmuxd_get_buid(handle_.get(), &c));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
std::string out(c);
|
||||
idevice_string_free(c);
|
||||
return out;
|
||||
return Ok(out);
|
||||
}
|
||||
|
||||
std::optional<PairingFile> UsbmuxdConnection::get_pair_record(const std::string& udid,
|
||||
FfiError& err) {
|
||||
Result<PairingFile, FfiError> UsbmuxdConnection::get_pair_record(const std::string& udid) {
|
||||
IdevicePairingFile* pf = nullptr;
|
||||
if (IdeviceFfiError* e = idevice_usbmuxd_get_pair_record(handle_.get(), udid.c_str(), &pf)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
FfiError e(idevice_usbmuxd_get_pair_record(handle_.get(), udid.c_str(), &pf));
|
||||
if (e) {
|
||||
return Err(e);
|
||||
}
|
||||
return PairingFile(pf);
|
||||
return Ok(PairingFile(pf));
|
||||
}
|
||||
|
||||
std::optional<Idevice> UsbmuxdConnection::connect_to_device(uint32_t device_id,
|
||||
uint16_t port,
|
||||
const std::string& path,
|
||||
FfiError& err) && {
|
||||
Result<Idevice, FfiError> UsbmuxdConnection::connect_to_device(uint32_t device_id,
|
||||
uint16_t port,
|
||||
const std::string& path) && {
|
||||
UsbmuxdConnectionHandle* raw = handle_.release();
|
||||
|
||||
IdeviceHandle* out = nullptr;
|
||||
IdeviceFfiError* e =
|
||||
idevice_usbmuxd_connect_to_device(raw, device_id, port, path.c_str(), &out);
|
||||
|
||||
FfiError e(idevice_usbmuxd_connect_to_device(raw, device_id, port, path.c_str(), &out));
|
||||
if (e) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
return Err(e);
|
||||
}
|
||||
return Idevice::adopt(out);
|
||||
return Ok(Idevice::adopt(out));
|
||||
}
|
||||
|
||||
} // namespace IdeviceFFI
|
||||
|
||||
Reference in New Issue
Block a user