use crate::net::atp::protocol::PeerId;
use serde::{Deserialize, Serialize};
pub mod diagnostics;
pub mod object;
pub mod session;
pub mod stream;
pub mod transfer;
pub use diagnostics::*;
pub use object::*;
pub use session::*;
pub use stream::*;
pub use transfer::*;
#[derive(Debug, Clone)]
pub struct AtpSdk {
mode: SdkMode,
default_config: SessionConfig,
transfer_policy: TransferPolicy,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SdkMode {
InProcess,
DaemonDelegated {
daemon_endpoint: String,
auth_token: Option<String>,
},
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SessionConfig {
pub local_peer: PeerId,
pub session_timeout_ms: u64,
pub enable_compression: bool,
pub enable_repair: bool,
pub enable_resume: bool,
pub max_concurrent_transfers: u32,
pub stream_buffer_size: usize,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct TransferPolicy {
pub max_transfer_size_bytes: u64,
pub max_chunk_size_bytes: u32,
pub transfer_timeout_ms: u64,
pub enable_auto_retry: bool,
pub max_retry_attempts: u32,
pub retry_backoff_ms: u64,
pub progress_report_interval_ms: u64,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct TransferId(pub String);
impl TransferId {
#[must_use]
pub fn new(id: impl Into<String>) -> Self {
Self(id.into())
}
#[must_use]
pub fn generate() -> Self {
use std::sync::atomic::{AtomicU64, Ordering};
static COUNTER: AtomicU64 = AtomicU64::new(0);
let id = COUNTER.fetch_add(1, Ordering::Relaxed);
Self(format!("atp_transfer_{:016x}", id))
}
#[must_use]
pub fn as_str(&self) -> &str {
&self.0
}
}
impl std::fmt::Display for TransferId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TransferProgress {
pub transfer_id: TransferId,
pub bytes_transferred: u64,
pub total_bytes: u64,
pub speed_bytes_per_sec: u64,
pub eta_ms: Option<u64>,
pub phase: TransferPhase,
pub active_paths: u32,
pub repair_symbols_active: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum TransferPhase {
Initializing,
PathDiscovery,
SessionNegotiation,
ManifestTransfer,
DataTransfer,
Verification,
Finalization,
Completed,
Failed,
Cancelled,
}
impl TransferProgress {
#[must_use]
pub fn progress_percent(&self) -> f64 {
if self.total_bytes == 0 {
return 0.0;
}
(self.bytes_transferred as f64 / self.total_bytes as f64) * 100.0
}
#[must_use]
pub const fn is_complete(&self) -> bool {
matches!(
self.phase,
TransferPhase::Completed | TransferPhase::Failed | TransferPhase::Cancelled
)
}
}
impl Default for SessionConfig {
fn default() -> Self {
Self {
local_peer: PeerId::from_label("default_local_peer"),
session_timeout_ms: 30000,
enable_compression: true,
enable_repair: true,
enable_resume: true,
max_concurrent_transfers: 10,
stream_buffer_size: 64 * 1024, }
}
}
impl Default for TransferPolicy {
fn default() -> Self {
Self {
max_transfer_size_bytes: 10 * 1024 * 1024 * 1024, max_chunk_size_bytes: 1024 * 1024, transfer_timeout_ms: 300000, enable_auto_retry: true,
max_retry_attempts: 3,
retry_backoff_ms: 1000,
progress_report_interval_ms: 1000,
}
}
}
impl AtpSdk {
#[must_use]
pub fn new_in_process(config: SessionConfig) -> Self {
Self {
mode: SdkMode::InProcess,
default_config: config,
transfer_policy: TransferPolicy::default(),
}
}
#[must_use]
pub fn new_daemon_delegated(
config: SessionConfig,
daemon_endpoint: String,
auth_token: Option<String>,
) -> Self {
Self {
mode: SdkMode::DaemonDelegated {
daemon_endpoint,
auth_token,
},
default_config: config,
transfer_policy: TransferPolicy::default(),
}
}
#[must_use]
pub fn with_transfer_policy(mut self, policy: TransferPolicy) -> Self {
self.transfer_policy = policy;
self
}
#[must_use]
pub const fn mode(&self) -> &SdkMode {
&self.mode
}
#[must_use]
pub const fn default_config(&self) -> &SessionConfig {
&self.default_config
}
#[must_use]
pub const fn transfer_policy(&self) -> &TransferPolicy {
&self.transfer_policy
}
}