use std::sync::Arc;
use crate::ffi;
pub const MOQ_ERROR_MOQ: i32 = -2;
pub const MOQ_ERROR_URL: i32 = -3;
pub const MOQ_ERROR_UTF8: i32 = -4;
pub const MOQ_ERROR_CONNECT: i32 = -5;
pub const MOQ_ERROR_INVALID_POINTER: i32 = -6;
pub const MOQ_ERROR_INVALID_ID: i32 = -7;
pub const MOQ_ERROR_NOT_FOUND: i32 = -8;
pub const MOQ_ERROR_UNKNOWN_FORMAT: i32 = -9;
pub const MOQ_ERROR_INIT_FAILED: i32 = -10;
pub const MOQ_ERROR_TIMESTAMP_OVERFLOW: i32 = -13;
pub const MOQ_ERROR_LEVEL: i32 = -14;
pub const MOQ_ERROR_INVALID_CODE: i32 = -15;
pub const MOQ_ERROR_PANIC: i32 = -16;
pub const MOQ_ERROR_OFFLINE: i32 = -17;
pub const MOQ_ERROR_HANG: i32 = -18;
pub const MOQ_ERROR_NO_INDEX: i32 = -19;
pub const MOQ_ERROR_NUL: i32 = -20;
pub const MOQ_ERROR_SESSION_NOT_FOUND: i32 = -21;
pub const MOQ_ERROR_ORIGIN_NOT_FOUND: i32 = -22;
pub const MOQ_ERROR_ANNOUNCEMENT_NOT_FOUND: i32 = -23;
pub const MOQ_ERROR_BROADCAST_NOT_FOUND: i32 = -24;
pub const MOQ_ERROR_CATALOG_NOT_FOUND: i32 = -25;
pub const MOQ_ERROR_MEDIA_NOT_FOUND: i32 = -26;
pub const MOQ_ERROR_TRACK_NOT_FOUND: i32 = -27;
pub const MOQ_ERROR_FRAME_NOT_FOUND: i32 = -28;
pub const MOQ_ERROR_MUX: i32 = -29;
pub const MOQ_ERROR_AUDIO: i32 = -30;
pub const MOQ_ERROR_BUFFER_NOT_CONSUMED: i32 = -31;
pub const MOQ_ERROR_GROUP_NOT_FOUND: i32 = -32;
pub const MOQ_ERROR_NATIVE: i32 = -33;
pub const MOQ_ERROR_UNAUTHORIZED: i32 = -34;
pub const MOQ_ERROR_FORBIDDEN: i32 = -35;
pub const MOQ_ERROR_VIDEO: i32 = -36;
pub const MOQ_ERROR_JSON: i32 = -37;
pub const MOQ_ERROR_JSON_TRACK: i32 = -38;
pub const MOQ_ERROR_INVALID_CONFIG: i32 = -40;
pub const MOQ_ERROR_UNRESOLVABLE_BROADCAST: i32 = -41;
#[repr(C)]
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, Debug)]
pub enum moq_error_scope {
MOQ_ERROR_SCOPE_SESSION = 0,
MOQ_ERROR_SCOPE_STREAM = 1,
}
#[repr(C)]
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, Debug)]
pub enum moq_protocol_kind {
MOQ_PROTOCOL_KIND_CANCEL = 0,
MOQ_PROTOCOL_KIND_INTERNAL = 1,
MOQ_PROTOCOL_KIND_UNAUTHORIZED = 2,
MOQ_PROTOCOL_KIND_PROTOCOL_VIOLATION = 3,
MOQ_PROTOCOL_KIND_KEY_VALUE_FORMATTING = 4,
MOQ_PROTOCOL_KIND_GOAWAY_TIMEOUT = 5,
MOQ_PROTOCOL_KIND_TIMEOUT = 6,
MOQ_PROTOCOL_KIND_VERSION = 7,
MOQ_PROTOCOL_KIND_DELIVERY_TIMEOUT = 11,
MOQ_PROTOCOL_KIND_SESSION_CLOSED = 12,
MOQ_PROTOCOL_KIND_GOING_AWAY = 13,
MOQ_PROTOCOL_KIND_TOO_FAR_BEHIND = 14,
MOQ_PROTOCOL_KIND_MALFORMED_TRACK = 15,
MOQ_PROTOCOL_KIND_NOT_FOUND = 16,
MOQ_PROTOCOL_KIND_UNROUTABLE = 17,
MOQ_PROTOCOL_KIND_OLD = 18,
MOQ_PROTOCOL_KIND_EVICTED = 19,
MOQ_PROTOCOL_KIND_WRONG_SIZE = 20,
MOQ_PROTOCOL_KIND_FRAME_TOO_LARGE = 21,
MOQ_PROTOCOL_KIND_TIMESTAMP_MISMATCH = 22,
MOQ_PROTOCOL_KIND_APP = 23,
MOQ_PROTOCOL_KIND_UNKNOWN = 24,
}
#[repr(C)]
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, Debug)]
pub struct moq_protocol_error {
pub scope: u32,
pub code: u32,
pub kind: u32,
}
pub type Status = i32;
#[derive(Debug, thiserror::Error, Clone)]
#[non_exhaustive]
pub enum Error {
#[error("moq error: {0}")]
Moq(#[from] moq_net::Error),
#[error("native error: {0}")]
Native(#[from] moq_tokio::Error),
#[error("url error: {0}")]
Url(String),
#[error("utf8 error: {0}")]
Utf8(#[from] std::str::Utf8Error),
#[error("connect error: {0}")]
Connect(Arc<anyhow::Error>),
#[error("invalid pointer")]
InvalidPointer,
#[error("invalid id")]
InvalidId,
#[error("not found")]
NotFound,
#[error("session not found")]
SessionNotFound,
#[error("origin not found")]
OriginNotFound,
#[error("announcement not found")]
AnnouncementNotFound,
#[error("broadcast not found")]
BroadcastNotFound,
#[error("catalog not found")]
CatalogNotFound,
#[error("media not found")]
MediaNotFound,
#[error("track not found")]
TrackNotFound,
#[error("group not found")]
GroupNotFound,
#[error("frame not found")]
FrameNotFound,
#[error("unknown format: {0}")]
UnknownFormat(String),
#[error("init failed: {0}")]
InitFailed(Arc<anyhow::Error>),
#[error("buffer was not fully consumed")]
BufferNotConsumed,
#[error("timestamp overflow")]
TimestampOverflow(#[from] moq_net::TimeOverflow),
#[error("level error: {0}")]
Level(String),
#[error("invalid code")]
InvalidCode,
#[error("panic")]
Panic,
#[error("offline")]
Offline,
#[error("unauthorized")]
Unauthorized,
#[error("forbidden")]
Forbidden,
#[error("hang error: {0}")]
Hang(#[from] hang::Error),
#[error("mux error: {0}")]
Mux(#[from] moq_mux::Error),
#[error("no index")]
NoIndex,
#[error("nul error")]
NulError(#[from] std::ffi::NulError),
#[error("audio error: {0}")]
Audio(Arc<moq_audio::Error>),
#[error("video error: {0}")]
Video(Arc<moq_video::Error>),
#[error("json error: {0}")]
Json(String),
#[error("json track error: {0}")]
JsonTrack(Arc<moq_json::Error>),
#[error("invalid config: {0}")]
InvalidConfig(String),
#[error("unresolvable broadcast reference: {0}")]
UnresolvableBroadcast(String),
}
impl From<moq_json::Error> for Error {
fn from(err: moq_json::Error) -> Self {
match err {
moq_json::Error::Net(e) => Error::Moq(e),
e => Error::JsonTrack(Arc::new(e)),
}
}
}
impl From<serde_json::Error> for Error {
fn from(err: serde_json::Error) -> Self {
Error::Json(err.to_string())
}
}
impl From<moq_net::InvalidPattern> for Error {
fn from(err: moq_net::InvalidPattern) -> Self {
Error::InvalidConfig(err.to_string())
}
}
impl From<url::ParseError> for Error {
fn from(err: url::ParseError) -> Self {
Error::Url(err.to_string())
}
}
impl From<moq_audio::Error> for Error {
fn from(err: moq_audio::Error) -> Self {
Error::Audio(Arc::new(err))
}
}
impl From<moq_video::Error> for Error {
fn from(err: moq_video::Error) -> Self {
Error::Video(Arc::new(err))
}
}
impl From<tracing::metadata::ParseLevelError> for Error {
fn from(err: tracing::metadata::ParseLevelError) -> Self {
Error::Level(err.to_string())
}
}
impl Error {
pub(crate) fn protocol(&self) -> Option<moq_protocol_error> {
std::iter::successors(Some(self as &(dyn std::error::Error + 'static)), |err| err.source())
.find_map(|err| err.downcast_ref::<moq_net::Error>().and_then(protocol_of_net))
}
}
fn protocol_of_net(err: &moq_net::Error) -> Option<moq_protocol_error> {
match err {
moq_net::Error::Transport(_) => None,
moq_net::Error::Session(err) => Some(from_session(err)),
moq_net::Error::Stream(err) => Some(from_stream(err)),
moq_net::Error::App(app) => Some(from_stream(&moq_net::StreamError::App(*app))),
_ => None,
}
}
fn from_session(err: &moq_net::SessionError) -> moq_protocol_error {
moq_protocol_error {
scope: moq_error_scope::MOQ_ERROR_SCOPE_SESSION as u32,
code: err.to_code(),
kind: session_kind(err) as u32,
}
}
fn from_stream(err: &moq_net::StreamError) -> moq_protocol_error {
moq_protocol_error {
scope: moq_error_scope::MOQ_ERROR_SCOPE_STREAM as u32,
code: err.to_code(),
kind: stream_kind(err) as u32,
}
}
fn session_kind(err: &moq_net::SessionError) -> moq_protocol_kind {
use moq_protocol_kind::*;
match err {
moq_net::SessionError::Cancel => MOQ_PROTOCOL_KIND_CANCEL,
moq_net::SessionError::Internal => MOQ_PROTOCOL_KIND_INTERNAL,
moq_net::SessionError::Unauthorized => MOQ_PROTOCOL_KIND_UNAUTHORIZED,
moq_net::SessionError::ProtocolViolation => MOQ_PROTOCOL_KIND_PROTOCOL_VIOLATION,
moq_net::SessionError::KeyValueFormatting => MOQ_PROTOCOL_KIND_KEY_VALUE_FORMATTING,
moq_net::SessionError::GoawayTimeout => MOQ_PROTOCOL_KIND_GOAWAY_TIMEOUT,
moq_net::SessionError::Timeout => MOQ_PROTOCOL_KIND_TIMEOUT,
moq_net::SessionError::Version => MOQ_PROTOCOL_KIND_VERSION,
moq_net::SessionError::App(_) => MOQ_PROTOCOL_KIND_APP,
moq_net::SessionError::Unknown(_) => MOQ_PROTOCOL_KIND_UNKNOWN,
_ => MOQ_PROTOCOL_KIND_UNKNOWN,
}
}
fn stream_kind(err: &moq_net::StreamError) -> moq_protocol_kind {
use moq_protocol_kind::*;
match err {
moq_net::StreamError::Session(_) => MOQ_PROTOCOL_KIND_SESSION_CLOSED,
moq_net::StreamError::Internal => MOQ_PROTOCOL_KIND_INTERNAL,
moq_net::StreamError::Cancel => MOQ_PROTOCOL_KIND_CANCEL,
moq_net::StreamError::DeliveryTimeout => MOQ_PROTOCOL_KIND_DELIVERY_TIMEOUT,
moq_net::StreamError::GoingAway => MOQ_PROTOCOL_KIND_GOING_AWAY,
moq_net::StreamError::TooFarBehind => MOQ_PROTOCOL_KIND_TOO_FAR_BEHIND,
moq_net::StreamError::MalformedTrack => MOQ_PROTOCOL_KIND_MALFORMED_TRACK,
moq_net::StreamError::NotFound => MOQ_PROTOCOL_KIND_NOT_FOUND,
moq_net::StreamError::Unroutable => MOQ_PROTOCOL_KIND_UNROUTABLE,
moq_net::StreamError::Old => MOQ_PROTOCOL_KIND_OLD,
moq_net::StreamError::Evicted => MOQ_PROTOCOL_KIND_EVICTED,
moq_net::StreamError::WrongSize => MOQ_PROTOCOL_KIND_WRONG_SIZE,
moq_net::StreamError::FrameTooLarge => MOQ_PROTOCOL_KIND_FRAME_TOO_LARGE,
moq_net::StreamError::TimestampMismatch => MOQ_PROTOCOL_KIND_TIMESTAMP_MISMATCH,
moq_net::StreamError::App(_) => MOQ_PROTOCOL_KIND_APP,
moq_net::StreamError::Unknown(_) => MOQ_PROTOCOL_KIND_UNKNOWN,
_ => MOQ_PROTOCOL_KIND_UNKNOWN,
}
}
impl ffi::ReturnCode for Error {
fn error(&self) -> Option<&Error> {
Some(self)
}
fn code(&self) -> i32 {
match self {
Error::Moq(_) => MOQ_ERROR_MOQ,
Error::Url(_) => MOQ_ERROR_URL,
Error::Utf8(_) => MOQ_ERROR_UTF8,
Error::Connect(_) => MOQ_ERROR_CONNECT,
Error::InvalidPointer => MOQ_ERROR_INVALID_POINTER,
Error::InvalidId => MOQ_ERROR_INVALID_ID,
Error::NotFound => MOQ_ERROR_NOT_FOUND,
Error::UnknownFormat(_) => MOQ_ERROR_UNKNOWN_FORMAT,
Error::InitFailed(_) => MOQ_ERROR_INIT_FAILED,
Error::TimestampOverflow(_) => MOQ_ERROR_TIMESTAMP_OVERFLOW,
Error::Level(_) => MOQ_ERROR_LEVEL,
Error::InvalidCode => MOQ_ERROR_INVALID_CODE,
Error::Panic => MOQ_ERROR_PANIC,
Error::Offline => MOQ_ERROR_OFFLINE,
Error::Hang(_) => MOQ_ERROR_HANG,
Error::NoIndex => MOQ_ERROR_NO_INDEX,
Error::NulError(_) => MOQ_ERROR_NUL,
Error::SessionNotFound => MOQ_ERROR_SESSION_NOT_FOUND,
Error::OriginNotFound => MOQ_ERROR_ORIGIN_NOT_FOUND,
Error::AnnouncementNotFound => MOQ_ERROR_ANNOUNCEMENT_NOT_FOUND,
Error::BroadcastNotFound => MOQ_ERROR_BROADCAST_NOT_FOUND,
Error::CatalogNotFound => MOQ_ERROR_CATALOG_NOT_FOUND,
Error::MediaNotFound => MOQ_ERROR_MEDIA_NOT_FOUND,
Error::TrackNotFound => MOQ_ERROR_TRACK_NOT_FOUND,
Error::FrameNotFound => MOQ_ERROR_FRAME_NOT_FOUND,
Error::Mux(_) => MOQ_ERROR_MUX,
Error::Audio(_) => MOQ_ERROR_AUDIO,
Error::BufferNotConsumed => MOQ_ERROR_BUFFER_NOT_CONSUMED,
Error::GroupNotFound => MOQ_ERROR_GROUP_NOT_FOUND,
Error::Native(_) => MOQ_ERROR_NATIVE,
Error::Unauthorized => MOQ_ERROR_UNAUTHORIZED,
Error::Forbidden => MOQ_ERROR_FORBIDDEN,
Error::Video(_) => MOQ_ERROR_VIDEO,
Error::Json(_) => MOQ_ERROR_JSON,
Error::JsonTrack(_) => MOQ_ERROR_JSON_TRACK,
Error::InvalidConfig(_) => MOQ_ERROR_INVALID_CONFIG,
Error::UnresolvableBroadcast(_) => MOQ_ERROR_UNRESOLVABLE_BROADCAST,
}
}
}