libmpv_client/types/
traits.rs

1//! Traits that define which types can be sent to and received from mpv.
2#![allow(private_bounds)]
3
4use std::ffi::c_void;
5use crate::{Format, Result};
6
7/// Defines a type understood by mpv.
8pub trait MpvFormat: Sized {
9    /// Defines the [`mpv_format`](libmpv_client_sys::mpv_format) used with mpv when transferring and requesting data.
10    const MPV_FORMAT: Format;
11}
12
13/// Defines a type which may be sent to mpv.
14///
15/// All types sent to mpv must have a stable C representation. However, since trait implementations may be able to
16/// construct these intermediate representations before sending the data to mpv, this trait is a superset of [`MpvRecv`]
17/// (i.e., it includes [`&str`] in addition to [`String`]).
18pub trait MpvSend: MpvSendInternal {}
19pub(crate) trait MpvSendInternal: MpvFormat {
20    /// Prepare and send data to mpv.
21    ///
22    /// Functionally, it prepares the data for sending to mpv (if necessary, by allocating an mpv-friendly data structure
23    /// and cloning the Rust structure's data into it) and then calls the provided function pointer `fun`. This function
24    /// is provided a `*mut c_void` and is expected to pass it to a libmpv function.
25    ///
26    /// See [`Handle::set_property()`](crate::Handle::set_property) for example usage.
27    fn to_mpv<F: Fn(*mut c_void) -> Result<i32>>(&self, fun: F) -> Result<i32>;
28}
29
30/// Defines a type which may be received from mpv.
31///
32/// Any data received from mpv is read-only. Thus, all types implementing this trait must own their own storage (i.e., cannot be references).
33/// Trait implementations are expected to copy any data mpv provides into their own structures as necessary.
34/// For complex types (i.e., [`Node`](crate::Node), or which may contain [`NodeArray`](crate::NodeArray)/[`NodeMap`](crate::NodeMap),
35/// which themselves contain more nodes), this can be comparatively expensive.
36pub trait MpvRecv: MpvRecvInternal {}
37pub(crate) trait MpvRecvInternal: MpvFormat {
38    // TODO: Reevaluate whether functions which are now properly guarded need to be marked themselves unsafe.
39    // I think they probably do, since they still rely on the pointer being to a valid data structure, which cannot be checked at runtime.
40    // During my documentation overhaul I will clearly document this contract.
41    /// Get a type T from a pointer to its mpv representation.
42    ///
43    /// Performs any necessary data copying or adjustment to go from a pointer to the mpv-friendly
44    /// C representation block into a Rust type.
45    ///
46    /// In simple cases this may just be a pointer cast, dereference, and copy,
47    /// while more complex types require several allocations.
48    ///
49    /// # Safety
50    /// This function assumes that the block pointer to by `ptr` is of the correct format for the type.
51    ///
52    /// Since any type information is lost to the [`c_void`] pointer, it is critical that only pointers to
53    /// properly structured data be passed in. In nearly all cases, these should be provided directly by mpv.
54    unsafe fn from_ptr(ptr: *const c_void) -> Result<Self>;
55
56    /// Receive data from mpv and process it into a Rust type.
57    ///
58    /// Functionally, it allocates a zero'd mpv-friendly data structure for the type `T`.
59    /// A `*mut c_void` pointer to this block is provided to the function pointer `fun`,
60    /// which is expected to pass it to a libmpv function.
61    /// Then the data is processed to turn it from the mpv-friendly C representation into a Rust type.
62    ///
63    /// See [`Handle::get_property()`](crate::Handle::get_property) for example usage.
64    ///
65    /// # Safety
66    /// This function assumes that the function `fun` will fill the pass pointer only with data that is of the correct format for the type.
67    ///
68    /// In many implementations, this function calls [`MpvRecv::from_ptr()`] (usually except in cases of primitives) with no additional checks.
69    /// In nearly all cases, `fun` should simply provide the pointer to mpv and let it handle writing the data.
70    unsafe fn from_mpv<F: Fn(*mut c_void) -> Result<i32>>(fun: F) -> Result<Self>;
71}
72
73pub(crate) trait ToMpvRepr: MpvSend {
74    type ReprWrap<'a>: MpvRepr where Self: 'a;
75
76    // TODO: Make this return a Result<> for better error handling.
77    fn to_mpv_repr(&self) -> Self::ReprWrap<'_>;
78}
79
80pub(crate) trait MpvRepr: Sized {
81    type Repr;
82
83    fn ptr(&self) -> *const Self::Repr;
84}