wvb 0.2.0-next.fe10f84

Offline-first web resources delivery system for webview mounted frameworks/platforms
Documentation
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ErrorCode {
  Io,
  Compress,
  Decompress,
  Encode,
  Decode,
  Http,
  InvalidMagicNum,
  InvalidVersion,
  InvalidHeaderChecksum,
  InvalidIndexChecksum,
  ChecksumMismatch,
  BundleNotFound,
  BundleEntryNotExists,
  BundleCannotBeRemoved,
  InvalidFilepath,
  SerdeJson,
  CannotResolveProxyServer,
  Reqwest,
  InvalidRemoteUrl,
  InvalidRemoteBundle,
  RemoteBundleNotFound,
  RemoteForbidden,
  RemoteHttp,
  InvalidRemoteConfig,
  InvalidIntegrity,
  IntegrityRequired,
  IntegrityVerifyFailed,
  InvalidSignature,
  InvalidSigningKey,
  SignatureSignFailed,
  InvalidVerifyingKey,
  SignatureNotExists,
  SignatureVerifyFailed,
  Generic,
}

impl ErrorCode {
  /// The wire form of the code, as exposed to every binding.
  pub const fn as_str(&self) -> &'static str {
    match self {
      Self::Io => "io",
      Self::Compress => "compress",
      Self::Decompress => "decompress",
      Self::Encode => "encode",
      Self::Decode => "decode",
      Self::Http => "http",
      Self::InvalidMagicNum => "invalid_magic_num",
      Self::InvalidVersion => "invalid_version",
      Self::InvalidHeaderChecksum => "invalid_header_checksum",
      Self::InvalidIndexChecksum => "invalid_index_checksum",
      Self::ChecksumMismatch => "checksum_mismatch",
      Self::BundleNotFound => "bundle_not_found",
      Self::BundleEntryNotExists => "bundle_entry_not_exists",
      Self::BundleCannotBeRemoved => "bundle_cannot_be_removed",
      Self::InvalidFilepath => "invalid_filepath",
      Self::SerdeJson => "serde_json",
      Self::CannotResolveProxyServer => "cannot_resolve_proxy_server",
      Self::Reqwest => "reqwest",
      Self::InvalidRemoteUrl => "invalid_remote_url",
      Self::InvalidRemoteBundle => "invalid_remote_bundle",
      Self::RemoteBundleNotFound => "remote_bundle_not_found",
      Self::RemoteForbidden => "remote_forbidden",
      Self::RemoteHttp => "remote_http",
      Self::InvalidRemoteConfig => "invalid_remote_config",
      Self::InvalidIntegrity => "invalid_integrity",
      Self::IntegrityRequired => "integrity_required",
      Self::IntegrityVerifyFailed => "integrity_verify_failed",
      Self::InvalidSignature => "invalid_signature",
      Self::InvalidSigningKey => "invalid_signing_key",
      Self::SignatureSignFailed => "signature_sign_failed",
      Self::InvalidVerifyingKey => "invalid_verifying_key",
      Self::SignatureNotExists => "signature_not_exists",
      Self::SignatureVerifyFailed => "signature_verify_failed",
      Self::Generic => "generic",
    }
  }
}

impl std::fmt::Display for ErrorCode {
  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    f.write_str(self.as_str())
  }
}

#[derive(Debug, thiserror::Error)]
pub enum Error {
  #[error("io error: {0}")]
  Io(#[from] std::io::Error),
  #[error("compress error: {0}")]
  Compress(#[from] lz4_flex::block::CompressError),
  #[error("decompress error: {0}")]
  Decompress(#[from] lz4_flex::block::DecompressError),
  #[error("encode error: {message}")]
  Encode {
    #[source]
    error: bincode::error::EncodeError,
    message: String,
  },
  #[error("decode error: {message}")]
  Decode {
    #[source]
    error: bincode::error::DecodeError,
    message: String,
  },
  #[error("http error: {0}")]
  Http(#[from] http::Error),
  #[error("invalid magic number")]
  InvalidMagicNum,
  #[error("invalid version format")]
  InvalidVersion,
  #[error("invalid header checksum")]
  InvalidHeaderChecksum,
  #[error("invalid index checksum")]
  InvalidIndexChecksum,
  #[error("checksum mismatch")]
  ChecksumMismatch,
  #[error("bundle not found")]
  BundleNotFound,
  #[cfg(feature = "source")]
  #[error("bundle entry not exists (bundle_name: {bundle_name}, version: {version})")]
  BundleEntryNotExists {
    bundle_name: String,
    version: String,
  },
  #[cfg(feature = "source")]
  #[error("bundle cannot be removed (bundle_name: {bundle_name}, version: {version}): {reason}")]
  BundleCannotBeRemoved {
    bundle_name: String,
    version: String,
    reason: String,
  },
  #[cfg(feature = "source")]
  #[error("invalid filepath: {0:?}")]
  InvalidFilepath(String),
  #[cfg(feature = "_serde")]
  #[error("serde json error: {0}")]
  SerdeJson(#[from] serde_json::Error),
  #[cfg(feature = "protocol-proxy")]
  #[error("cannot resolve proxy server")]
  CannotResolveProxyServer,
  #[cfg(feature = "_reqwest")]
  #[error("reqwest error: {0}")]
  Reqwest(#[from] reqwest::Error),
  #[cfg(feature = "remote")]
  #[error("invalid remote url: {0}")]
  InvalidRemoteUrl(#[from] http::uri::InvalidUri),
  #[cfg(feature = "remote")]
  #[error("invalid remote bundle: {0}")]
  InvalidRemoteBundle(String),
  #[cfg(feature = "remote")]
  #[error("remote bundle not found")]
  RemoteBundleNotFound,
  #[cfg(feature = "remote")]
  #[error("remote forbidden")]
  RemoteForbidden,
  #[cfg(feature = "remote")]
  #[error("remote http error with status {status}")]
  RemoteHttp {
    status: u16,
    message: Option<String>,
  },
  #[cfg(feature = "remote")]
  #[error("invalid remote config: {0}")]
  InvalidRemoteConfig(String),
  #[cfg(feature = "integrity")]
  #[error("invalid integrity: {0}")]
  InvalidIntegrity(String),
  #[cfg(feature = "integrity")]
  #[error("integrity required")]
  IntegrityRequired,
  #[cfg(feature = "integrity")]
  #[error("integrity verify failed")]
  IntegrityVerifyFailed,
  #[cfg(feature = "signature")]
  #[error("invalid signature")]
  InvalidSignature,
  #[cfg(feature = "signature")]
  #[error("invalid signing key: {0}")]
  InvalidSigningKey(#[source] Box<dyn std::error::Error + Send + Sync + 'static>),
  #[cfg(feature = "signature")]
  #[error("signature sign failed: {0}")]
  SignatureSignFailed(#[source] Box<dyn std::error::Error + Send + Sync + 'static>),
  #[cfg(feature = "signature")]
  #[error("invalid verifying key: {0}")]
  InvalidVerifyingKey(#[source] Box<dyn std::error::Error + Send + Sync + 'static>),
  #[cfg(feature = "signature")]
  #[error("signature not exists")]
  SignatureNotExists,
  #[cfg(feature = "signature")]
  #[error("signature verify failed")]
  SignatureVerifyFailed,
  #[error("generic error: {0}")]
  Generic(#[source] Box<dyn std::error::Error + Send + Sync + 'static>),
}

impl Error {
  pub fn code(&self) -> ErrorCode {
    match self {
      Self::Io(_) => ErrorCode::Io,
      Self::Compress(_) => ErrorCode::Compress,
      Self::Decompress(_) => ErrorCode::Decompress,
      Self::Encode { .. } => ErrorCode::Encode,
      Self::Decode { .. } => ErrorCode::Decode,
      Self::Http(_) => ErrorCode::Http,
      Self::InvalidMagicNum => ErrorCode::InvalidMagicNum,
      Self::InvalidVersion => ErrorCode::InvalidVersion,
      Self::InvalidHeaderChecksum => ErrorCode::InvalidHeaderChecksum,
      Self::InvalidIndexChecksum => ErrorCode::InvalidIndexChecksum,
      Self::ChecksumMismatch => ErrorCode::ChecksumMismatch,
      Self::BundleNotFound => ErrorCode::BundleNotFound,
      #[cfg(feature = "source")]
      Self::BundleEntryNotExists { .. } => ErrorCode::BundleEntryNotExists,
      #[cfg(feature = "source")]
      Self::BundleCannotBeRemoved { .. } => ErrorCode::BundleCannotBeRemoved,
      #[cfg(feature = "source")]
      Self::InvalidFilepath(_) => ErrorCode::InvalidFilepath,
      #[cfg(feature = "_serde")]
      Self::SerdeJson(_) => ErrorCode::SerdeJson,
      #[cfg(feature = "protocol-proxy")]
      Self::CannotResolveProxyServer => ErrorCode::CannotResolveProxyServer,
      #[cfg(feature = "_reqwest")]
      Self::Reqwest(_) => ErrorCode::Reqwest,
      #[cfg(feature = "remote")]
      Self::InvalidRemoteUrl(_) => ErrorCode::InvalidRemoteUrl,
      #[cfg(feature = "remote")]
      Self::InvalidRemoteBundle(_) => ErrorCode::InvalidRemoteBundle,
      #[cfg(feature = "remote")]
      Self::RemoteBundleNotFound => ErrorCode::RemoteBundleNotFound,
      #[cfg(feature = "remote")]
      Self::RemoteForbidden => ErrorCode::RemoteForbidden,
      #[cfg(feature = "remote")]
      Self::RemoteHttp { .. } => ErrorCode::RemoteHttp,
      #[cfg(feature = "remote")]
      Self::InvalidRemoteConfig(_) => ErrorCode::InvalidRemoteConfig,
      #[cfg(feature = "integrity")]
      Self::InvalidIntegrity(_) => ErrorCode::InvalidIntegrity,
      #[cfg(feature = "integrity")]
      Self::IntegrityRequired => ErrorCode::IntegrityRequired,
      #[cfg(feature = "integrity")]
      Self::IntegrityVerifyFailed => ErrorCode::IntegrityVerifyFailed,
      #[cfg(feature = "signature")]
      Self::InvalidSignature => ErrorCode::InvalidSignature,
      #[cfg(feature = "signature")]
      Self::InvalidSigningKey(_) => ErrorCode::InvalidSigningKey,
      #[cfg(feature = "signature")]
      Self::SignatureSignFailed(_) => ErrorCode::SignatureSignFailed,
      #[cfg(feature = "signature")]
      Self::InvalidVerifyingKey(_) => ErrorCode::InvalidVerifyingKey,
      #[cfg(feature = "signature")]
      Self::SignatureNotExists => ErrorCode::SignatureNotExists,
      #[cfg(feature = "signature")]
      Self::SignatureVerifyFailed => ErrorCode::SignatureVerifyFailed,
      Self::Generic(_) => ErrorCode::Generic,
    }
  }

  #[cfg(feature = "source")]
  pub(crate) fn bundle_entry_not_exists(
    bundle_name: impl Into<String>,
    version: impl Into<String>,
  ) -> Self {
    Self::BundleEntryNotExists {
      bundle_name: bundle_name.into(),
      version: version.into(),
    }
  }

  #[cfg(feature = "source")]
  pub(crate) fn bundle_cannot_be_removed(
    bundle_name: impl Into<String>,
    version: impl Into<String>,
    reason: impl Into<String>,
  ) -> Self {
    Self::BundleCannotBeRemoved {
      bundle_name: bundle_name.into(),
      version: version.into(),
      reason: reason.into(),
    }
  }

  #[cfg(feature = "source")]
  pub(crate) fn invalid_filepath(filepath: impl Into<String>) -> Self {
    Self::InvalidFilepath(filepath.into())
  }

  #[cfg(feature = "remote")]
  pub(crate) fn invalid_remote_config(message: impl Into<String>) -> Self {
    Self::InvalidRemoteConfig(message.into())
  }

  #[cfg(feature = "remote")]
  pub(crate) fn invalid_remote_bundle(message: impl Into<String>) -> Self {
    Self::InvalidRemoteBundle(message.into())
  }

  #[cfg(feature = "remote")]
  pub(crate) fn remote_http(status: http::StatusCode, message: Option<impl Into<String>>) -> Self {
    Self::RemoteHttp {
      status: status.as_u16(),
      message: message.map(|x| x.into()),
    }
  }

  #[cfg(feature = "integrity")]
  pub(crate) fn invalid_integrity(message: impl Into<String>) -> Self {
    Self::InvalidIntegrity(message.into())
  }

  #[cfg(feature = "signature")]
  pub(crate) fn invalid_verifying_key(
    error: impl Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
  ) -> Self {
    Self::InvalidVerifyingKey(error.into())
  }

  #[allow(dead_code)]
  pub(crate) fn generic(
    error: impl Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
  ) -> Self {
    Self::Generic(error.into())
  }
}