Skip to main content

sdp_types/
builders.rs

1// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>
2
3//! Builders for the `sdp_types` `struct`s
4
5use crate::{attributes, clock_signalling, enums};
6use std::net::IpAddr;
7
8/// A [`crate::Origin`] builder.
9#[derive(Debug)]
10pub struct Origin(crate::Origin);
11impl Origin {
12    /// Construct an [`crate::builders::Origin`] with the specified IP `unicast_address`
13    pub fn with_ip_addr(
14        sess_id: impl ToString,
15        sess_version: u64,
16        unicast_address: impl Into<IpAddr>,
17    ) -> Self {
18        Self(crate::Origin::with_ip_addr(
19            sess_id,
20            sess_version,
21            unicast_address,
22        ))
23    }
24
25    /// Construct an [`crate::builders::Origin`]
26    ///
27    /// See also [`crate::Origin::builder_with_ip_addr`]
28    pub fn new(
29        sess_id: impl ToString,
30        sess_version: u64,
31        nettype: enums::NetType,
32        addrtype: enums::AddrType,
33        unicast_address: impl ToString,
34    ) -> Self {
35        Self(crate::Origin::new(
36            sess_id,
37            sess_version,
38            nettype,
39            addrtype,
40            unicast_address,
41        ))
42    }
43
44    pub fn username(mut self, username: impl ToString) -> Self {
45        self.0.set_username(username);
46        self
47    }
48
49    pub fn username_if(mut self, username: impl ToString, predicate: bool) -> Self {
50        if predicate {
51            self.0.set_username(username);
52        }
53        self
54    }
55
56    pub fn username_if_some(mut self, username: Option<impl ToString>) -> Self {
57        if let Some(username) = username {
58            self.0.set_username(username);
59        }
60        self
61    }
62
63    pub fn build(self) -> crate::Origin {
64        self.0
65    }
66}
67
68/// A [`crate::Origin`] builder.
69#[derive(Debug)]
70pub struct Time(crate::Time);
71impl Time {
72    pub fn new(start_time: u64, stop_time: u64) -> Self {
73        Self(crate::Time::new(start_time, stop_time))
74    }
75
76    pub fn repeat(mut self, repeat: crate::Repeat) -> Self {
77        self.0.add_repeat(repeat);
78        self
79    }
80
81    pub fn repeat_if(mut self, repeat: crate::Repeat, predicate: bool) -> Self {
82        if predicate {
83            self.0.add_repeat(repeat);
84        }
85        self
86    }
87
88    pub fn repeat_if_some(mut self, repeat: Option<crate::Repeat>) -> Self {
89        if let Some(repeat) = repeat {
90            self.0.add_repeat(repeat);
91        }
92        self
93    }
94
95    pub fn repeats(mut self, repeats: impl IntoIterator<Item = crate::Repeat>) -> Self {
96        self.0.add_repeats(repeats);
97        self
98    }
99
100    pub fn repeats_if(
101        mut self,
102        repeats: impl IntoIterator<Item = crate::Repeat>,
103        predicate: bool,
104    ) -> Self {
105        if predicate {
106            self.0.add_repeats(repeats);
107        }
108        self
109    }
110
111    pub fn build(self) -> crate::Time {
112        self.0
113    }
114}
115
116/// A [`crate::Repeat`] builder.
117#[derive(Debug)]
118pub struct Repeat(crate::Repeat);
119impl Repeat {
120    pub fn new(repeat_interval: u64, active_duration: u64) -> Self {
121        Self(crate::Repeat::new(repeat_interval, active_duration))
122    }
123
124    pub fn offset(mut self, repeat: u64) -> Self {
125        self.0.add_offset(repeat);
126        self
127    }
128
129    pub fn offset_if(mut self, offset: u64, predicate: bool) -> Self {
130        if predicate {
131            self.0.add_offset(offset);
132        }
133        self
134    }
135
136    pub fn offset_if_some(mut self, offset: Option<u64>) -> Self {
137        if let Some(offset) = offset {
138            self.0.add_offset(offset);
139        }
140        self
141    }
142
143    pub fn offsets(mut self, offsets: impl IntoIterator<Item = u64>) -> Self {
144        self.0.add_offsets(offsets);
145        self
146    }
147
148    pub fn offsets_if(mut self, offsets: impl IntoIterator<Item = u64>, predicate: bool) -> Self {
149        if predicate {
150            self.0.add_offsets(offsets);
151        }
152        self
153    }
154
155    pub fn build(self) -> crate::Repeat {
156        self.0
157    }
158}
159
160/// A [`crate::Media`] builder.
161#[derive(Debug)]
162pub struct Media(crate::Media);
163impl Media {
164    pub fn new(
165        media: enums::MediaType,
166        port: u16,
167        proto: enums::TransportProto,
168        fmt: impl ToString,
169    ) -> Self {
170        Self(crate::Media::new(media, port, proto, fmt))
171    }
172
173    pub fn num_ports(mut self, num_ports: u16) -> Self {
174        self.0.set_num_ports(num_ports);
175        self
176    }
177
178    pub fn num_ports_if(mut self, num_ports: u16, predicate: bool) -> Self {
179        if predicate {
180            self.0.set_num_ports(num_ports);
181        }
182        self
183    }
184
185    pub fn num_ports_if_some(mut self, num_ports: Option<u16>) -> Self {
186        if let Some(num_ports) = num_ports {
187            self.0.set_num_ports(num_ports);
188        }
189        self
190    }
191
192    pub fn media_title(mut self, media_title: impl ToString) -> Self {
193        self.0.set_media_title(media_title);
194        self
195    }
196
197    pub fn media_title_if(mut self, media_title: impl ToString, predicate: bool) -> Self {
198        if predicate {
199            self.0.set_media_title(media_title);
200        }
201        self
202    }
203
204    pub fn media_title_if_some(mut self, media_title: Option<impl ToString>) -> Self {
205        if let Some(media_title) = media_title {
206            self.0.set_media_title(media_title);
207        }
208        self
209    }
210
211    pub fn connection(mut self, connection: impl Into<crate::Connection>) -> Self {
212        self.0.add_connection(connection);
213        self
214    }
215
216    pub fn connection_if(
217        mut self,
218        connection: impl Into<crate::Connection>,
219        predicate: bool,
220    ) -> Self {
221        if predicate {
222            self.0.add_connection(connection);
223        }
224        self
225    }
226
227    pub fn connection_if_some(mut self, connection: Option<impl Into<crate::Connection>>) -> Self {
228        if let Some(connection) = connection {
229            self.0.add_connection(connection);
230        }
231        self
232    }
233
234    pub fn connections(
235        mut self,
236        connections: impl IntoIterator<Item = impl Into<crate::Connection>>,
237    ) -> Self {
238        self.0.add_connections(connections);
239        self
240    }
241
242    pub fn connections_if(
243        mut self,
244        connections: impl IntoIterator<Item = impl Into<crate::Connection>>,
245        predicate: bool,
246    ) -> Self {
247        if predicate {
248            self.0.add_connections(connections);
249        }
250        self
251    }
252
253    pub fn bandwidth(mut self, bandwidth: crate::Bandwidth) -> Self {
254        self.0.add_bandwidth(bandwidth);
255        self
256    }
257
258    pub fn bandwidth_if(mut self, bandwidth: crate::Bandwidth, predicate: bool) -> Self {
259        if predicate {
260            self.0.add_bandwidth(bandwidth);
261        }
262        self
263    }
264
265    pub fn bandwidth_if_some(mut self, bandwidth: Option<crate::Bandwidth>) -> Self {
266        if let Some(bandwidth) = bandwidth {
267            self.0.add_bandwidth(bandwidth);
268        }
269        self
270    }
271
272    pub fn bandwidths(mut self, bandwidths: impl IntoIterator<Item = crate::Bandwidth>) -> Self {
273        self.0.add_bandwidths(bandwidths);
274        self
275    }
276
277    pub fn bandwidths_if(
278        mut self,
279        bandwidths: impl IntoIterator<Item = crate::Bandwidth>,
280        predicate: bool,
281    ) -> Self {
282        if predicate {
283            self.0.add_bandwidths(bandwidths);
284        }
285        self
286    }
287
288    pub fn encryption_key(mut self, key: impl Into<crate::Key>) -> Self {
289        self.0.set_encryption_key(key);
290        self
291    }
292
293    pub fn encryption_key_if(
294        mut self,
295        encryption_key: impl Into<crate::Key>,
296        predicate: bool,
297    ) -> Self {
298        if predicate {
299            self.0.set_encryption_key(encryption_key);
300        }
301        self
302    }
303
304    pub fn encryption_key_if_some(mut self, encryption_key: Option<impl Into<crate::Key>>) -> Self {
305        if let Some(encryption_key) = encryption_key {
306            self.0.set_encryption_key(encryption_key);
307        }
308        self
309    }
310
311    pub fn attribute(mut self, attribute: impl Into<crate::Attribute>) -> Self {
312        self.0.add_attribute(attribute);
313        self
314    }
315
316    pub fn attribute_if(mut self, attribute: impl Into<crate::Attribute>, predicate: bool) -> Self {
317        if predicate {
318            self.0.add_attribute(attribute);
319        }
320        self
321    }
322
323    pub fn attribute_if_some(mut self, attribute: Option<impl Into<crate::Attribute>>) -> Self {
324        if let Some(attribute) = attribute {
325            self.0.add_attribute(attribute);
326        }
327        self
328    }
329
330    pub fn attribute_from_str(mut self, attribute: impl ToString) -> Self {
331        self.0.add_attribute_from_str(attribute);
332        self
333    }
334
335    pub fn attribute_from_str_if(mut self, attribute: impl ToString, predicate: bool) -> Self {
336        if predicate {
337            self.0.add_attribute_from_str(attribute);
338        }
339        self
340    }
341
342    pub fn attribute_from_str_if_some(mut self, attribute: Option<impl ToString>) -> Self {
343        if let Some(attribute) = attribute {
344            self.0.add_attribute_from_str(attribute);
345        }
346        self
347    }
348
349    pub fn attribute_with_value(mut self, attribute: impl ToString, value: impl ToString) -> Self {
350        self.0.add_attribute_with_value(attribute, value);
351        self
352    }
353
354    pub fn attribute_with_value_if(
355        mut self,
356        attribute: impl ToString,
357        value: impl ToString,
358        predicate: bool,
359    ) -> Self {
360        if predicate {
361            self.0.add_attribute_with_value(attribute, value);
362        }
363        self
364    }
365
366    pub fn attribute_with_value_if_some(
367        mut self,
368        attribute: impl ToString,
369        value: Option<impl ToString>,
370    ) -> Self {
371        if let Some(value) = value {
372            self.0.add_attribute_with_value(attribute, value);
373        }
374        self
375    }
376
377    pub fn attributes(
378        mut self,
379        attributes: impl IntoIterator<Item = impl Into<crate::Attribute>>,
380    ) -> Self {
381        self.0.add_attributes(attributes);
382        self
383    }
384
385    pub fn attributes_if(
386        mut self,
387        attributes: impl IntoIterator<Item = impl Into<crate::Attribute>>,
388        predicate: bool,
389    ) -> Self {
390        if predicate {
391            self.0.add_attributes(attributes);
392        }
393        self
394    }
395
396    pub fn attributes_from_strs(
397        mut self,
398        attributes: impl IntoIterator<Item = impl ToString>,
399    ) -> Self {
400        self.0.add_attributes_from_strs(attributes);
401        self
402    }
403
404    pub fn attributes_from_strs_if(
405        mut self,
406        attributes: impl IntoIterator<Item = impl ToString>,
407        predicate: bool,
408    ) -> Self {
409        if predicate {
410            self.0.add_attributes_from_strs(attributes);
411        }
412        self
413    }
414
415    pub fn attributes_from_strs_if_some(
416        mut self,
417        attributes: Option<impl IntoIterator<Item = impl ToString>>,
418    ) -> Self {
419        if let Some(attributes) = attributes {
420            self.0.add_attributes_from_strs(attributes);
421        }
422        self
423    }
424
425    pub fn build(self) -> crate::Media {
426        self.0
427    }
428}
429
430/// A [`crate::Session`] builder.
431#[derive(Debug)]
432pub struct Session(crate::Session);
433impl Session {
434    pub fn new(origin: crate::Origin, session_name: impl ToString) -> Self {
435        Self(crate::Session::new(origin, session_name))
436    }
437
438    pub fn session_description(mut self, session_description: impl ToString) -> Self {
439        self.0.set_session_description(session_description);
440        self
441    }
442
443    pub fn session_description_if(
444        mut self,
445        session_description: impl ToString,
446        predicate: bool,
447    ) -> Self {
448        if predicate {
449            self.0.set_session_description(session_description);
450        }
451        self
452    }
453
454    pub fn session_description_if_some(
455        mut self,
456        session_description: Option<impl ToString>,
457    ) -> Self {
458        if let Some(session_description) = session_description {
459            self.0.set_session_description(session_description);
460        }
461        self
462    }
463
464    pub fn uri(mut self, uri: impl ToString) -> Self {
465        self.0.set_uri(uri);
466        self
467    }
468
469    pub fn uri_if(mut self, uri: impl ToString, predicate: bool) -> Self {
470        if predicate {
471            self.0.set_uri(uri);
472        }
473        self
474    }
475
476    pub fn uri_if_some(mut self, uri: Option<impl ToString>) -> Self {
477        if let Some(uri) = uri {
478            self.0.set_uri(uri);
479        }
480        self
481    }
482
483    pub fn email(mut self, email: impl ToString) -> Self {
484        self.0.add_email(email);
485        self
486    }
487
488    pub fn email_if(mut self, email: impl ToString, predicate: bool) -> Self {
489        if predicate {
490            self.0.add_email(email);
491        }
492        self
493    }
494
495    pub fn email_if_some(mut self, email: Option<impl ToString>) -> Self {
496        if let Some(email) = email {
497            self.0.add_email(email);
498        }
499        self
500    }
501
502    pub fn emails(mut self, emails: impl IntoIterator<Item = impl ToString>) -> Self {
503        self.0.add_emails(emails);
504        self
505    }
506
507    pub fn emails_if(
508        mut self,
509        emails: impl IntoIterator<Item = impl ToString>,
510        predicate: bool,
511    ) -> Self {
512        if predicate {
513            self.0.add_emails(emails);
514        }
515        self
516    }
517
518    pub fn phone(mut self, phone: impl ToString) -> Self {
519        self.0.add_phone(phone);
520        self
521    }
522
523    pub fn phone_if(mut self, phone: impl ToString, predicate: bool) -> Self {
524        if predicate {
525            self.0.add_phone(phone);
526        }
527        self
528    }
529
530    pub fn phone_if_some(mut self, phone: Option<impl ToString>) -> Self {
531        if let Some(phone) = phone {
532            self.0.add_phone(phone);
533        }
534        self
535    }
536
537    pub fn phones(mut self, phones: impl IntoIterator<Item = impl ToString>) -> Self {
538        self.0.add_phones(phones);
539        self
540    }
541
542    pub fn phones_if(
543        mut self,
544        phones: impl IntoIterator<Item = impl ToString>,
545        predicate: bool,
546    ) -> Self {
547        if predicate {
548            self.0.add_phones(phones);
549        }
550        self
551    }
552
553    pub fn connection(mut self, connection: impl Into<crate::Connection>) -> Self {
554        self.0.set_connection(connection);
555        self
556    }
557
558    pub fn connection_if(
559        mut self,
560        connection: impl Into<crate::Connection>,
561        predicate: bool,
562    ) -> Self {
563        if predicate {
564            self.0.set_connection(connection);
565        }
566        self
567    }
568
569    pub fn connection_if_some(mut self, connection: Option<impl Into<crate::Connection>>) -> Self {
570        if let Some(connection) = connection {
571            self.0.set_connection(connection);
572        }
573        self
574    }
575
576    pub fn bandwidth(mut self, bandwidth: crate::Bandwidth) -> Self {
577        self.0.add_bandwidth(bandwidth);
578        self
579    }
580
581    pub fn bandwidth_if(mut self, bandwidth: crate::Bandwidth, predicate: bool) -> Self {
582        if predicate {
583            self.0.add_bandwidth(bandwidth);
584        }
585        self
586    }
587
588    pub fn bandwidth_if_some(mut self, bandwidth: Option<crate::Bandwidth>) -> Self {
589        if let Some(bandwidth) = bandwidth {
590            self.0.add_bandwidth(bandwidth);
591        }
592        self
593    }
594
595    pub fn bandwidths(mut self, bandwidths: impl IntoIterator<Item = crate::Bandwidth>) -> Self {
596        self.0.add_bandwidths(bandwidths);
597        self
598    }
599
600    pub fn bandwidths_if(
601        mut self,
602        bandwidths: impl IntoIterator<Item = crate::Bandwidth>,
603        predicate: bool,
604    ) -> Self {
605        if predicate {
606            self.0.add_bandwidths(bandwidths);
607        }
608        self
609    }
610
611    pub fn time(mut self, time: crate::Time) -> Self {
612        self.0.add_time(time);
613        self
614    }
615
616    pub fn time_if(mut self, time: crate::Time, predicate: bool) -> Self {
617        if predicate {
618            self.0.add_time(time);
619        }
620        self
621    }
622
623    pub fn time_if_some(mut self, time: Option<crate::Time>) -> Self {
624        if let Some(time) = time {
625            self.0.add_time(time);
626        }
627        self
628    }
629
630    pub fn times(mut self, times: impl IntoIterator<Item = crate::Time>) -> Self {
631        self.0.add_times(times);
632        self
633    }
634
635    pub fn times_if(
636        mut self,
637        times: impl IntoIterator<Item = crate::Time>,
638        predicate: bool,
639    ) -> Self {
640        if predicate {
641            self.0.add_times(times);
642        }
643        self
644    }
645
646    pub fn times_if_some(mut self, times: Option<impl IntoIterator<Item = crate::Time>>) -> Self {
647        if let Some(times) = times {
648            self.0.add_times(times);
649        }
650        self
651    }
652
653    pub fn time_zone(mut self, time_zone: crate::TimeZone) -> Self {
654        self.0.add_time_zone(time_zone);
655        self
656    }
657
658    pub fn time_zone_if(mut self, time_zone: crate::TimeZone, predicate: bool) -> Self {
659        if predicate {
660            self.0.add_time_zone(time_zone);
661        }
662        self
663    }
664
665    pub fn time_zone_if_some(mut self, time_zone: Option<crate::TimeZone>) -> Self {
666        if let Some(time_zone) = time_zone {
667            self.0.add_time_zone(time_zone);
668        }
669        self
670    }
671
672    pub fn time_zones(mut self, time_zones: impl IntoIterator<Item = crate::TimeZone>) -> Self {
673        self.0.add_time_zones(time_zones);
674        self
675    }
676
677    pub fn time_zones_if(
678        mut self,
679        time_zones: impl IntoIterator<Item = crate::TimeZone>,
680        predicate: bool,
681    ) -> Self {
682        if predicate {
683            self.0.add_time_zones(time_zones);
684        }
685        self
686    }
687
688    pub fn encryption_key(mut self, key: impl Into<crate::Key>) -> Self {
689        self.0.set_encryption_key(key);
690        self
691    }
692
693    pub fn encryption_key_if(
694        mut self,
695        encryption_key: impl Into<crate::Key>,
696        predicate: bool,
697    ) -> Self {
698        if predicate {
699            self.0.set_encryption_key(encryption_key);
700        }
701        self
702    }
703
704    pub fn encryption_key_if_some(mut self, encryption_key: Option<impl Into<crate::Key>>) -> Self {
705        if let Some(encryption_key) = encryption_key {
706            self.0.set_encryption_key(encryption_key);
707        }
708        self
709    }
710
711    pub fn attribute(mut self, attribute: impl Into<crate::Attribute>) -> Self {
712        self.0.add_attribute(attribute);
713        self
714    }
715
716    pub fn attribute_if(mut self, attribute: impl Into<crate::Attribute>, predicate: bool) -> Self {
717        if predicate {
718            self.0.add_attribute(attribute);
719        }
720        self
721    }
722
723    pub fn attribute_if_some(mut self, attribute: Option<impl Into<crate::Attribute>>) -> Self {
724        if let Some(attribute) = attribute {
725            self.0.add_attribute(attribute);
726        }
727        self
728    }
729
730    pub fn attribute_from_str(mut self, attribute: impl ToString) -> Self {
731        self.0.add_attribute_from_str(attribute);
732        self
733    }
734
735    pub fn attribute_from_str_if(mut self, attribute: impl ToString, predicate: bool) -> Self {
736        if predicate {
737            self.0.add_attribute_from_str(attribute);
738        }
739        self
740    }
741
742    pub fn attribute_from_str_if_some(mut self, attribute: Option<impl ToString>) -> Self {
743        if let Some(attribute) = attribute {
744            self.0.add_attribute_from_str(attribute);
745        }
746        self
747    }
748
749    pub fn attribute_with_value(mut self, attribute: impl ToString, value: impl ToString) -> Self {
750        self.0.add_attribute_with_value(attribute, value);
751        self
752    }
753
754    pub fn attribute_with_value_if(
755        mut self,
756        attribute: impl ToString,
757        value: impl ToString,
758        predicate: bool,
759    ) -> Self {
760        if predicate {
761            self.0.add_attribute_with_value(attribute, value);
762        }
763        self
764    }
765
766    pub fn attribute_with_value_if_some(
767        mut self,
768        attribute: impl ToString,
769        value: Option<impl ToString>,
770    ) -> Self {
771        if let Some(value) = value {
772            self.0.add_attribute_with_value(attribute, value);
773        }
774        self
775    }
776
777    pub fn attributes(
778        mut self,
779        attributes: impl IntoIterator<Item = impl Into<crate::Attribute>>,
780    ) -> Self {
781        self.0.add_attributes(attributes);
782        self
783    }
784
785    pub fn attributes_if(
786        mut self,
787        attributes: impl IntoIterator<Item = impl Into<crate::Attribute>>,
788        predicate: bool,
789    ) -> Self {
790        if predicate {
791            self.0.add_attributes(attributes);
792        }
793        self
794    }
795
796    pub fn attributes_if_some(
797        mut self,
798        attributes: Option<impl IntoIterator<Item = impl Into<crate::Attribute>>>,
799    ) -> Self {
800        if let Some(attributes) = attributes {
801            self.0.add_attributes(attributes);
802        }
803        self
804    }
805
806    pub fn attributes_from_strs(
807        mut self,
808        attributes: impl IntoIterator<Item = impl ToString>,
809    ) -> Self {
810        self.0.add_attributes_from_strs(attributes);
811        self
812    }
813
814    pub fn attributes_from_strs_if(
815        mut self,
816        attributes: impl IntoIterator<Item = impl ToString>,
817        predicate: bool,
818    ) -> Self {
819        if predicate {
820            self.0.add_attributes_from_strs(attributes);
821        }
822        self
823    }
824
825    pub fn attributes_from_strs_if_some(
826        mut self,
827        attributes: Option<impl IntoIterator<Item = impl ToString>>,
828    ) -> Self {
829        if let Some(attributes) = attributes {
830            self.0.add_attributes_from_strs(attributes);
831        }
832        self
833    }
834
835    pub fn media(mut self, media: crate::Media) -> Self {
836        self.0.add_media(media);
837        self
838    }
839
840    pub fn media_if(mut self, media: crate::Media, predicate: bool) -> Self {
841        if predicate {
842            self.0.add_media(media);
843        }
844        self
845    }
846
847    pub fn media_if_some(mut self, media: Option<crate::Media>) -> Self {
848        if let Some(media) = media {
849            self.0.add_media(media);
850        }
851        self
852    }
853
854    pub fn medias(mut self, medias: impl IntoIterator<Item = crate::Media>) -> Self {
855        self.0.add_medias(medias);
856        self
857    }
858
859    pub fn medias_if(
860        mut self,
861        medias: impl IntoIterator<Item = crate::Media>,
862        predicate: bool,
863    ) -> Self {
864        if predicate {
865            self.0.add_medias(medias);
866        }
867        self
868    }
869
870    pub fn build(self) -> crate::Session {
871        self.0
872    }
873}
874
875// attributes
876
877/// A [`crate::RtpMap`] builder.
878#[derive(Debug)]
879pub struct RtpMap(attributes::RtpMap);
880impl RtpMap {
881    pub fn new(payload_type: u8, encoding_name: impl ToString, clock_rate: u32) -> Self {
882        Self(attributes::RtpMap::new(
883            payload_type,
884            encoding_name,
885            clock_rate,
886        ))
887    }
888
889    pub fn encoding_params(mut self, encoding_params: impl ToString) -> Self {
890        self.0.set_encoding_params(encoding_params);
891        self
892    }
893
894    pub fn encoding_params_if(mut self, encoding_params: impl ToString, predicate: bool) -> Self {
895        if predicate {
896            self.0.set_encoding_params(encoding_params);
897        }
898        self
899    }
900
901    pub fn encoding_params_if_some(mut self, encoding_params: Option<impl ToString>) -> Self {
902        if let Some(encoding_params) = encoding_params {
903            self.0.set_encoding_params(encoding_params);
904        }
905        self
906    }
907
908    pub fn build(self) -> attributes::RtpMap {
909        self.0
910    }
911}
912
913/// An [`crate::FmtpParam`] builder.
914#[derive(Debug)]
915pub struct FmtpParam(attributes::FmtpParam);
916impl FmtpParam {
917    pub fn new(param: impl ToString) -> Self {
918        Self(attributes::FmtpParam::new(param))
919    }
920
921    pub fn value(mut self, value: impl ToString) -> Self {
922        self.0.set_value(value);
923        self
924    }
925
926    pub fn value_if(mut self, value: impl ToString, predicate: bool) -> Self {
927        if predicate {
928            self.0.set_value(value);
929        }
930        self
931    }
932
933    pub fn value_if_some(mut self, value: Option<impl ToString>) -> Self {
934        if let Some(value) = value {
935            self.0.set_value(value);
936        }
937        self
938    }
939
940    pub fn build(self) -> attributes::FmtpParam {
941        self.0
942    }
943}
944
945/// An [`crate::Fmtp`] builder.
946#[derive(Debug)]
947pub struct Fmtp(attributes::Fmtp);
948impl Fmtp {
949    pub fn new(fmt: u8) -> Self {
950        Self(attributes::Fmtp::new(fmt))
951    }
952
953    pub fn format_specific_param(mut self, format_specific_param: attributes::FmtpParam) -> Self {
954        self.0.add_format_specific_param(format_specific_param);
955        self
956    }
957
958    pub fn format_specific_param_if(
959        mut self,
960        format_specific_param: attributes::FmtpParam,
961        predicate: bool,
962    ) -> Self {
963        if predicate {
964            self.0.add_format_specific_param(format_specific_param);
965        }
966        self
967    }
968
969    pub fn format_specific_param_if_some(
970        mut self,
971        format_specific_param: Option<attributes::FmtpParam>,
972    ) -> Self {
973        if let Some(format_specific_param) = format_specific_param {
974            self.0.add_format_specific_param(format_specific_param);
975        }
976        self
977    }
978
979    pub fn format_specific_params(
980        mut self,
981        format_specific_params: impl IntoIterator<Item = attributes::FmtpParam>,
982    ) -> Self {
983        self.0.add_format_specific_params(format_specific_params);
984        self
985    }
986
987    pub fn format_specific_params_if(
988        mut self,
989        format_specific_params: impl IntoIterator<Item = attributes::FmtpParam>,
990        predicate: bool,
991    ) -> Self {
992        if predicate {
993            self.0.add_format_specific_params(format_specific_params);
994        }
995        self
996    }
997
998    pub fn build(self) -> attributes::Fmtp {
999        self.0
1000    }
1001}
1002
1003/// An [`crate::ExtMap`] builder.
1004#[derive(Debug)]
1005pub struct ExtMap(attributes::ExtMap);
1006impl ExtMap {
1007    pub fn new(id: u8, uri: impl ToString) -> Self {
1008        Self(attributes::ExtMap::new(id, uri))
1009    }
1010
1011    pub fn direction(mut self, direction: attributes::Direction) -> Self {
1012        self.0.set_direction(direction);
1013        self
1014    }
1015
1016    pub fn direction_if(mut self, direction: attributes::Direction, predicate: bool) -> Self {
1017        if predicate {
1018            self.0.set_direction(direction);
1019        }
1020        self
1021    }
1022
1023    pub fn direction_if_some(mut self, direction: Option<attributes::Direction>) -> Self {
1024        if let Some(direction) = direction {
1025            self.0.set_direction(direction);
1026        }
1027        self
1028    }
1029
1030    pub fn attributes(mut self, attributes: impl ToString) -> Self {
1031        self.0.set_attributes(attributes);
1032        self
1033    }
1034
1035    pub fn attributes_if(mut self, attributes: impl ToString, predicate: bool) -> Self {
1036        if predicate {
1037            self.0.set_attributes(attributes);
1038        }
1039        self
1040    }
1041
1042    pub fn attributes_if_some(mut self, attributes: Option<impl ToString>) -> Self {
1043        if let Some(attributes) = attributes {
1044            self.0.set_attributes(attributes);
1045        }
1046        self
1047    }
1048
1049    pub fn build(self) -> attributes::ExtMap {
1050        self.0
1051    }
1052}
1053
1054/// A [`crate::Fingerprint`] builder.
1055#[derive(Debug)]
1056pub struct Fingerprint(attributes::Fingerprint);
1057impl Fingerprint {
1058    pub fn new(hash_func: enums::HashFunc) -> Self {
1059        Self(attributes::Fingerprint::new(hash_func))
1060    }
1061
1062    pub fn fingerprint(mut self, fingerprint: impl IntoIterator<Item = u8>) -> Self {
1063        self.0.set_fingerprint(fingerprint);
1064        self
1065    }
1066
1067    pub fn fingerprint_if(
1068        mut self,
1069        fingerprint: impl IntoIterator<Item = u8>,
1070        predicate: bool,
1071    ) -> Self {
1072        if predicate {
1073            self.0.set_fingerprint(fingerprint);
1074        }
1075        self
1076    }
1077
1078    pub fn fingerprint_if_some(
1079        mut self,
1080        fingerprint: Option<impl IntoIterator<Item = u8>>,
1081    ) -> Self {
1082        if let Some(fingerprint) = fingerprint {
1083            self.0.set_fingerprint(fingerprint);
1084        }
1085        self
1086    }
1087
1088    pub fn build(self) -> attributes::Fingerprint {
1089        self.0
1090    }
1091}
1092
1093/// A [`crate::Group`] builder.
1094#[derive(Debug)]
1095pub struct Group(attributes::Group);
1096impl Group {
1097    pub fn new(semantics: enums::GroupSemantics) -> Self {
1098        Self(attributes::Group::new(semantics))
1099    }
1100
1101    pub fn mid_tag(mut self, mid_tag: impl ToString) -> Self {
1102        self.0.add_mid_tag(mid_tag);
1103        self
1104    }
1105
1106    pub fn mid_tag_if(mut self, mid_tag: impl ToString, predicate: bool) -> Self {
1107        if predicate {
1108            self.0.add_mid_tag(mid_tag);
1109        }
1110        self
1111    }
1112
1113    pub fn mid_tag_if_some(mut self, mid_tag: Option<impl ToString>) -> Self {
1114        if let Some(mid_tag) = mid_tag {
1115            self.0.add_mid_tag(mid_tag);
1116        }
1117        self
1118    }
1119
1120    pub fn mid_tags(mut self, mid_tags: impl IntoIterator<Item = impl ToString>) -> Self {
1121        self.0.add_mid_tags(mid_tags);
1122        self
1123    }
1124
1125    pub fn mid_tags_if(
1126        mut self,
1127        mid_tags: impl IntoIterator<Item = impl ToString>,
1128        predicate: bool,
1129    ) -> Self {
1130        if predicate {
1131            self.0.add_mid_tags(mid_tags);
1132        }
1133        self
1134    }
1135
1136    pub fn mid_tags_if_some(
1137        mut self,
1138        mid_tags: Option<impl IntoIterator<Item = impl ToString>>,
1139    ) -> Self {
1140        if let Some(mid_tags) = mid_tags {
1141            self.0.add_mid_tags(mid_tags);
1142        }
1143        self
1144    }
1145
1146    pub fn build(self) -> attributes::Group {
1147        self.0
1148    }
1149}
1150
1151/// An [`crate::Ssrc`] builder.
1152#[derive(Debug)]
1153pub struct Ssrc(attributes::Ssrc);
1154impl Ssrc {
1155    pub fn new(ssrc_id: u32, attribute: enums::SsrcAttribute) -> Self {
1156        Self(attributes::Ssrc::new(ssrc_id, attribute))
1157    }
1158
1159    pub fn value(mut self, value: impl ToString) -> Self {
1160        self.0.set_value(value);
1161        self
1162    }
1163
1164    pub fn value_if(mut self, value: impl ToString, predicate: bool) -> Self {
1165        if predicate {
1166            self.0.set_value(value);
1167        }
1168        self
1169    }
1170
1171    pub fn value_if_some(mut self, value: Option<impl ToString>) -> Self {
1172        if let Some(value) = value {
1173            self.0.set_value(value);
1174        }
1175        self
1176    }
1177
1178    pub fn build(self) -> attributes::Ssrc {
1179        self.0
1180    }
1181}
1182
1183/// An [`crate::SsrcGroup`] builder.
1184#[derive(Debug)]
1185pub struct SsrcGroup(attributes::SsrcGroup);
1186impl SsrcGroup {
1187    pub fn new(semantics: enums::GroupSemantics) -> Self {
1188        Self(attributes::SsrcGroup::new(semantics))
1189    }
1190
1191    pub fn ssrc_id(mut self, ssrc_id: u32) -> Self {
1192        self.0.add_ssrc_id(ssrc_id);
1193        self
1194    }
1195
1196    pub fn ssrc_id_if(mut self, ssrc_id: u32, predicate: bool) -> Self {
1197        if predicate {
1198            self.0.add_ssrc_id(ssrc_id);
1199        }
1200        self
1201    }
1202
1203    pub fn ssrc_id_if_some(mut self, ssrc_id: Option<u32>) -> Self {
1204        if let Some(ssrc_id) = ssrc_id {
1205            self.0.add_ssrc_id(ssrc_id);
1206        }
1207        self
1208    }
1209
1210    pub fn ssrc_ids(mut self, ssrc_ids: impl IntoIterator<Item = u32>) -> Self {
1211        self.0.add_ssrc_ids(ssrc_ids);
1212        self
1213    }
1214
1215    pub fn ssrc_ids_if(mut self, ssrc_ids: impl IntoIterator<Item = u32>, predicate: bool) -> Self {
1216        if predicate {
1217            self.0.add_ssrc_ids(ssrc_ids);
1218        }
1219        self
1220    }
1221
1222    pub fn ssrc_ids_if_some(mut self, ssrc_ids: Option<impl IntoIterator<Item = u32>>) -> Self {
1223        if let Some(ssrc_ids) = ssrc_ids {
1224            self.0.add_ssrc_ids(ssrc_ids);
1225        }
1226        self
1227    }
1228
1229    pub fn build(self) -> attributes::SsrcGroup {
1230        self.0
1231    }
1232}
1233
1234/// A [`crate::SrtpKeyParam`] builder.
1235#[derive(Debug)]
1236pub struct SrtpKeyParam(attributes::SrtpKeyParam);
1237impl SrtpKeyParam {
1238    pub fn new(key_and_salt: impl ToString) -> Self {
1239        Self(attributes::SrtpKeyParam::new(key_and_salt))
1240    }
1241
1242    pub fn lifetime(mut self, lifetime: u32) -> Self {
1243        self.0.set_lifetime(lifetime);
1244        self
1245    }
1246
1247    pub fn lifetime_if(mut self, lifetime: u32, predicate: bool) -> Self {
1248        if predicate {
1249            self.0.set_lifetime(lifetime);
1250        }
1251        self
1252    }
1253
1254    pub fn lifetime_if_some(mut self, lifetime: Option<u32>) -> Self {
1255        if let Some(lifetime) = lifetime {
1256            self.0.set_lifetime(lifetime);
1257        }
1258        self
1259    }
1260
1261    pub fn mki_and_length(mut self, mki: u32, length: u32) -> Self {
1262        self.0.set_mki_and_length(mki, length);
1263        self
1264    }
1265
1266    pub fn mki_and_length_if(mut self, mki: u32, length: u32, predicate: bool) -> Self {
1267        if predicate {
1268            self.0.set_mki_and_length(mki, length);
1269        }
1270        self
1271    }
1272
1273    pub fn mki_and_length_if_some(mut self, mki_length: Option<(u32, u32)>) -> Self {
1274        if let Some((mki, length)) = mki_length {
1275            self.0.set_mki_and_length(mki, length);
1276        }
1277        self
1278    }
1279
1280    pub fn build(self) -> attributes::SrtpKeyParam {
1281        self.0
1282    }
1283}
1284
1285/// A [`crate::Crypto`] builder.
1286#[derive(Debug)]
1287pub struct Crypto(attributes::Crypto);
1288impl Crypto {
1289    pub fn new(tag: u32, crypto_suite: enums::CryptoSuite) -> Self {
1290        Self(attributes::Crypto::new(tag, crypto_suite))
1291    }
1292
1293    pub fn key_param(mut self, key_param: attributes::SrtpKeyParam) -> Self {
1294        self.0.add_key_param(key_param);
1295        self
1296    }
1297
1298    pub fn key_param_if(mut self, key_param: attributes::SrtpKeyParam, predicate: bool) -> Self {
1299        if predicate {
1300            self.0.add_key_param(key_param);
1301        }
1302        self
1303    }
1304
1305    pub fn key_param_if_some(mut self, key_param: Option<attributes::SrtpKeyParam>) -> Self {
1306        if let Some(key_param) = key_param {
1307            self.0.add_key_param(key_param);
1308        }
1309        self
1310    }
1311
1312    pub fn key_params(
1313        mut self,
1314        key_params: impl IntoIterator<Item = attributes::SrtpKeyParam>,
1315    ) -> Self {
1316        self.0.add_key_params(key_params);
1317        self
1318    }
1319
1320    pub fn key_params_if(
1321        mut self,
1322        key_params: impl IntoIterator<Item = attributes::SrtpKeyParam>,
1323        predicate: bool,
1324    ) -> Self {
1325        if predicate {
1326            self.0.add_key_params(key_params);
1327        }
1328        self
1329    }
1330
1331    pub fn key_params_if_some(
1332        mut self,
1333        key_params: Option<impl IntoIterator<Item = attributes::SrtpKeyParam>>,
1334    ) -> Self {
1335        if let Some(key_params) = key_params {
1336            self.0.add_key_params(key_params);
1337        }
1338        self
1339    }
1340
1341    pub fn session_param(mut self, session_param: enums::SrtpSessionParam) -> Self {
1342        self.0.add_session_param(session_param);
1343        self
1344    }
1345
1346    pub fn session_param_if(
1347        mut self,
1348        session_param: enums::SrtpSessionParam,
1349        predicate: bool,
1350    ) -> Self {
1351        if predicate {
1352            self.0.add_session_param(session_param);
1353        }
1354        self
1355    }
1356
1357    pub fn session_param_if_some(mut self, session_param: Option<enums::SrtpSessionParam>) -> Self {
1358        if let Some(session_param) = session_param {
1359            self.0.add_session_param(session_param);
1360        }
1361        self
1362    }
1363
1364    pub fn session_params(
1365        mut self,
1366        session_params: impl IntoIterator<Item = enums::SrtpSessionParam>,
1367    ) -> Self {
1368        self.0.add_session_params(session_params);
1369        self
1370    }
1371
1372    pub fn session_params_if(
1373        mut self,
1374        session_params: impl IntoIterator<Item = enums::SrtpSessionParam>,
1375        predicate: bool,
1376    ) -> Self {
1377        if predicate {
1378            self.0.add_session_params(session_params);
1379        }
1380        self
1381    }
1382
1383    pub fn session_params_if_some(
1384        mut self,
1385        session_params: Option<impl IntoIterator<Item = enums::SrtpSessionParam>>,
1386    ) -> Self {
1387        if let Some(session_params) = session_params {
1388            self.0.add_session_params(session_params);
1389        }
1390        self
1391    }
1392
1393    pub fn build(self) -> attributes::Crypto {
1394        self.0
1395    }
1396}
1397
1398/// A [`crate::Candidate`] builder.
1399#[derive(Debug)]
1400pub struct Candidate(attributes::Candidate);
1401impl Candidate {
1402    pub fn new(
1403        foundation: impl ToString,
1404        component_id: u32,
1405        transport: impl ToString,
1406        priority: u64,
1407        address: enums::CandidateAddress,
1408        port: u16,
1409        typ: enums::CandidateType,
1410    ) -> Self {
1411        Self(attributes::Candidate::new(
1412            foundation,
1413            component_id,
1414            transport,
1415            priority,
1416            address,
1417            port,
1418            typ,
1419        ))
1420    }
1421
1422    pub fn rel_addr(mut self, rel_addr: impl Into<IpAddr>) -> Self {
1423        self.0.set_rel_addr(rel_addr);
1424        self
1425    }
1426
1427    pub fn rel_addr_if(mut self, rel_addr: impl Into<IpAddr>, predicate: bool) -> Self {
1428        if predicate {
1429            self.0.set_rel_addr(rel_addr);
1430        }
1431        self
1432    }
1433
1434    pub fn rel_addr_if_some(mut self, rel_addr: Option<impl Into<IpAddr>>) -> Self {
1435        if let Some(rel_addr) = rel_addr {
1436            self.0.set_rel_addr(rel_addr);
1437        }
1438        self
1439    }
1440
1441    pub fn rel_port(mut self, rel_port: u16) -> Self {
1442        self.0.set_rel_port(rel_port);
1443        self
1444    }
1445
1446    pub fn rel_port_if(mut self, rel_port: u16, predicate: bool) -> Self {
1447        if predicate {
1448            self.0.set_rel_port(rel_port);
1449        }
1450        self
1451    }
1452
1453    pub fn rel_port_if_some(mut self, rel_port: Option<u16>) -> Self {
1454        if let Some(rel_port) = rel_port {
1455            self.0.set_rel_port(rel_port);
1456        }
1457        self
1458    }
1459
1460    pub fn extension(mut self, name: impl ToString, value: impl ToString) -> Self {
1461        self.0.add_extension(name, value);
1462        self
1463    }
1464
1465    pub fn extension_if(
1466        mut self,
1467        name: impl ToString,
1468        value: impl ToString,
1469        predicate: bool,
1470    ) -> Self {
1471        if predicate {
1472            self.0.add_extension(name, value);
1473        }
1474        self
1475    }
1476
1477    pub fn extension_if_some(mut self, name_value: Option<(impl ToString, impl ToString)>) -> Self {
1478        if let Some((name, value)) = name_value {
1479            self.0.add_extension(name, value);
1480        }
1481        self
1482    }
1483
1484    pub fn build(self) -> attributes::Candidate {
1485        self.0
1486    }
1487}
1488
1489/// An [`crate::NtpServerAddr`] builder.
1490#[derive(Debug)]
1491pub struct NtpServerAddr(clock_signalling::NtpServerAddr);
1492impl NtpServerAddr {
1493    pub fn new(hostname: impl ToString) -> Self {
1494        Self(clock_signalling::NtpServerAddr::from_hostname(hostname))
1495    }
1496
1497    pub fn port(mut self, port: u16) -> Self {
1498        let clock_signalling::NtpServerAddr::HostPort { port: port_opt, .. } = &mut self.0 else {
1499            unreachable!("Builder constructed from hostname");
1500        };
1501        *port_opt = Some(port);
1502
1503        self
1504    }
1505
1506    pub fn port_if(mut self, port: u16, predicate: bool) -> Self {
1507        if predicate {
1508            self = self.port(port);
1509        }
1510        self
1511    }
1512
1513    pub fn port_if_some(mut self, port: Option<u16>) -> Self {
1514        if let Some(port) = port {
1515            self = self.port(port);
1516        }
1517        self
1518    }
1519
1520    pub fn build(self) -> clock_signalling::NtpServerAddr {
1521        self.0
1522    }
1523}
1524
1525/// An [`ClockSourceExt`] builder.
1526#[derive(Debug)]
1527pub struct ClockSourceExt(clock_signalling::ClockSourceExt);
1528impl ClockSourceExt {
1529    pub fn new(name: impl ToString) -> Self {
1530        Self(clock_signalling::ClockSourceExt::new(name))
1531    }
1532
1533    pub fn value(mut self, value: impl ToString) -> Self {
1534        self.0.set_value(value);
1535        self
1536    }
1537
1538    pub fn value_if(mut self, value: impl ToString, predicate: bool) -> Self {
1539        if predicate {
1540            self.0.set_value(value);
1541        }
1542        self
1543    }
1544
1545    pub fn value_if_some(mut self, value: Option<impl ToString>) -> Self {
1546        if let Some(value) = value {
1547            self.0.set_value(value);
1548        }
1549        self
1550    }
1551
1552    pub fn build(self) -> clock_signalling::ClockSourceExt {
1553        self.0
1554    }
1555}
1556
1557/// A [`crate::MediaClockSource`] builder.
1558#[derive(Debug)]
1559pub struct MediaClockSource(clock_signalling::MediaClockSource);
1560impl MediaClockSource {
1561    pub fn new(clock: impl Into<clock_signalling::MediaClock>) -> Self {
1562        Self(clock_signalling::MediaClockSource::new(clock))
1563    }
1564
1565    pub fn id(mut self, id: clock_signalling::MediaClockId) -> Self {
1566        self.0.set_id(id);
1567        self
1568    }
1569
1570    pub fn id_if(mut self, id: clock_signalling::MediaClockId, predicate: bool) -> Self {
1571        if predicate {
1572            self.0.set_id(id);
1573        }
1574        self
1575    }
1576
1577    pub fn id_if_some(mut self, id: Option<clock_signalling::MediaClockId>) -> Self {
1578        if let Some(id) = id {
1579            self.0.set_id(id);
1580        }
1581        self
1582    }
1583
1584    pub fn build(self) -> clock_signalling::MediaClockSource {
1585        self.0
1586    }
1587}
1588
1589/// A [`Direct`] builder.
1590#[derive(Debug)]
1591pub struct Direct(clock_signalling::Direct);
1592impl Direct {
1593    pub fn new() -> Self {
1594        Self(clock_signalling::Direct::new())
1595    }
1596
1597    pub fn offset(mut self, offset: u32) -> Self {
1598        self.0.set_offset(offset);
1599        self
1600    }
1601
1602    pub fn offset_if(mut self, offset: u32, predicate: bool) -> Self {
1603        if predicate {
1604            self.0.set_offset(offset);
1605        }
1606        self
1607    }
1608
1609    pub fn offset_if_some(mut self, offset: Option<u32>) -> Self {
1610        if let Some(offset) = offset {
1611            self.0.set_offset(offset);
1612        }
1613        self
1614    }
1615
1616    pub fn rate(mut self, rate: impl Into<clock_signalling::Rate>) -> Self {
1617        self.0.set_rate(rate);
1618        self
1619    }
1620
1621    pub fn rate_if(mut self, rate: impl Into<clock_signalling::Rate>, predicate: bool) -> Self {
1622        if predicate {
1623            self.0.set_rate(rate);
1624        }
1625        self
1626    }
1627
1628    pub fn rate_if_some(mut self, rate: Option<impl Into<clock_signalling::Rate>>) -> Self {
1629        if let Some(rate) = rate {
1630            self.0.set_rate(rate);
1631        }
1632        self
1633    }
1634
1635    pub fn build(self) -> clock_signalling::Direct {
1636        self.0
1637    }
1638}
1639
1640impl Default for Direct {
1641    fn default() -> Self {
1642        Direct::new()
1643    }
1644}
1645
1646/// A [`MediaClockExt`] builder.
1647#[derive(Debug)]
1648pub struct MediaClockExt(clock_signalling::MediaClockExt);
1649impl MediaClockExt {
1650    pub fn new(name: impl ToString) -> Self {
1651        Self(clock_signalling::MediaClockExt::new(name))
1652    }
1653
1654    pub fn value(mut self, value: impl ToString) -> Self {
1655        self.0.set_value(value);
1656        self
1657    }
1658
1659    pub fn value_if(mut self, value: impl ToString, predicate: bool) -> Self {
1660        if predicate {
1661            self.0.set_value(value);
1662        }
1663        self
1664    }
1665
1666    pub fn value_if_some(mut self, value: Option<impl ToString>) -> Self {
1667        if let Some(value) = value {
1668            self.0.set_value(value);
1669        }
1670        self
1671    }
1672
1673    pub fn build(self) -> clock_signalling::MediaClockExt {
1674        self.0
1675    }
1676
1677    pub fn build_media_clock(self) -> clock_signalling::MediaClock {
1678        self.0.into()
1679    }
1680}
1681
1682#[cfg(test)]
1683mod test {
1684    #[test]
1685    fn builder() {
1686        use crate::{
1687            Direction, Media, MediaType, Origin, RtpMap, Session, Ssrc, SsrcAttribute,
1688            TransportProto,
1689        };
1690        use std::{net::Ipv4Addr, str::FromStr};
1691
1692        const SESSION_ID: &str = "1234";
1693        const SESSION_NAME: &str = "sdp-type-builder-test";
1694        const USER_NAME: &str = "test-user";
1695        const UNICAST_ADDRESS: &str = "192.168.0.2";
1696        const CONNECTION_ADDRESS: &str = "192.168.0.3";
1697        const CONNECTION_PORT: u16 = 5000;
1698        const SENDER_ADDRESS: &str = "192.168.0.4";
1699        const SENDER_RTCP_PORT: u16 = 5001;
1700        const PT: u8 = 96;
1701        const ENCODING_NAME: &str = "L24";
1702        const AUDIO_RATE: u32 = 48_000;
1703        const AUDIO_PARAMS: u8 = 2;
1704        const SSRC: u32 = 1234;
1705        const CNAME: &str = "user@test.org";
1706        const REFCLK_NTP_HOSTNAME: &str = "192.168.0.2";
1707        const REFCLK_NTP_PORT: u16 = 5000;
1708        const MEDIACLK_OFFSET: u32 = 123456;
1709
1710        let sdp = Session::builder(
1711            Origin::builder_with_ip_addr(
1712                SESSION_ID,
1713                0,
1714                Ipv4Addr::from_str(UNICAST_ADDRESS).unwrap(),
1715            )
1716            .username(USER_NAME)
1717            .build(),
1718            SESSION_NAME,
1719        )
1720        .connection(Ipv4Addr::from_str(CONNECTION_ADDRESS).unwrap())
1721        .attribute(Direction::SendOnly)
1722        .media(
1723            Media::builder(
1724                MediaType::Audio,
1725                CONNECTION_PORT,
1726                TransportProto::RtpAvp,
1727                PT,
1728            )
1729            .attribute(RtpMap::with_encoding_params(
1730                PT,
1731                ENCODING_NAME,
1732                AUDIO_RATE,
1733                AUDIO_PARAMS,
1734            ))
1735            .attribute(Ssrc::with_value(SSRC, SsrcAttribute::Cname, CNAME))
1736            .attribute(Ssrc::with_typed_attribute(
1737                SSRC,
1738                crate::ReferenceClock::from(
1739                    crate::NtpServerAddr::builder(REFCLK_NTP_HOSTNAME)
1740                        .port(REFCLK_NTP_PORT)
1741                        .build(),
1742                ),
1743            ))
1744            .attribute(Ssrc::with_typed_attribute(
1745                SSRC,
1746                crate::MediaClockSource::builder(
1747                    crate::Direct::builder().offset(MEDIACLK_OFFSET).build(),
1748                )
1749                .build(),
1750            ))
1751            .attribute(Ssrc::with_typed_attribute(
1752                SSRC,
1753                crate::Rtcp::with_ip_addr(
1754                    SENDER_RTCP_PORT,
1755                    Ipv4Addr::from_str(SENDER_ADDRESS).unwrap(),
1756                ),
1757            ))
1758            .attribute_from_str("rtcp-mux")
1759            .build(),
1760        )
1761        .build();
1762
1763        use crate::{AddrType, Attribute, Connection, NetType};
1764        assert_eq!(
1765            sdp,
1766            Session {
1767                origin: Origin {
1768                    username: Some(USER_NAME.to_string()),
1769                    sess_id: SESSION_ID.to_string(),
1770                    sess_version: 0,
1771                    nettype: NetType::In,
1772                    addrtype: AddrType::Ip4,
1773                    unicast_address: UNICAST_ADDRESS.to_string(),
1774                },
1775                session_name: SESSION_NAME.to_string(),
1776                connection: Some(Connection {
1777                    nettype: NetType::In,
1778                    addrtype: AddrType::Ip4,
1779                    connection_address: CONNECTION_ADDRESS.to_string(),
1780                }),
1781                session_description: None,
1782                uri: None,
1783                emails: vec![],
1784                phones: vec![],
1785                bandwidths: vec![],
1786                times: vec![],
1787                time_zones: vec![],
1788                key: None,
1789                attributes: vec![Attribute {
1790                    attribute: "sendonly".to_string(),
1791                    value: None
1792                }],
1793                medias: vec![Media {
1794                    media: MediaType::Audio.to_string(),
1795                    port: CONNECTION_PORT,
1796                    num_ports: None,
1797                    proto: TransportProto::RtpAvp.to_string(),
1798                    fmt: PT.to_string(),
1799                    media_title: None,
1800                    connections: vec![],
1801                    bandwidths: vec![],
1802                    key: None,
1803                    attributes: vec![
1804                        Attribute {
1805                            attribute: "rtpmap".to_string(),
1806                            value: Some(format!(
1807                                "{PT} {ENCODING_NAME}/{AUDIO_RATE}/{AUDIO_PARAMS}"
1808                            )),
1809                        },
1810                        Attribute {
1811                            attribute: "ssrc".to_string(),
1812                            value: Some(format!("{SSRC} cname:{CNAME}")),
1813                        },
1814                        Attribute {
1815                            attribute: "ssrc".to_string(),
1816                            value: Some(format!(
1817                                "{SSRC} ts-refclk:ntp={REFCLK_NTP_HOSTNAME}:{REFCLK_NTP_PORT}"
1818                            )),
1819                        },
1820                        Attribute {
1821                            attribute: "ssrc".to_string(),
1822                            value: Some(format!("{SSRC} mediaclk:direct={MEDIACLK_OFFSET}")),
1823                        },
1824                        Attribute {
1825                            attribute: "ssrc".to_string(),
1826                            value: Some(format!(
1827                                "{SSRC} rtcp:{SENDER_RTCP_PORT} IN IP4 {SENDER_ADDRESS}"
1828                            )),
1829                        },
1830                        Attribute {
1831                            attribute: "rtcp-mux".to_string(),
1832                            value: None,
1833                        },
1834                    ],
1835                }],
1836            }
1837        )
1838    }
1839}