diff --git a/src/rsfilesink.rs b/src/rsfilesink.rs index 999fd3db..abb564f8 100644 --- a/src/rsfilesink.rs +++ b/src/rsfilesink.rs @@ -66,7 +66,7 @@ impl Sink for FileSink { &self.controller } - fn set_uri(&self, uri: Option) -> Result<(), (UriError, String)> { + fn set_uri(&self, uri: Option) -> Result<(), UriError> { let location = &mut self.settings.lock().unwrap().location; match uri { @@ -82,8 +82,8 @@ impl Sink for FileSink { } None => { *location = None; - Err((UriError::UnsupportedProtocol, - format!("Unsupported file URI '{}'", uri.as_str()))) + Err(UriError::new(UriErrorKind::UnsupportedProtocol, + Some(format!("Unsupported file URI '{}'", uri.as_str())))) } } } diff --git a/src/rsfilesrc.rs b/src/rsfilesrc.rs index e065f91b..576b2cd3 100644 --- a/src/rsfilesrc.rs +++ b/src/rsfilesrc.rs @@ -67,7 +67,7 @@ impl Source for FileSrc { &self.controller } - fn set_uri(&self, uri: Option) -> Result<(), (UriError, String)> { + fn set_uri(&self, uri: Option) -> Result<(), UriError> { let location = &mut self.settings.lock().unwrap().location; match uri { @@ -83,8 +83,8 @@ impl Source for FileSrc { } None => { *location = None; - Err((UriError::UnsupportedProtocol, - format!("Unsupported file URI '{}'", uri.as_str()))) + Err(UriError::new(UriErrorKind::UnsupportedProtocol, + Some(format!("Unsupported file URI '{}'", uri.as_str())))) } } } diff --git a/src/rshttpsrc.rs b/src/rshttpsrc.rs index c7608389..b90634b1 100644 --- a/src/rshttpsrc.rs +++ b/src/rshttpsrc.rs @@ -145,7 +145,7 @@ impl Source for HttpSrc { &self.controller } - fn set_uri(&self, uri: Option) -> Result<(), (UriError, String)> { + fn set_uri(&self, uri: Option) -> Result<(), UriError> { let url = &mut self.settings.lock().unwrap().url; match uri { @@ -159,8 +159,8 @@ impl Source for HttpSrc { Ok(()) } else { *url = None; - Err((UriError::UnsupportedProtocol, - format!("Unsupported URI '{}'", uri.as_str()))) + Err(UriError::new(UriErrorKind::UnsupportedProtocol, + Some(format!("Unsupported URI '{}'", uri.as_str())))) } } } diff --git a/src/rssink.rs b/src/rssink.rs index 2b9f20df..d0a30486 100644 --- a/src/rssink.rs +++ b/src/rssink.rs @@ -41,7 +41,7 @@ pub trait Sink: Sync + Send { fn get_controller(&self) -> &SinkController; // Called from any thread at any time - fn set_uri(&self, uri: Option) -> Result<(), (UriError, String)>; + fn set_uri(&self, uri: Option) -> Result<(), UriError>; fn get_uri(&self) -> Option; // Called from the streaming thread only @@ -70,8 +70,8 @@ pub unsafe extern "C" fn sink_set_uri(ptr: *mut Box, let sink: &mut Box = &mut *ptr; if uri_ptr.is_null() { - if let Err((code, msg)) = sink.set_uri(None) { - code.into_gerror(cerr, Some(&msg)); + if let Err(err) = sink.set_uri(None) { + err.into_gerror(cerr); GBoolean::False } else { GBoolean::True @@ -81,8 +81,8 @@ pub unsafe extern "C" fn sink_set_uri(ptr: *mut Box, match Url::parse(uri_str) { Ok(uri) => { - if let Err((code, msg)) = sink.set_uri(Some(uri)) { - code.into_gerror(cerr, Some(&msg)); + if let Err(err) = sink.set_uri(Some(uri)) { + err.into_gerror(cerr); GBoolean::False } else { GBoolean::True @@ -90,10 +90,9 @@ pub unsafe extern "C" fn sink_set_uri(ptr: *mut Box, } Err(err) => { let _ = sink.set_uri(None); - UriError::BadUri.into_gerror(cerr, - Some(&format!("Failed to parse URI '{}': {}", - uri_str, - err))); + UriError::new(UriErrorKind::BadUri, + Some(format!("Failed to parse URI '{}': {}", uri_str, err))) + .into_gerror(cerr); GBoolean::False } } diff --git a/src/rssource.rs b/src/rssource.rs index ee88ae46..a3ddd64b 100644 --- a/src/rssource.rs +++ b/src/rssource.rs @@ -40,7 +40,7 @@ pub trait Source: Sync + Send { fn get_controller(&self) -> &SourceController; // Called from any thread at any time - fn set_uri(&self, uri: Option) -> Result<(), (UriError, String)>; + fn set_uri(&self, uri: Option) -> Result<(), UriError>; fn get_uri(&self) -> Option; // Called from any thread between start/stop @@ -74,8 +74,8 @@ pub unsafe extern "C" fn source_set_uri(ptr: *mut Box, let source: &mut Box = &mut *ptr; if uri_ptr.is_null() { - if let Err((code, msg)) = source.set_uri(None) { - code.into_gerror(cerr, Some(&msg)); + if let Err(err) = source.set_uri(None) { + err.into_gerror(cerr); GBoolean::False } else { GBoolean::True @@ -85,8 +85,8 @@ pub unsafe extern "C" fn source_set_uri(ptr: *mut Box, match Url::parse(uri_str) { Ok(uri) => { - if let Err((code, msg)) = source.set_uri(Some(uri)) { - code.into_gerror(cerr, Some(&msg)); + if let Err(err) = source.set_uri(Some(uri)) { + err.into_gerror(cerr); GBoolean::False } else { GBoolean::True @@ -94,10 +94,9 @@ pub unsafe extern "C" fn source_set_uri(ptr: *mut Box, } Err(err) => { let _ = source.set_uri(None); - UriError::BadUri.into_gerror(cerr, - Some(&format!("Failed to parse URI '{}': {}", - uri_str, - err))); + UriError::new(UriErrorKind::BadUri, + Some(format!("Failed to parse URI '{}': {}", uri_str, err))) + .into_gerror(cerr); GBoolean::False } } diff --git a/src/utils.rs b/src/utils.rs index 8bcd8753..ad856e67 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -20,6 +20,9 @@ use libc::c_char; use std::os::raw::c_void; use std::ffi::CString; use std::ptr; +use std::error::Error; +use std::fmt::{Display, Formatter}; +use std::fmt::Error as FmtError; #[macro_export] macro_rules! println_err( @@ -57,26 +60,73 @@ pub unsafe extern "C" fn cstring_drop(ptr: *mut c_char) { CString::from_raw(ptr); } -#[repr(C)] -pub enum UriError { +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum UriErrorKind { UnsupportedProtocol = 0, BadUri, BadState, BadReference, } +#[derive(Debug)] +pub struct UriError { + error_kind: UriErrorKind, + message: Option, +} + extern "C" { fn g_set_error_literal(err: *mut c_void, domain: u32, code: i32, message: *const c_char); fn gst_uri_error_quark() -> u32; } impl UriError { - pub unsafe fn into_gerror(self, err: *mut c_void, message: Option<&String>) { - if let Some(msg) = message { + pub fn new(error_kind: UriErrorKind, message: Option) -> UriError { + UriError { + error_kind: error_kind, + message: message, + } + } + + pub fn message(&self) -> &Option { + &self.message + } + + pub fn kind(&self) -> UriErrorKind { + self.error_kind + } + + pub unsafe fn into_gerror(self, err: *mut c_void) { + if let Some(msg) = self.message { let cmsg = CString::new(msg.as_str()).unwrap(); - g_set_error_literal(err, gst_uri_error_quark(), self as i32, cmsg.as_ptr()); + g_set_error_literal(err, + gst_uri_error_quark(), + self.error_kind as i32, + cmsg.as_ptr()); } else { - g_set_error_literal(err, gst_uri_error_quark(), self as i32, ptr::null()); + g_set_error_literal(err, + gst_uri_error_quark(), + self.error_kind as i32, + ptr::null()); + } + } +} + +impl Display for UriError { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { + match self.message { + None => f.write_str(self.description()), + Some(ref message) => f.write_fmt(format_args!("{}: {}", self.description(), message)), + } + } +} + +impl Error for UriError { + fn description(&self) -> &str { + match self.error_kind { + UriErrorKind::UnsupportedProtocol => "Unsupported protocol", + UriErrorKind::BadUri => "Bad URI", + UriErrorKind::BadState => "Bad State", + UriErrorKind::BadReference => "Bad Reference", } } }