gstreamer-rs/gstreamer/src/pad_template.rs
François Laignel ea25c9262b Add field_if_some setter for builders
This commit adds `_if_some()` variants for builder field setters.
The variants aim at improving usability when setting optional fields.
E.g. currently, we need to write something like:

```rust
let opt_value = ...;
let mut sb = gst::Structure::builder("test")
    .field("mandatory_field", "mandatory");

if let Some(value) = opt_value
    sb = sb.field("optional_field", value);
}

let s = sb.build();
```

With `_if_some()`, this can be written like this:

```rust
let opt_value = ...;
let s = gst::Structure::builder("test")
    .field("mandatory_field", "mandatory")
    .field_if_some("optional_field", opt_value)
    .build();
```

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1424>
2024-04-17 17:15:39 +02:00

176 lines
5.2 KiB
Rust

// Take a look at the license at the top of the repository in the LICENSE file.
use std::ffi::CStr;
use glib::{prelude::*, translate::*};
use crate::{Caps, PadDirection, PadPresence, PadTemplate, StaticPadTemplate};
impl PadTemplate {
#[doc(alias = "gst_pad_template_new_from_static_pad_template_with_gtype")]
pub fn from_static_pad_template_with_gtype(
pad_template: &StaticPadTemplate,
pad_type: glib::types::Type,
) -> Result<PadTemplate, glib::BoolError> {
skip_assert_initialized!();
unsafe {
Option::<_>::from_glib_none(
ffi::gst_pad_template_new_from_static_pad_template_with_gtype(
mut_override(pad_template.to_glib_none().0),
pad_type.into_glib(),
),
)
.ok_or_else(|| glib::bool_error!("Failed to create PadTemplate"))
}
}
#[doc(alias = "gst_pad_template_get_caps")]
#[doc(alias = "get_caps")]
pub fn caps(&self) -> &Caps {
unsafe {
let templ = &*(self.as_ptr() as *const ffi::GstPadTemplate);
&*(&templ.caps as *const *mut ffi::GstCaps as *const Caps)
}
}
#[cfg(feature = "v1_18")]
#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
#[doc(alias = "gst_pad_template_get_documentation_caps")]
#[doc(alias = "get_documentation_caps")]
pub fn documentation_caps(&self) -> &Caps {
unsafe {
let templ = &*(self.as_ptr() as *const ffi::GstPadTemplate);
if !templ.ABI.abi.documentation_caps.is_null() {
&*(&templ.ABI.abi.documentation_caps as *const *mut ffi::GstCaps as *const Caps)
} else {
&*(&templ.caps as *const *mut ffi::GstCaps as *const Caps)
}
}
}
pub fn direction(&self) -> PadDirection {
unsafe {
let templ = &*(self.as_ptr() as *const ffi::GstPadTemplate);
from_glib(templ.direction)
}
}
pub fn gtype(&self) -> glib::types::Type {
unsafe {
let templ = &*(self.as_ptr() as *const ffi::GstPadTemplate);
from_glib(templ.ABI.abi.gtype)
}
}
#[doc(alias = "name-template")]
pub fn name_template(&self) -> &str {
unsafe {
let templ = &*(self.as_ptr() as *const ffi::GstPadTemplate);
CStr::from_ptr(templ.name_template).to_str().unwrap()
}
}
pub fn presence(&self) -> PadPresence {
unsafe {
let templ = &*(self.as_ptr() as *const ffi::GstPadTemplate);
from_glib(templ.presence)
}
}
pub fn builder<'a>(
name_template: &'a str,
direction: PadDirection,
presence: PadPresence,
caps: &'a Caps,
) -> PadTemplateBuilder<'a> {
skip_assert_initialized!();
PadTemplateBuilder {
name_template,
direction,
presence,
caps,
gtype: None,
#[cfg(feature = "v1_18")]
#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
documentation_caps: None,
}
}
}
#[must_use = "The builder must be built to be used"]
#[derive(Debug)]
pub struct PadTemplateBuilder<'a> {
name_template: &'a str,
direction: PadDirection,
presence: PadPresence,
caps: &'a Caps,
gtype: Option<glib::Type>,
#[cfg(feature = "v1_18")]
#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
documentation_caps: Option<&'a Caps>,
}
impl<'a> PadTemplateBuilder<'a> {
pub fn gtype(self, gtype: glib::Type) -> Self {
PadTemplateBuilder {
gtype: Some(gtype),
..self
}
}
pub fn gtype_if_some(self, gtype: Option<glib::Type>) -> Self {
if let Some(gtype) = gtype {
self.gtype(gtype)
} else {
self
}
}
#[cfg(feature = "v1_18")]
#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
pub fn documentation_caps(self, documentation_caps: &'a Caps) -> Self {
PadTemplateBuilder {
documentation_caps: Some(documentation_caps),
..self
}
}
#[cfg(feature = "v1_18")]
#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
pub fn documentation_caps_if_some(self, documentation_caps: Option<&'a Caps>) -> Self {
if let Some(documentation_caps) = documentation_caps {
self.documentation_caps(documentation_caps)
} else {
self
}
}
pub fn build(self) -> Result<PadTemplate, glib::BoolError> {
let templ = if let Some(gtype) = self.gtype {
PadTemplate::with_gtype(
self.name_template,
self.direction,
self.presence,
self.caps,
gtype,
)?
} else {
PadTemplate::new(self.name_template, self.direction, self.presence, self.caps)?
};
#[cfg(feature = "v1_18")]
#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
if let Some(documentation_caps) = self.documentation_caps {
unsafe {
ffi::gst_pad_template_set_documentation_caps(
templ.to_glib_none().0,
documentation_caps.to_glib_none().0,
);
}
}
Ok(templ)
}
}