#[derive(Debug, Clone)]
pub struct TransportError {
pub code: String,
pub message: String,
pub details: Option<serde_json::Value>,
}
impl TransportError {
pub fn new(code: impl Into<String>, message: impl Into<String>) -> Self {
TransportError {
code: code.into(),
message: message.into(),
details: None,
}
}
}
#[derive(Debug, Clone)]
pub struct SegmentRequest {
pub segment_id: String,
pub table: String,
pub requested_scopes_json: String,
}
#[derive(Debug, Clone)]
pub enum SegmentFetch {
Direct(SegmentRequest),
Url(String),
}
#[derive(Debug, Clone)]
pub enum BlobDownload {
Bytes(Vec<u8>),
Url {
url: String,
url_expires_at_ms: Option<i64>,
},
}
#[derive(Debug, Clone)]
pub enum BlobUploadGrant {
Url {
url: String,
url_expires_at_ms: Option<i64>,
},
Present,
None,
}
pub trait Transport {
fn sync(&mut self, request: &[u8]) -> Result<Vec<u8>, TransportError>;
fn remote_operation(&mut self, request: &[u8]) -> Result<Vec<u8>, TransportError> {
let _ = request;
Err(TransportError::new(
"client.remote_operations_unconfigured",
"this transport has no remote operation endpoint",
))
}
fn realtime_sync(&mut self, request: &[u8]) -> Result<Vec<u8>, TransportError>;
fn download_segment(
&mut self,
request: &SegmentRequest,
_on_progress: &mut dyn FnMut(u64),
) -> Result<Vec<u8>, TransportError>;
fn download_segments(
&mut self,
fetches: &[SegmentFetch],
on_progress: &mut (dyn FnMut(usize, u64) + Send),
) -> Vec<Result<Vec<u8>, TransportError>> {
let mut results = Vec::new();
for (index, fetch) in fetches.iter().enumerate() {
let mut report = |bytes| on_progress(index, bytes);
let result = match fetch {
SegmentFetch::Direct(request) => self.download_segment(request, &mut report),
SegmentFetch::Url(url) => self.fetch_url(url, &mut report),
};
let failed = result.is_err();
results.push(result);
if failed {
break;
}
}
results
}
fn supports_url_fetch(&self) -> bool {
false
}
fn fetch_url(
&mut self,
url: &str,
_on_progress: &mut dyn FnMut(u64),
) -> Result<Vec<u8>, TransportError> {
let _ = url;
Err(TransportError::new(
"sync.invalid_request",
"this transport has no direct URL fetch (§5.4)",
))
}
fn segment_fetch_started_at(&self, _url: &str) -> Option<i64> {
None
}
fn blob_upload(
&mut self,
blob_id: &str,
bytes: &[u8],
media_type: Option<&str>,
) -> Result<(), TransportError> {
let _ = (blob_id, bytes, media_type);
Err(TransportError::new(
"sync.invalid_request",
"this transport has no blob upload (§5.9)",
))
}
fn blob_download(&mut self, blob_id: &str) -> Result<BlobDownload, TransportError> {
let _ = blob_id;
Err(TransportError::new(
"blob.not_found",
"this transport has no blob download (§5.9)",
))
}
fn fetch_blob_url(&mut self, url: &str) -> Result<Vec<u8>, TransportError> {
let _ = url;
Err(TransportError::new(
"sync.invalid_request",
"this transport has no blob url fetch (§5.9.5)",
))
}
fn blob_upload_grant(
&mut self,
blob_id: &str,
byte_length: u64,
media_type: Option<&str>,
) -> Result<BlobUploadGrant, TransportError> {
let _ = (blob_id, byte_length, media_type);
Ok(BlobUploadGrant::None)
}
fn blob_put_url(
&mut self,
url: &str,
bytes: &[u8],
media_type: Option<&str>,
) -> Result<(), TransportError> {
let _ = (url, bytes, media_type);
Err(TransportError::new(
"sync.invalid_request",
"this transport has no blob put url (§5.9.3)",
))
}
fn realtime_connect(&mut self) -> Result<(), TransportError>;
fn realtime_connect_for_client(&mut self, _client_id: &str) -> Result<(), TransportError> {
self.realtime_connect()
}
fn round_deadline(&self) -> Option<std::time::Duration> {
None
}
fn set_round_deadline(&mut self, _deadline: Option<std::time::Instant>) {}
fn realtime_send(&mut self, text: &str) -> Result<(), TransportError>;
fn realtime_close(&mut self) -> Result<(), TransportError>;
}