diff --git a/examples/src/bin/rtsp-server-custom-auth.rs b/examples/src/bin/rtsp-server-custom-auth.rs index b1af7b9f2..324641258 100644 --- a/examples/src/bin/rtsp-server-custom-auth.rs +++ b/examples/src/bin/rtsp-server-custom-auth.rs @@ -138,7 +138,11 @@ mod auth { if let Some(authorization) = auth_credentials.authorization() { if let Some(user) = self.external_auth(authorization) { // Update context token with authenticated username - ctx.set_token(gst_rtsp_server::RTSPToken::new(&[("user", &user)])); + ctx.set_token( + gst_rtsp_server::RTSPToken::builder() + .field("user", user) + .build(), + ); return true; } } diff --git a/examples/src/bin/rtsp-server-record.rs b/examples/src/bin/rtsp-server-record.rs index e252b2408..5ab523ec7 100644 --- a/examples/src/bin/rtsp-server-record.rs +++ b/examples/src/bin/rtsp-server-record.rs @@ -45,10 +45,9 @@ fn main_loop() -> Result<(), Error> { // Here we configure a method of authentication that we want the // server to require from clients. let auth = gst_rtsp_server::RTSPAuth::new(); - let token = gst_rtsp_server::RTSPToken::new(&[( - gst_rtsp_server::RTSP_TOKEN_MEDIA_FACTORY_ROLE, - &"user", - )]); + let token = gst_rtsp_server::RTSPToken::builder() + .field(gst_rtsp_server::RTSP_TOKEN_MEDIA_FACTORY_ROLE, "user") + .build(); let basic = gst_rtsp_server::RTSPAuth::make_basic("user", "password"); // For proper authentication, we want to use encryption. And there's no // encryption without a certificate! diff --git a/gstreamer-rtsp-server/src/rtsp_token.rs b/gstreamer-rtsp-server/src/rtsp_token.rs index 0f0baef7d..dfbd65540 100644 --- a/gstreamer-rtsp-server/src/rtsp_token.rs +++ b/gstreamer-rtsp-server/src/rtsp_token.rs @@ -2,7 +2,7 @@ use std::fmt; -use glib::{translate::*, value::ToSendValue}; +use glib::{translate::*, SendValue}; gst::mini_object_wrapper!(RTSPToken, RTSPTokenRef, ffi::GstRTSPToken, || { ffi::gst_rtsp_token_get_type() @@ -15,18 +15,19 @@ impl RTSPToken { unsafe { from_glib_full(ffi::gst_rtsp_token_new_empty()) } } - pub fn new(values: &[(&str, &(dyn ToSendValue + Sync))]) -> Self { + #[doc(alias = "gst_rtsp_token_new")] + pub fn builder() -> Builder { + skip_assert_initialized!(); + Builder::new() + } + + #[allow(clippy::should_implement_trait)] + pub fn from_iter(iter: impl IntoIterator) -> RTSPToken { skip_assert_initialized!(); let mut token = RTSPToken::new_empty(); - { - let token = token.get_mut().unwrap(); - let structure = token.structure_mut(); - - for &(f, v) in values { - structure.set_value(f, v.to_send_value()); - } - } + let s = token.get_mut().unwrap().structure_mut(); + iter.into_iter().for_each(|(f, v)| s.set_value(f, v)); token } @@ -82,3 +83,32 @@ impl fmt::Debug for RTSPTokenRef { .finish() } } + +#[derive(Debug)] +#[must_use = "The builder must be built to be used"] +pub struct Builder { + token: RTSPToken, +} + +impl Builder { + fn new() -> Self { + skip_assert_initialized!(); + Builder { + token: RTSPToken::new_empty(), + } + } + + pub fn field(mut self, name: impl IntoGStr, value: impl Into + Send) -> Self { + self.token + .get_mut() + .unwrap() + .structure_mut() + .set(name, value); + self + } + + #[must_use = "Building the structure without using it has no effect"] + pub fn build(self) -> RTSPToken { + self.token + } +}