1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
//! Internal shared convenient things.
use crate::error::{Result, Ret, RsmpegError};
use libc::c_int;
use rusty_ffmpeg::ffi;
use std::{ops::Deref, ptr::NonNull};
/// Triage a pointer to Some(non-null) or None
pub trait PointerUpgrade<T>: Sized {
    fn upgrade(self) -> Option<NonNull<T>>;
}
impl<T> PointerUpgrade<T> for *const T {
    #[inline]
    fn upgrade(self) -> Option<NonNull<T>> {
        NonNull::new(self as *mut _)
    }
}
impl<T> PointerUpgrade<T> for *mut T {
    #[inline]
    fn upgrade(self) -> Option<NonNull<T>> {
        NonNull::new(self)
    }
}
/// This is a common pattern in FFmpeg that an api returns Null as an error.
/// We can set specific error code(Usually FFmpeg error code like
/// ffi::AVERROR(ffi::ENOMEM)).
pub trait RsmpegPointerUpgrade<T>: PointerUpgrade<T> {
    /// Triage the pointer. If null, return RsmpegError::AVError(err) here.
    fn upgrade_or(self, err: c_int) -> Result<NonNull<T>>;
}
impl<T> RsmpegPointerUpgrade<T> for *const T {
    #[inline]
    fn upgrade_or(self, err: c_int) -> Result<NonNull<T>> {
        self.upgrade().ok_or(RsmpegError::AVError(err))
    }
}
impl<T> RsmpegPointerUpgrade<T> for *mut T {
    #[inline]
    fn upgrade_or(self, err: c_int) -> Result<NonNull<T>> {
        self.upgrade().ok_or(RsmpegError::AVError(err))
    }
}
/// This is a common pattern in FFmpeg that an api returns negative number as an
/// error, zero or bigger a success. Here we triage the returned number of FFmpeg
/// API to `Ok(positive)` and `Err(negative)`.
pub trait RetUpgrade {
    fn upgrade(self) -> Ret;
}
impl RetUpgrade for c_int {
    fn upgrade(self) -> Ret {
        if self < 0 {
            Ret::Err(self)
        } else {
            Ret::Ok(self)
        }
    }
}
/// This is a convenient trait we cannot find in the rust std library. Accessing
/// member of a ffi struct mutably is not always safe(consider directly changing
/// the capacity of a Vec). But for some members, accessing them is a need. So
/// `UnsafeDerefMut` is come to rescue. You can use `foo.deref_mut().member =
/// bar` in a unsafe block if type of foo implements this trait.
pub trait UnsafeDerefMut: Deref {
    /// Mutably dereferences the value, unsafely.
    /// # Safety
    ///
    /// This function should be used carefully, adding safe convenient for
    /// rsmpeg is preferred.
    unsafe fn deref_mut(&mut self) -> &mut Self::Target;
}
/// Since ffi::AVERROR(ffi::EAGAIN) is often used in match arm, but RFC #2920
/// ([tracking issue](https://github.com/rust-lang/rust/issues/76001)) haven't
/// yet been implemented, we currently create a const value here as a workaround.
pub const AVERROR_EAGAIN: i32 = ffi::AVERROR(ffi::EAGAIN);
pub const AVERROR_ENOMEM: i32 = ffi::AVERROR(ffi::ENOMEM);