all: use builder conditional setters where applicable

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1926>
This commit is contained in:
François Laignel 2024-11-20 20:11:02 +01:00 committed by GStreamer Marge Bot
parent 4262a8aafe
commit a8146f333f
20 changed files with 140 additions and 183 deletions

View file

@ -27,9 +27,11 @@ fn start_consumer(producer_name: &str) -> gst_check::Harness {
} }
fn start_producer(producer_name: &str) -> (gst::Pad, gst::Element) { fn start_producer(producer_name: &str) -> (gst::Pad, gst::Element) {
let element = gst::ElementFactory::make("intersink").build().unwrap(); let element = gst::ElementFactory::make("intersink")
.property("producer-name", producer_name)
.build()
.unwrap();
element.set_property("producer-name", producer_name);
element.set_state(gst::State::Playing).unwrap(); element.set_state(gst::State::Playing).unwrap();
let sinkpad = element.static_pad("sink").unwrap(); let sinkpad = element.static_pad("sink").unwrap();

View file

@ -114,13 +114,10 @@ fn main() {
.property("port", 5004i32 + i as i32) .property("port", 5004i32 + i as i32)
.property("context", &context) .property("context", &context)
.property("context-wait", wait) .property("context-wait", wait)
.property_if("caps", &rtp_caps, is_rtp)
.build() .build()
.unwrap(); .unwrap();
if is_rtp {
source.set_property("caps", &rtp_caps);
}
(source, Some(context)) (source, Some(context))
} }
"tcpclientsrc" => { "tcpclientsrc" => {
@ -177,11 +174,9 @@ fn main() {
.name(format!("jb-{i}").as_str()) .name(format!("jb-{i}").as_str())
.property("context-wait", wait) .property("context-wait", wait)
.property("latency", wait) .property("latency", wait)
.property_if_some("context", context.as_ref())
.build() .build()
.unwrap(); .unwrap();
if let Some(context) = context {
jb.set_property("context", &context);
}
let elements = &[&source, &jb, &sink]; let elements = &[&source, &jb, &sink];
pipeline.add_many(elements).unwrap(); pipeline.add_many(elements).unwrap();

View file

@ -94,13 +94,10 @@ fn send_test_buffers(n_streams: u16, num_buffers: Option<i32>) {
.property("context-wait", 20u32) .property("context-wait", 20u32)
.property("is-live", true) .property("is-live", true)
.property("do-timestamp", true) .property("do-timestamp", true)
.property_if_some("num-buffers", num_buffers)
.build() .build()
.unwrap(); .unwrap();
if let Some(num_buffers) = num_buffers {
src.set_property("num-buffers", num_buffers);
}
#[cfg(feature = "tuning")] #[cfg(feature = "tuning")]
if i == 0 { if i == 0 {
src.set_property("main-elem", true); src.set_property("main-elem", true);
@ -129,13 +126,10 @@ fn send_rtp_buffers(n_streams: u16, num_buffers: Option<i32>) {
.property("context-wait", 20u32) .property("context-wait", 20u32)
.property("is-live", true) .property("is-live", true)
.property("do-timestamp", true) .property("do-timestamp", true)
.property_if_some("num-buffers", num_buffers)
.build() .build()
.unwrap(); .unwrap();
if let Some(num_buffers) = num_buffers {
src.set_property("num-buffers", num_buffers);
}
#[cfg(feature = "tuning")] #[cfg(feature = "tuning")]
if i == 0 { if i == 0 {
src.set_property("main-elem", true); src.set_property("main-elem", true);

View file

@ -715,9 +715,10 @@ fn setup(
// Sink // Sink
let (sender, receiver) = mpsc::channel::<Item>(10); let (sender, receiver) = mpsc::channel::<Item>(10);
let sink_element = glib::Object::builder::<ElementSinkTest>() let sink_element = gst::Object::builder::<ElementSinkTest>()
.property("sender", ItemSender { sender }) .property("sender", ItemSender { sender })
.build(); .build()
.unwrap();
pipeline.add(&sink_element).unwrap(); pipeline.add(&sink_element).unwrap();
last_element.link(&sink_element).unwrap(); last_element.link(&sink_element).unwrap();

View file

@ -922,14 +922,16 @@ impl ObjectSubclass for MpegTsLiveSource {
| gst::PadFlags::PROXY_SCHEDULING, | gst::PadFlags::PROXY_SCHEDULING,
) )
.build(); .build();
let internal_clock = glib::Object::builder::<gst::SystemClock>() let internal_clock = gst::Object::builder::<gst::SystemClock>()
.name("mpegts-internal-clock")
.property("clock-type", gst::ClockType::Monotonic) .property("clock-type", gst::ClockType::Monotonic)
.property("name", "mpegts-internal-clock") .build()
.build(); .unwrap();
let external_clock = glib::Object::builder::<gst::SystemClock>() let external_clock = gst::Object::builder::<gst::SystemClock>()
.name("mpegts-live-clock")
.property("clock-type", gst::ClockType::Monotonic) .property("clock-type", gst::ClockType::Monotonic)
.property("name", "mpegts-live-clock") .build()
.build(); .unwrap();
// Return an instance of our struct // Return an instance of our struct
Self { Self {
srcpad, srcpad,

View file

@ -212,11 +212,12 @@ impl GstObjectImpl for Device {}
impl DeviceImpl for Device { impl DeviceImpl for Device {
fn create_element(&self, name: Option<&str>) -> Result<gst::Element, gst::LoggableError> { fn create_element(&self, name: Option<&str>) -> Result<gst::Element, gst::LoggableError> {
let source_info = self.source.get().unwrap(); let source_info = self.source.get().unwrap();
let element = glib::Object::builder::<crate::ndisrc::NdiSrc>() let element = gst::Object::builder::<crate::ndisrc::NdiSrc>()
.property("name", name) .name_if_some(name)
.property("ndi-name", source_info.ndi_name()) .property("ndi-name", source_info.ndi_name())
.property("url-address", source_info.url_address()) .property("url-address", source_info.url_address())
.build() .build()
.unwrap()
.upcast::<gst::Element>(); .upcast::<gst::Element>();
Ok(element) Ok(element)
@ -239,12 +240,13 @@ impl super::Device {
.field("url-address", source.url_address()) .field("url-address", source.url_address())
.build(); .build();
let device = glib::Object::builder::<super::Device>() let device = gst::Object::builder::<super::Device>()
.property("caps", caps) .property("caps", caps)
.property("display-name", display_name) .property("display-name", display_name)
.property("device-class", device_class) .property("device-class", device_class)
.property("properties", extra_properties) .property("properties", extra_properties)
.build(); .build()
.unwrap();
let imp = device.imp(); let imp = device.imp();
imp.source.set(source.to_owned()).unwrap(); imp.source.set(source.to_owned()).unwrap();

View file

@ -448,9 +448,10 @@ impl ElementImpl for NdiSrc {
state.receiver = Some(receiver); state.receiver = Some(receiver);
state.timestamp_mode = settings.timestamp_mode; state.timestamp_mode = settings.timestamp_mode;
if state.timestamp_mode == TimestampMode::Clocked { if state.timestamp_mode == TimestampMode::Clocked {
let clock = glib::Object::builder::<gst::SystemClock>() let clock = gst::Object::builder::<gst::SystemClock>()
.property("name", format!("{}-clock", self.obj().name())) .name(format!("{}-clock", self.obj().name()))
.build() .build()
.unwrap()
.upcast::<gst::Clock>(); .upcast::<gst::Clock>();
state.clock_state = Some(ClockState { state.clock_state = Some(ClockState {
clock: clock.clone(), clock: clock.clone(),

View file

@ -238,18 +238,16 @@ impl NdiSrcDemux {
#[allow(irrefutable_let_patterns)] #[allow(irrefutable_let_patterns)]
if let AudioInfo::Audio(ref info) = info { if let AudioInfo::Audio(ref info) = info {
let mut builder = gst_audio::AudioInfo::builder( let non_interleaved_info = gst_audio::AudioInfo::builder(
info.format(), info.format(),
info.rate(), info.rate(),
info.channels(), info.channels(),
) )
.layout(gst_audio::AudioLayout::NonInterleaved); .layout(gst_audio::AudioLayout::NonInterleaved)
.positions_if_some(info.positions())
.build()
.unwrap();
if let Some(positions) = info.positions() {
builder = builder.positions(positions);
}
let non_interleaved_info = builder.build().unwrap();
state.audio_caps_non_interleaved = state.audio_caps_non_interleaved =
Some(non_interleaved_info.to_caps().unwrap()); Some(non_interleaved_info.to_caps().unwrap());
state.audio_info_non_interleaved = Some(non_interleaved_info); state.audio_info_non_interleaved = Some(non_interleaved_info);
@ -640,22 +638,21 @@ impl NdiSrcDemux {
// supported by GStreamer // supported by GStreamer
}; };
let mut builder = gst_video::VideoInfo::builder( let info = gst_video::VideoInfo::builder(
format, format,
video_frame.xres() as u32, video_frame.xres() as u32,
video_frame.yres() as u32, video_frame.yres() as u32,
) )
.fps(gst::Fraction::from(video_frame.frame_rate())) .fps(gst::Fraction::from(video_frame.frame_rate()))
.par(par) .par(par)
.interlace_mode(interlace_mode); .interlace_mode(interlace_mode)
.field_order_if(
if video_frame.frame_format_type() gst_video::VideoFieldOrder::TopFieldFirst,
== ndisys::NDIlib_frame_format_type_e::NDIlib_frame_format_type_interleaved video_frame.frame_format_type()
{ == ndisys::NDIlib_frame_format_type_e::NDIlib_frame_format_type_interleaved,
builder = builder.field_order(gst_video::VideoFieldOrder::TopFieldFirst); )
} .build()
.map_err(|_| {
return Ok(VideoInfo::Video(builder.build().map_err(|_| {
gst::element_imp_error!( gst::element_imp_error!(
self, self,
gst::StreamError::Format, gst::StreamError::Format,
@ -663,7 +660,9 @@ impl NdiSrcDemux {
); );
gst::FlowError::NotNegotiated gst::FlowError::NotNegotiated
})?)); })?;
return Ok(VideoInfo::Video(info));
} }
#[cfg(feature = "advanced-sdk")] #[cfg(feature = "advanced-sdk")]
@ -1211,14 +1210,14 @@ impl NdiSrcDemux {
); );
} }
let builder = gst_audio::AudioInfo::builder( let info = gst_audio::AudioInfo::builder(
gst_audio::AUDIO_FORMAT_F32, gst_audio::AUDIO_FORMAT_F32,
audio_frame.sample_rate() as u32, audio_frame.sample_rate() as u32,
channels, channels,
) )
.positions(&positions[..channels as usize]); .positions(&positions[..channels as usize])
.build()
let info = builder.build().map_err(|_| { .map_err(|_| {
gst::element_imp_error!( gst::element_imp_error!(
self, self,
gst::StreamError::Format, gst::StreamError::Format,

View file

@ -822,7 +822,7 @@ impl ElementImpl for RaptorqDec {
} }
let sinkpad_fec = gst::Pad::builder_from_template(templ) let sinkpad_fec = gst::Pad::builder_from_template(templ)
.maybe_name(name) .name_if_some(name)
.chain_function(|pad, parent, buffer| { .chain_function(|pad, parent, buffer| {
Self::catch_panic_pad_function( Self::catch_panic_pad_function(
parent, parent,

View file

@ -355,7 +355,7 @@ impl RtpBaseDepay2Impl for RtpJpegDepay {
|| state.dimensions != Some((width, height)) || state.dimensions != Some((width, height))
|| state.framerate != state.sdp_framerate || state.framerate != state.sdp_framerate
{ {
let mut caps_builder = gst::Caps::builder("image/jpeg") let caps = gst::Caps::builder("image/jpeg")
.field("parsed", true) .field("parsed", true)
.field("width", width) .field("width", width)
.field("height", height) .field("height", height)
@ -368,12 +368,9 @@ impl RtpBaseDepay2Impl for RtpJpegDepay {
} else { } else {
"YCbCr-4:2:0" "YCbCr-4:2:0"
}, },
); )
if let Some(framerate) = state.sdp_framerate { .field_if_some("framerate", state.sdp_framerate)
caps_builder = caps_builder.field("framerate", framerate); .build();
}
let caps = caps_builder.build();
gst::debug!(CAT, imp = self, "Setting caps {caps:?}"); gst::debug!(CAT, imp = self, "Setting caps {caps:?}");
self.obj().set_src_caps(&caps); self.obj().set_src_caps(&caps);
state.dimensions = Some((width, height)); state.dimensions = Some((width, height));

View file

@ -291,9 +291,10 @@ fn test_opus_payloader_get_caps() {
fn get_allowed_opus_caps_for_rtp_caps_string(recv_caps_str: &str) -> gst::Caps { fn get_allowed_opus_caps_for_rtp_caps_string(recv_caps_str: &str) -> gst::Caps {
let src = gst::ElementFactory::make("appsrc").build().unwrap(); let src = gst::ElementFactory::make("appsrc").build().unwrap();
let pay = gst::ElementFactory::make("rtpopuspay2").build().unwrap(); let pay = gst::ElementFactory::make("rtpopuspay2").build().unwrap();
let sink = gst::ElementFactory::make("appsink").build().unwrap(); let sink = gst::ElementFactory::make("appsink")
.property_from_str("caps", recv_caps_str)
sink.set_property_from_str("caps", recv_caps_str); .build()
.unwrap();
gst::Element::link_many([&src, &pay, &sink]).unwrap(); gst::Element::link_many([&src, &pay, &sink]).unwrap();

View file

@ -125,23 +125,18 @@ fn spawn_consumer(
pipeline.add(&bin).context("Adding consumer bin")?; pipeline.add(&bin).context("Adding consumer bin")?;
let webrtcsrc = gst::ElementFactory::make("webrtcsrc") let webrtcsrc = gst::ElementFactory::make("webrtcsrc")
.build() .name(
.context("Creating webrtcsrc")?; meta.as_ref()
.map_or_else(|| peer_id.clone(), serde_json::Value::to_string),
if args.expect_clock_signalling { )
// Discard retransmission in RFC 7273 mode. See: // Discard retransmission in RFC 7273 mode. See:
// * https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/issues/914 // * https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/issues/914
// * https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1574 // * https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1574
webrtcsrc.set_property("do-retransmission", false); .property_if("do-retransmission", false, args.expect_clock_signalling)
} .property_if_not_empty::<gst::Array>("audio-codecs", &args.audio_codecs)
.property_if_not_empty::<gst::Array>("video-codecs", &args.video_codecs)
if !args.audio_codecs.is_empty() { .build()
webrtcsrc.set_property("audio-codecs", gst::Array::new(&args.audio_codecs)); .context("Creating webrtcsrc")?;
}
if !args.video_codecs.is_empty() {
webrtcsrc.set_property("video-codecs", gst::Array::new(&args.video_codecs));
}
bin.add(&webrtcsrc).context("Adding webrtcsrc")?; bin.add(&webrtcsrc).context("Adding webrtcsrc")?;

View file

@ -10,15 +10,13 @@ struct Args {
} }
fn link_video(pad: &gst::Pad, pipeline: &gst::Pipeline) { fn link_video(pad: &gst::Pad, pipeline: &gst::Pipeline) {
let q = gst::ElementFactory::make_with_name( let q = gst::ElementFactory::make("queue")
"queue", .name(format!("queue_{}", pad.name()))
Some(format!("queue_{}", pad.name()).as_str()), .build()
)
.unwrap(); .unwrap();
let vsink = gst::ElementFactory::make_with_name( let vsink = gst::ElementFactory::make("autovideosink")
"autovideosink", .name(format!("vsink_{}", pad.name()))
Some(format!("vsink_{}", pad.name()).as_str()), .build()
)
.unwrap(); .unwrap();
pipeline.add_many([&q, &vsink]).unwrap(); pipeline.add_many([&q, &vsink]).unwrap();
@ -45,16 +43,14 @@ fn unlink_video(pad: &gst::Pad, pipeline: &gst::Pipeline) {
} }
fn link_audio(pad: &gst::Pad, pipeline: &gst::Pipeline) { fn link_audio(pad: &gst::Pad, pipeline: &gst::Pipeline) {
let aq = gst::ElementFactory::make_with_name( let aq = gst::ElementFactory::make("queue")
"queue", .name(format!("aqueue_{}", pad.name()))
Some(format!("aqueue_{}", pad.name()).as_str()), .build()
)
.unwrap(); .unwrap();
let asink = gst::ElementFactory::make_with_name( let asink = gst::ElementFactory::make("autoaudiosink")
"autoaudiosink", .name(format!("asink_{}", pad.name()))
Some(format!("asink_{}", pad.name()).as_str()), .build()
)
.unwrap(); .unwrap();
pipeline.add_many([&aq, &asink]).unwrap(); pipeline.add_many([&aq, &asink]).unwrap();

View file

@ -402,12 +402,8 @@ pub fn build_link_header(url_str: &str) -> Result<String, url::ParseError> {
/// Wrapper around `gst::ElementFactory::make` with a better error /// Wrapper around `gst::ElementFactory::make` with a better error
/// message /// message
pub fn make_element(element: &str, name: Option<&str>) -> Result<gst::Element, Error> { pub fn make_element(element: &str, name: Option<&str>) -> Result<gst::Element, Error> {
let mut builder = gst::ElementFactory::make(element); gst::ElementFactory::make(element)
if let Some(name) = name { .name_if_some(name)
builder = builder.name(name);
}
builder
.build() .build()
.with_context(|| format!("Failed to make element {element}")) .with_context(|| format!("Failed to make element {element}"))
} }

View file

@ -128,13 +128,11 @@ impl State {
let mut events = Vec::new(); let mut events = Vec::new();
if self.need_flush_stop { if self.need_flush_stop {
let mut b = gst::event::FlushStop::builder(true); events.push(
gst::event::FlushStop::builder(true)
if let Some(seek_seqnum) = self.seek_seqnum { .seqnum_if_some(self.seek_seqnum)
b = b.seqnum(seek_seqnum); .build(),
} );
events.push(b.build());
self.need_flush_stop = false; self.need_flush_stop = false;
} }
@ -146,13 +144,9 @@ impl State {
} }
if self.need_caps { if self.need_caps {
let mut caps_builder = gst::Caps::builder("application/x-json"); let caps = gst::Caps::builder("application/x-json")
.field_if_some("format", self.format.as_ref())
if let Some(format) = &self.format { .build();
caps_builder = caps_builder.field("format", format);
}
let caps = caps_builder.build();
events.push(gst::event::Caps::new(&caps)); events.push(gst::event::Caps::new(&caps));
gst::info!(CAT, imp = imp, "Caps changed to {:?}", &caps); gst::info!(CAT, imp = imp, "Caps changed to {:?}", &caps);
@ -160,13 +154,11 @@ impl State {
} }
if self.need_segment { if self.need_segment {
let mut b = gst::event::Segment::builder(&self.segment); events.push(
gst::event::Segment::builder(&self.segment)
if let Some(seek_seqnum) = self.seek_seqnum { .seqnum_if_some(self.seek_seqnum)
b = b.seqnum(seek_seqnum); .build(),
} );
events.push(b.build());
self.need_segment = false; self.need_segment = false;
} }
@ -486,13 +478,11 @@ impl JsonGstParse {
} }
let mut events = state.create_events(self); let mut events = state.create_events(self);
let mut eos_event = gst::event::Eos::builder(); events.push(
gst::event::Eos::builder()
if let Some(seek_seqnum) = state.seek_seqnum { .seqnum_if_some(state.seek_seqnum)
eos_event = eos_event.seqnum(seek_seqnum); .build(),
} );
events.push(eos_event.build());
// Drop our state mutex while we push out events // Drop our state mutex while we push out events
drop(state); drop(state);

View file

@ -16,6 +16,9 @@ glib::wrapper! {
impl CustomSource { impl CustomSource {
pub fn new(source: &gst::Element) -> CustomSource { pub fn new(source: &gst::Element) -> CustomSource {
glib::Object::builder().property("source", source).build() gst::Object::builder()
.property("source", source)
.build()
.unwrap()
} }
} }

View file

@ -492,16 +492,11 @@ fn setup_pipeline(
let switch = gst::ElementFactory::make("fallbackswitch") let switch = gst::ElementFactory::make("fallbackswitch")
.name("switch") .name("switch")
.property("timeout", 3.seconds()) .property("timeout", 3.seconds())
.property_if_some("immediate-fallback", immediate_fallback)
.property_if_some("auto-switch", auto_switch)
.build() .build()
.unwrap(); .unwrap();
if let Some(imm) = immediate_fallback {
switch.set_property("immediate-fallback", imm);
}
if let Some(auto_switch) = auto_switch {
switch.set_property("auto-switch", auto_switch);
}
let sink = gst_app::AppSink::builder().name("sink").sync(false).build(); let sink = gst_app::AppSink::builder().name("sink").sync(false).build();
let queue = gst::ElementFactory::make("queue").build().unwrap(); let queue = gst::ElementFactory::make("queue").build().unwrap();

View file

@ -251,13 +251,11 @@ impl State {
let mut events = Vec::new(); let mut events = Vec::new();
if self.need_flush_stop { if self.need_flush_stop {
let mut b = gst::event::FlushStop::builder(true); events.push(
gst::event::FlushStop::builder(true)
if let Some(seek_seqnum) = self.seek_seqnum { .seqnum_if_some(self.seek_seqnum)
b = b.seqnum(seek_seqnum); .build(),
} );
events.push(b.build());
self.need_flush_stop = false; self.need_flush_stop = false;
} }
@ -289,13 +287,11 @@ impl State {
} }
if self.need_segment { if self.need_segment {
let mut b = gst::event::Segment::builder(&self.segment); events.push(
gst::event::Segment::builder(&self.segment)
if let Some(seek_seqnum) = self.seek_seqnum { .seqnum_if_some(self.seek_seqnum)
b = b.seqnum(seek_seqnum); .build(),
} );
events.push(b.build());
self.need_segment = false; self.need_segment = false;
} }
@ -695,13 +691,11 @@ impl MccParse {
match parse_timecode_rate(state.timecode_rate) { match parse_timecode_rate(state.timecode_rate) {
Ok((framerate, _)) => { Ok((framerate, _)) => {
let mut events = state.create_events(self, None, framerate); let mut events = state.create_events(self, None, framerate);
let mut eos_event = gst::event::Eos::builder(); events.push(
gst::event::Eos::builder()
if let Some(seek_seqnum) = state.seek_seqnum { .seqnum_if_some(state.seek_seqnum)
eos_event = eos_event.seqnum(seek_seqnum); .build(),
} );
events.push(eos_event.build());
// Drop our state mutex while we push out events // Drop our state mutex while we push out events
drop(state); drop(state);

View file

@ -219,13 +219,11 @@ impl State {
let mut events = Vec::new(); let mut events = Vec::new();
if self.need_flush_stop { if self.need_flush_stop {
let mut b = gst::event::FlushStop::builder(true); events.push(
gst::event::FlushStop::builder(true)
if let Some(seek_seqnum) = self.seek_seqnum { .seqnum_if_some(self.seek_seqnum)
b = b.seqnum(seek_seqnum); .build(),
} );
events.push(b.build());
self.need_flush_stop = false; self.need_flush_stop = false;
} }
@ -252,13 +250,11 @@ impl State {
} }
if self.need_segment { if self.need_segment {
let mut b = gst::event::Segment::builder(&self.segment); events.push(
gst::event::Segment::builder(&self.segment)
if let Some(seek_seqnum) = self.seek_seqnum { .seqnum_if_some(self.seek_seqnum)
b = b.seqnum(seek_seqnum); .build(),
} );
events.push(b.build());
self.need_segment = false; self.need_segment = false;
} }
@ -608,13 +604,11 @@ impl SccParse {
} }
let mut events = state.create_events(self, None); let mut events = state.create_events(self, None);
let mut eos_event = gst::event::Eos::builder(); events.push(
gst::event::Eos::builder()
if let Some(seek_seqnum) = state.seek_seqnum { .seqnum_if_some(state.seek_seqnum)
eos_event = eos_event.seqnum(seek_seqnum); .build(),
} );
events.push(eos_event.build());
// Drop our state mutex while we push out events // Drop our state mutex while we push out events
drop(state); drop(state);

View file

@ -55,7 +55,7 @@ glib::wrapper! {
impl PaintableSink { impl PaintableSink {
pub fn new(name: Option<&str>) -> Self { pub fn new(name: Option<&str>) -> Self {
glib::Object::builder().property("name", name).build() gst::Object::builder().name_if_some(name).build().unwrap()
} }
} }