use std::path::PathBuf;
use efema_proto::{Epoch, StreamName};
use lacodda_seal::KeyId;
use crate::transport::TransportError;
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum Error {
#[error(transparent)]
Transport(#[from] TransportError),
#[error("stream {stream} is gone from the relay")]
StreamGone { stream: StreamName },
#[error("stream {stream} on the relay is not the one this device synced with")]
StreamReplaced { stream: StreamName },
#[error("stream {stream} ends at {head} on the relay, and this device has read up to {cursor}")]
CursorAhead { stream: StreamName, cursor: u64, head: u64 },
#[error("stream {stream} on the relay has another history at position {seq} than the one this device read")]
CursorDiverged { stream: StreamName, seq: u64 },
#[error("stream {stream}: the entry at position {seq} does not follow from the one before it")]
BrokenChain { stream: StreamName, seq: u64 },
#[error(
"stream {stream} is at epoch {current}, and this app writes epoch {ours}: a newer version of the app has written to it"
)]
EpochBehind { stream: StreamName, ours: Epoch, current: Epoch },
#[error("stream {stream}: the entry at position {seq} is in epoch {entry}, and this app reads up to epoch {ours}")]
NewerEpoch { stream: StreamName, seq: u64, ours: Epoch, entry: Epoch },
#[error("stream {stream}: the entry at position {seq} is in entry format {version}, newer than this library reads")]
NewerEntryFormat { stream: StreamName, seq: u64, version: u8 },
#[error(
"stream {stream}: the entry at position {seq} is compressed with codec {codec}, newer than this library reads"
)]
NewerCodec { stream: StreamName, seq: u64, codec: u8 },
#[error("the passphrase does not unlock the key of stream {stream}")]
WrongPassphrase { stream: StreamName },
#[error(
"the passphrase of stream {stream} was changed on another device at the same moment, and that change holds"
)]
PassphraseRace { stream: StreamName },
#[error("stream {stream} is sealed under key {stream_key}, not under the key given ({ours})")]
KeyMismatch { stream: StreamName, ours: KeyId, stream_key: KeyId },
#[error("stream {stream} has no key yet: open it with a passphrase the first time")]
NoStreamKey { stream: StreamName },
#[error("stream {stream}: the entry at position {seq} is sealed under key {key}, which this device does not have")]
UnknownKey { stream: StreamName, seq: u64, key: KeyId },
#[error("stream {stream}: the entry at position {seq} does not open - it was changed after it was sealed")]
Inauthentic { stream: StreamName, seq: u64 },
#[error("stream {stream}: the entry at position {seq} was not written by an efema client")]
ForeignEntry { stream: StreamName, seq: u64 },
#[error(transparent)]
Seal(#[from] lacodda_seal::Error),
#[error("an item of {size} bytes is larger than the {limit} bytes one request may carry")]
ItemTooLarge { size: usize, limit: usize },
#[error("the push stopped after {written} of its items were written")]
Interrupted {
written: usize,
#[source]
source: Box<Error>,
},
#[error("the sync state in {path} failed")]
State {
path: PathBuf,
#[source]
source: rusqlite::Error,
},
#[error("the sync state in {path} has schema version {found}, newer than this library reads")]
StateNewer { path: PathBuf, found: i64 },
#[error("the sync state in {0} is in use by another process")]
StateBusy(PathBuf),
#[error("cannot lock the sync state {path}")]
StateLock {
path: PathBuf,
#[source]
source: std::io::Error,
},
#[error("the operating system's random source failed")]
Random,
}