use cua_proto::env::v1 as pb;
use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq, Eq, uniffi::Record)]
pub struct SpacesdFeature {
pub name: String,
pub supported: bool,
pub limitation: Option<String>,
pub attributes: HashMap<String, String>,
}
#[derive(Debug, Clone, PartialEq, Eq, uniffi::Record)]
pub struct SpacesdCapabilities {
pub version: String,
pub protocol_version: u32,
pub protocol_revision: u32,
pub os_family: String,
pub os_name: String,
pub os_version: String,
pub arch: String,
pub hostname: String,
pub initialized: bool,
pub features: Vec<SpacesdFeature>,
pub json: String,
}
pub(crate) fn enum_suffix(debug: String) -> String {
debug.to_ascii_lowercase()
}
impl From<pb::GetCapabilitiesResponse> for SpacesdCapabilities {
fn from(c: pb::GetCapabilitiesResponse) -> Self {
let json = serde_json::to_string(&c).unwrap_or_default();
let os = c.os.clone().unwrap_or_default();
SpacesdCapabilities {
version: c.version.clone(),
protocol_version: c.protocol_version,
protocol_revision: c.protocol_revision,
os_family: enum_suffix(format!(
"{:?}",
pb::OsFamily::try_from(os.family).unwrap_or_default()
)),
os_name: os.name,
os_version: os.version,
arch: enum_suffix(format!(
"{:?}",
pb::Architecture::try_from(c.arch).unwrap_or_default()
)),
hostname: c.hostname.clone(),
initialized: c.initialized,
features: c
.features
.into_iter()
.map(|f| SpacesdFeature {
name: f.name,
supported: f.supported,
limitation: (!f.limitation.is_empty()).then_some(f.limitation),
attributes: f.attributes.into_iter().collect(),
})
.collect(),
json,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, uniffi::Record)]
pub struct PtySize {
pub cols: u32,
pub rows: u32,
}
#[derive(Debug, Clone, PartialEq, Eq, uniffi::Record)]
pub struct SpacesdCommand {
pub program: String,
#[uniffi(default = [])]
pub args: Vec<String>,
#[uniffi(default)]
pub env: HashMap<String, String>,
#[uniffi(default = None)]
pub cwd: Option<String>,
#[uniffi(default = None)]
pub user: Option<String>,
#[uniffi(default = None)]
pub timeout_ms: Option<u32>,
#[uniffi(default = None)]
pub tag: Option<String>,
#[uniffi(default = false)]
pub stdin: bool,
#[uniffi(default = None)]
pub pty: Option<PtySize>,
#[uniffi(default = false)]
pub kill_on_disconnect: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, uniffi::Record)]
pub struct ExitInfo {
pub code: Option<i32>,
pub signal: Option<String>,
pub timed_out: bool,
pub error: Option<String>,
pub success: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, uniffi::Record)]
pub struct ProcessOutput {
pub exit: ExitInfo,
pub stdout: Vec<u8>,
pub stderr: Vec<u8>,
pub pty: Vec<u8>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, uniffi::Enum)]
pub enum ProcessEventKind {
Stdout,
Stderr,
Pty,
Exit,
}
#[derive(Debug, Clone, PartialEq, Eq, uniffi::Record)]
pub struct ProcessEvent {
pub kind: ProcessEventKind,
pub offset: u64,
pub data: Vec<u8>,
pub exit: Option<ExitInfo>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, uniffi::Enum)]
pub enum ImageFormat {
Png,
Jpeg,
Webp,
}
impl ImageFormat {
pub(crate) fn to_pb(self) -> pb::ImageFormat {
match self {
ImageFormat::Png => pb::ImageFormat::Png,
ImageFormat::Jpeg => pb::ImageFormat::Jpeg,
ImageFormat::Webp => pb::ImageFormat::Webp,
}
}
pub(crate) fn from_pb(f: pb::ImageFormat) -> Self {
match f {
pb::ImageFormat::Jpeg => ImageFormat::Jpeg,
pb::ImageFormat::Webp => ImageFormat::Webp,
_ => ImageFormat::Png,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, uniffi::Record)]
pub struct ScreenshotOptions {
#[uniffi(default = None)]
pub display: Option<String>,
#[uniffi(default = None)]
pub format: Option<ImageFormat>,
#[uniffi(default = None)]
pub quality: Option<u32>,
#[uniffi(default = None)]
pub max_dimension: Option<u32>,
#[uniffi(default = false)]
pub include_cursor: bool,
}
#[derive(Debug, Clone, PartialEq, uniffi::Record)]
pub struct Screenshot {
pub image: Vec<u8>,
pub format: ImageFormat,
pub width: u32,
pub height: u32,
pub scale: f64,
pub screenshot_id: String,
}
#[derive(Debug, Clone, PartialEq, uniffi::Record)]
pub struct SpaceThumbnail {
pub image: Vec<u8>,
pub format: ImageFormat,
pub width: u32,
pub height: u32,
pub captured_at_ms: u64,
}
#[derive(Debug, Clone, Copy, PartialEq, uniffi::Record)]
pub struct Point {
pub x: f64,
pub y: f64,
}
#[derive(Debug, Clone, PartialEq, Eq, uniffi::Record)]
pub struct FileEntry {
pub name: String,
pub path: String,
pub kind: String,
pub size: u64,
pub mode: u32,
pub modified_ms: Option<i64>,
pub symlink_target: Option<String>,
}
impl From<pb::EntryInfo> for FileEntry {
fn from(e: pb::EntryInfo) -> Self {
let kind = match pb::FileType::try_from(e.r#type).unwrap_or_default() {
pb::FileType::File => "file",
pb::FileType::Directory => "directory",
pb::FileType::Symlink => "symlink",
_ => "other",
};
FileEntry {
name: e.name,
path: e.path,
kind: kind.into(),
size: e.size,
mode: e.mode,
modified_ms: e
.modified_at
.map(|t| t.seconds * 1000 + i64::from(t.nanos) / 1_000_000),
symlink_target: (!e.symlink_target.is_empty()).then_some(e.symlink_target),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, uniffi::Record)]
pub struct UploadOptions {
#[uniffi(default = false)]
pub create_new: bool,
#[uniffi(default = false)]
pub append: bool,
#[uniffi(default = 0)]
pub permissions: u32,
#[uniffi(default = true)]
pub create_parents: bool,
}
impl Default for UploadOptions {
fn default() -> Self {
UploadOptions {
create_new: false,
append: false,
permissions: 0,
create_parents: true,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, uniffi::Record)]
pub struct TransferResult {
pub size: u64,
pub sha256: String,
pub resumes: u32,
}
#[derive(Debug, Clone, PartialEq, Eq, uniffi::Record)]
pub struct MediaOpenOptions {
#[uniffi(default = None)]
pub display: Option<String>,
#[uniffi(default = None)]
pub window_handle: Option<String>,
#[uniffi(default = 0)]
pub max_fps: u32,
#[uniffi(default = 0)]
pub max_dimension: u32,
#[uniffi(default = false)]
pub audio: bool,
#[uniffi(default = false)]
pub disable_video: bool,
#[uniffi(default = None)]
pub request_json: Option<String>,
}