sdp_nom/
udisplay.rs

1use ufmt::{uWrite, uwrite, uwriteln, Formatter};
2
3use crate::{
4    attributes::{
5        bundle::BundleGroup,
6        candidate::{Candidate, CandidateComponent, CandidateProtocol, CandidateType},
7        control::Control,
8        direction::Direction,
9        dtls::SetupRole,
10        extmap::Extmap,
11        fingerprint::Fingerprint,
12        fmtp::Fmtp,
13        ice::IceParameter,
14        mid::Mid,
15        msid::*,
16        rtcp::*,
17        rtcp_option::RtcpOption,
18        rtp::Rtp,
19        rtpmap::*,
20        ssrc::{Ssrc, SsrcGroup, SsrcSemantic},
21        AttributeLine,
22    },
23    lines::{
24        bandwidth::*, connection::*, email::*, media::*, origin::*, phone_number::*,
25        session_information::*, session_name::*, timing::*, uri::*, version::*, SessionLine,
26    },
27    media_section::MediaSection,
28    parsers::IpVer,
29    SdpLine, Session,
30};
31impl ufmt::uDisplay for Session<'_> {
32    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
33    where
34        W: uWrite + ?Sized,
35    {
36        write_ln_option(f, &self.version)?;
37        write_ln_option(f, &self.origin)?;
38        write_ln_option(f, &self.name)?;
39        write_ln_option(f, &self.timing)?;
40        write_ln_option(f, &self.band_width)?;
41        write_ln_option(f, &self.uri)?;
42        write_ln_option(f, &self.phone_number)?;
43        write_ln_option(f, &self.email_address)?;
44        write_ln_option(f, &self.connection)?;
45        write_ln_option(f, &self.description)?;
46
47        for x in &self.attributes {
48            uwriteln!(f, "{}", x)?;
49        }
50
51        for x in &self.media {
52            uwrite!(f, "{}", x)?;
53        }
54        Ok(())
55    }
56}
57
58fn write_ln_option<W>(
59    f: &mut Formatter<'_, W>,
60    content: &Option<impl ufmt::uDisplay>,
61) -> Result<(), W::Error>
62where
63    W: uWrite + ?Sized,
64{
65    if let Some(ref x) = content {
66        uwriteln!(f, "{}", x)?;
67    }
68    Ok(())
69}
70
71impl ufmt::uDisplay for MediaSection<'_> {
72    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
73    where
74        W: uWrite + ?Sized,
75    {
76        uwriteln!(f, "{}", self.media())?;
77
78        write_ln_option(f, &self.connection)?;
79
80        write_ln_option(f, &self.rtcp)?;
81        for candidate in &self.candidates {
82            uwriteln!(f, "{}", candidate)?;
83        }
84
85        write_ln_option(f, &self.ice.ufrag.clone().map(IceParameter::Ufrag))?;
86
87        write_ln_option(f, &self.ice.pwd.clone().map(IceParameter::Pwd))?;
88
89        write_ln_option(f, &self.ice.options.clone().map(IceParameter::Options))?;
90
91        write_ln_option(f, &self.fingerprint)?;
92        write_ln_option(f, &self.setup_role)?;
93        // uwriteln!(f, "{}", Mid(self.mid.clone()))?;
94        write_ln_option(f, &self.mid.to_owned().map(Mid))?;
95
96        write_ln_option(f, &self.p_time)?;
97        for extmap in &self.extmap {
98            uwriteln!(f, "{}", extmap)?;
99        }
100
101        write_ln_option(f, &self.bundle_group)?;
102        if self.bundle_only {
103            uwriteln!(f, "a=bundle-only")?;
104        }
105        write_ln_option(f, &self.direction)?;
106        write_ln_option(f, &self.msid_semantic)?;
107        write_ln_option(f, &self.msid)?;
108        write_ln_option(f, &self.rtp)?;
109        for rtcp_option in &self.rtcp_option {
110            uwriteln!(f, "{}", rtcp_option)?;
111        }
112
113        let known_payloads = self
114            .payloads
115            .iter()
116            .filter_map(|p| p.parse::<u32>().ok())
117            .collect::<Vec<_>>();
118
119        for payload in &known_payloads {
120            for rtp in self.rtp_map.iter().filter(|r| r.payload == *payload) {
121                uwriteln!(f, "{}", rtp)?;
122            }
123            for rtcp_fb in self.rtcp_fb.iter().filter(|r| r.payload == *payload) {
124                uwriteln!(f, "{}", rtcp_fb)?;
125            }
126            for fmtp in self.fmtp.iter().filter(|r| r.payload == *payload) {
127                uwriteln!(f, "{}", fmtp)?;
128            }
129        } // one more round for those not listed in the fmt field
130        {
131            for rtp in self
132                .rtp_map
133                .iter()
134                .filter(|r| !known_payloads.contains(&r.payload))
135            {
136                uwriteln!(f, "{}", rtp)?;
137            }
138            for rtcp_fb in self
139                .rtcp_fb
140                .iter()
141                .filter(|r| !known_payloads.contains(&r.payload))
142            {
143                uwriteln!(f, "{}", rtcp_fb)?;
144            }
145            for fmtp in self
146                .fmtp
147                .iter()
148                .filter(|r| !known_payloads.contains(&r.payload))
149            {
150                uwriteln!(f, "{}", fmtp)?;
151            }
152        }
153
154        write_ln_option(f, &self.ssrc_group)?;
155        for ssrc in &self.ssrc {
156            uwriteln!(f, "{}", ssrc)?;
157        }
158
159        write_ln_option(f, &self.control)?;
160
161        for x in &self.attributes {
162            uwriteln!(f, "{}", x)?;
163        }
164
165        Ok(())
166    }
167}
168impl ufmt::uDisplay for SdpLine<'_> {
169    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
170    where
171        W: uWrite + ?Sized,
172    {
173        match self {
174            SdpLine::Session(session) => uwriteln!(f, "{}", session),
175            SdpLine::Attribute(attribute) => uwriteln!(f, "{}", attribute),
176            SdpLine::Comment(_) => Ok(()),
177        }
178    }
179}
180#[cfg(all(feature = "udisplay"))]
181impl std::string::ToString for SdpLine<'_> {
182    fn to_string(&self) -> String {
183        let mut output = String::new();
184        ufmt::uwrite!(output, "{}", self).unwrap();
185        output
186    }
187}
188
189impl ufmt::uDisplay for SessionLine<'_> {
190    #[rustfmt::skip]
191    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
192    where
193        W: uWrite + ?Sized, {
194        match self {
195            SessionLine::Version(v)      => uwrite!(f,"{}", v),
196            SessionLine::Name(n)         => uwrite!(f,"{}", n),
197            SessionLine::Timing(t)       => uwrite!(f,"{}", t),
198            SessionLine::Origin(o)       => uwrite!(f,"{}", o),
199            SessionLine::BandWidth(b)    => uwrite!(f,"{}", b),
200            SessionLine::Uri(u)          => uwrite!(f,"{}", u),
201            SessionLine::PhoneNumber(p)  => uwrite!(f,"{}", p),
202            SessionLine::EmailAddress(e) => uwrite!(f,"{}", e),
203            SessionLine::Connection(c)   => uwrite!(f,"{}", c),
204            SessionLine::Description(d)  => uwrite!(f,"{}", d),
205            SessionLine::Media(m)        => uwrite!(f,"{}", m),
206        }
207    }
208}
209
210impl ufmt::uDisplay for AttributeLine<'_> {
211    #[rustfmt::skip]
212    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
213    where
214        W: uWrite + ?Sized, {
215        match self {
216            AttributeLine::Candidate(c)    => uwrite!(f, "{}", c),
217            AttributeLine::Ice(i)          => uwrite!(f, "{}", i),
218            AttributeLine::Mid(m)          => uwrite!(f, "{}", m),
219            AttributeLine::MsidSemantic(ms) => uwrite!(f, "{}", ms),
220            AttributeLine::Msid(m)         => uwrite!(f, "{}", m),
221            AttributeLine::RtpMap(r)       => uwrite!(f, "{}", r),
222            AttributeLine::PTime(p)        => uwrite!(f, "{}", p),
223            AttributeLine::Ssrc(s)         => uwrite!(f, "{}", s),
224            AttributeLine::BundleGroup(b)  => uwrite!(f, "{}", b),
225            AttributeLine::SsrcGroup(s)    => uwrite!(f, "{}", s),
226            AttributeLine::Fingerprint(fp) => uwrite!(f, "{}", fp),
227            AttributeLine::Direction(d)    => uwrite!(f, "{}", d),
228            AttributeLine::Rtp(r)          => uwrite!(f, "{}", r),
229            AttributeLine::Rtcp(r)         => uwrite!(f, "{}", r),
230            AttributeLine::Fmtp(fmtp)      => uwrite!(f, "{}", fmtp),
231            AttributeLine::RtcpFb(r)       => uwrite!(f, "{}", r),
232            AttributeLine::RtcpOption(r)   => uwrite!(f, "{}", r),
233            AttributeLine::Control(c)      => uwrite!(f, "{}", c),
234            AttributeLine::SetupRole(s)    => uwrite!(f, "{}", s),
235            AttributeLine::Extmap(e)       => uwrite!(f, "{}", e),
236            AttributeLine::BundleOnly      => uwrite!(f, "a=bundle-only"),
237            AttributeLine::EoC             => uwrite!(f, "a=end-of-candidates"),
238            AttributeLine::KeyValue {
239                key,
240                val
241            }                              => uwrite!(f, "a={}:{}", key.as_ref(), val.as_ref()),
242            AttributeLine::KeyOnly(key)    => uwrite!(f, "a={}", key.as_ref()),
243        }
244    }
245}
246
247impl ufmt::uDisplay for BundleGroup<'_> {
248    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
249    where
250        W: uWrite + ?Sized,
251    {
252        uwrite!(f, "a=group:BUNDLE")?;
253        for v in &self.0 {
254            uwrite!(f, " {}", v.as_ref())?;
255        }
256        Ok(())
257    }
258}
259impl ufmt::uDisplay for Fmtp<'_> {
260    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
261    where
262        W: uWrite + ?Sized,
263    {
264        uwrite!(f, "a=fmtp:{} {}", self.payload, self.config.as_ref())
265    }
266}
267impl ufmt::uDisplay for Rtp<'_> {
268    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
269    where
270        W: uWrite + ?Sized,
271    {
272        uwrite!(
273            f,
274            "a=rtpmap:{} {}/{}/{}",
275            self.payload,
276            self.codec.as_ref(),
277            self.rate,
278            self.encoding
279        )
280    }
281}
282impl ufmt::uDisplay for Control<'_> {
283    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
284    where
285        W: uWrite + ?Sized,
286    {
287        uwrite!(f, "a=control:{}", self.0.as_ref())
288    }
289}
290impl ufmt::uDisplay for Direction {
291    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
292    where
293        W: uWrite + ?Sized,
294    {
295        match self {
296            Direction::SendOnly => uwrite!(f, "a=sendonly"),
297            Direction::SendRecv => uwrite!(f, "a=sendrecv"),
298            Direction::RecvOnly => uwrite!(f, "a=recvonly"),
299            Direction::Inactive => uwrite!(f, "a=inactive"),
300        }
301    }
302}
303impl ufmt::uDisplay for RtcpOption {
304    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
305    where
306        W: uWrite + ?Sized,
307    {
308        match self {
309            RtcpOption::RtcpMux => uwrite!(f, "a=rtcp-mux"),
310            RtcpOption::RtcpMuxOnly => uwrite!(f, "a=rtcp-mux-only"),
311            RtcpOption::RtcpRsize => uwrite!(f, "a=rtcp-rsize"),
312        }
313    }
314}
315impl ufmt::uDisplay for Fingerprint<'_> {
316    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
317    where
318        W: uWrite + ?Sized,
319    {
320        uwrite!(
321            f,
322            "a=fingerprint:{} {}",
323            self.r#type.as_ref(),
324            self.hash.as_ref()
325        )
326    }
327}
328impl ufmt::uDisplay for Mid<'_> {
329    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
330    where
331        W: uWrite + ?Sized,
332    {
333        uwrite!(f, "a=mid:{}", self.0.as_ref())
334    }
335}
336impl ufmt::uDisplay for MsidSemantic<'_> {
337    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
338    where
339        W: uWrite + ?Sized,
340    {
341        uwrite!(f, "a=msid-semantic: ")?;
342        uwrite!(f, "{} ", self.semantic.as_ref())?;
343        if let Some(ref token) = self.token {
344            uwrite!(f, "{}", token.as_ref())?;
345        }
346        Ok(())
347    }
348}
349impl ufmt::uDisplay for Msid<'_> {
350    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
351    where
352        W: uWrite + ?Sized,
353    {
354        uwrite!(f, "a=msid:")?;
355        for (i, x) in self.0.iter().enumerate() {
356            if i > 0 {
357                uwrite!(f, " ")?;
358            }
359            uwrite!(f, "{}", x.as_ref())?;
360        }
361        Ok(())
362    }
363}
364impl ufmt::uDisplay for Version {
365    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
366    where
367        W: uWrite + ?Sized,
368    {
369        uwrite!(f, "v={}", self.0)
370    }
371}
372impl ufmt::uDisplay for SessionInformation<'_> {
373    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
374    where
375        W: uWrite + ?Sized,
376    {
377        uwrite!(f, "i={}", self.0.as_ref())
378    }
379}
380impl ufmt::uDisplay for SessionName<'_> {
381    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
382    where
383        W: uWrite + ?Sized,
384    {
385        uwrite!(f, "s={}", self.0.as_ref())
386    }
387}
388
389impl ufmt::uDisplay for Origin<'_> {
390    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
391    where
392        W: uWrite + ?Sized,
393    {
394        uwrite!(
395            f,
396            "o={} {} {} {} {} {}",
397            self.user_name.as_ref(),
398            self.session_id,
399            self.session_version,
400            self.net_type.as_ref(),
401            self.ip_ver,
402            IpAddress(&self.addr)
403        )
404    }
405}
406
407impl ufmt::uDisplay for Media<'_> {
408    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
409    where
410        W: uWrite + ?Sized,
411    {
412        uwrite!(
413            f,
414            "m={} {} {}",
415            self.r#type.as_ref(),
416            self.port,
417            self.protocol.join("/").as_str(),
418        )?;
419        for payload in &self.payloads {
420            uwrite!(f, " {}", payload.as_ref())?;
421        }
422        Ok(())
423    }
424}
425
426struct IpAddress<'a>(&'a std::net::IpAddr);
427#[allow(clippy::many_single_char_names)]
428impl ufmt::uDisplay for IpAddress<'_> {
429    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
430    where
431        W: uWrite + ?Sized,
432    {
433        match self.0 {
434            std::net::IpAddr::V4(addr) => {
435                let [a, b, c, d] = addr.octets();
436                uwrite!(f, "{}.{}.{}.{}", a, b, c, d)
437            }
438            std::net::IpAddr::V6(addr) => {
439                uwrite!(f, "{}", addr.to_string())
440            }
441        }
442    }
443}
444
445impl ufmt::uDisplay for Connection {
446    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
447    where
448        W: uWrite + ?Sized,
449    {
450        let Self { ip_ver, addr, mask } = self;
451        if let Some(mask) = mask {
452            uwrite!(f, "c=IN {} {}/{}", ip_ver, IpAddress(addr), mask)
453        } else {
454            uwrite!(f, "c=IN {} {}", ip_ver, IpAddress(addr))
455        }
456    }
457}
458impl ufmt::uDisplay for SsrcGroup {
459    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
460    where
461        W: uWrite + ?Sized,
462    {
463        uwrite!(f, "a=ssrc-group:")?;
464        match self.semantic {
465            SsrcSemantic::FID => uwrite!(f, "FID")?,
466            SsrcSemantic::FEC => uwrite!(f, "FEC")?,
467        }
468        for id in &self.ids {
469            uwrite!(f, " {}", id)?;
470        }
471        Ok(())
472    }
473}
474impl ufmt::uDisplay for Ssrc<'_> {
475    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
476    where
477        W: uWrite + ?Sized,
478    {
479        uwrite!(
480            f,
481            "a=ssrc:{} {}:{}",
482            self.id,
483            self.attribute.as_ref(),
484            self.value.as_ref()
485        )
486    }
487}
488impl ufmt::uDisplay for RtpMap<'_> {
489    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
490    where
491        W: uWrite + ?Sized,
492    {
493        uwrite!(
494            f,
495            "a=rtpmap:{} {}",
496            self.payload,
497            self.encoding_name.as_ref()
498        )?;
499        if let Some(clock_rate) = self.clock_rate {
500            uwrite!(f, "/{}", clock_rate)?;
501        }
502        if let Some(encoding) = self.encoding {
503            uwrite!(f, "/{}", encoding)?;
504        }
505        Ok(())
506    }
507}
508impl ufmt::uDisplay for PTime {
509    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
510    where
511        W: uWrite + ?Sized,
512    {
513        match self {
514            PTime::MaxPTime(x) => uwrite!(f, "a=maxptime:{}", x),
515            PTime::MinPTime(x) => uwrite!(f, "a=minptime:{}", x),
516            PTime::PTime(x) => uwrite!(f, "a=ptime:{}", x),
517        }
518    }
519}
520
521impl ufmt::uDisplay for FbAckParam<'_> {
522    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
523    where
524        W: uWrite + ?Sized,
525    {
526        match self {
527            FbAckParam::Rpsi => uwrite!(f, "rpsi"),
528            FbAckParam::Sli(Some(x)) => uwrite!(f, "sli {}", x.as_ref()),
529            FbAckParam::Sli(None) => uwrite!(f, "sli"),
530            FbAckParam::App(x) => uwrite!(f, "app {}", x.as_ref()),
531            FbAckParam::Other(k, Some(v)) => uwrite!(f, "{} {}", k.as_ref(), v.as_ref()),
532            FbAckParam::Other(k, None) => uwrite!(f, "{}", k.as_ref()),
533        }
534    }
535}
536
537impl ufmt::uDisplay for FbNackParam<'_> {
538    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
539    where
540        W: uWrite + ?Sized,
541    {
542        match self {
543            FbNackParam::Pli => uwrite!(f, "pli"),
544            FbNackParam::Rpsi => uwrite!(f, "rpsi"),
545            FbNackParam::Sli => uwrite!(f, "sli"),
546            FbNackParam::Other(k, v) => uwrite!(f, "{} {}", k.as_ref(), v.as_ref()),
547            FbNackParam::App(x) => uwrite!(f, "app {}", x.as_ref()),
548        }
549    }
550}
551
552impl ufmt::uDisplay for FbParam<'_> {
553    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
554    where
555        W: uWrite + ?Sized,
556    {
557        match self {
558            FbParam::App(p) => uwrite!(f, "app {}", p.as_ref()),
559            FbParam::Single(p) => uwrite!(f, "{}", p.as_ref()),
560            FbParam::Pair(k, v) => uwrite!(f, "{} {}", k.as_ref(), v.as_ref()),
561        }
562    }
563}
564
565impl ufmt::uDisplay for FbVal<'_> {
566    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
567    where
568        W: uWrite + ?Sized,
569    {
570        match self {
571            FbVal::Ack(p) => uwrite!(f, "ack {}", p),
572            FbVal::Nack(p) => uwrite!(f, "nack {}", p),
573            FbVal::TrrInt(p) => uwrite!(f, "trr-int {}", p),
574            FbVal::RtcpFbId {
575                id,
576                param: Some(param),
577            } => uwrite!(f, "{} {}", id.as_ref(), param),
578            FbVal::RtcpFbId { id, param: None } => uwrite!(f, "{}", id.as_ref()),
579        }
580    }
581}
582
583impl ufmt::uDisplay for Fb<'_> {
584    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
585    where
586        W: uWrite + ?Sized,
587    {
588        uwrite!(f, "a=rtcp-fb:{} {}", self.payload, self.val)
589    }
590}
591impl ufmt::uDisplay for NetType {
592    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
593    where
594        W: uWrite + ?Sized,
595    {
596        uwrite!(f, "IN")
597    }
598}
599
600impl ufmt::uDisplay for Rtcp {
601    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
602    where
603        W: uWrite + ?Sized,
604    {
605        uwrite!(
606            f,
607            "a=rtcp:{} {} {} {}",
608            self.port,
609            self.net_type,
610            self.ip_ver,
611            IpAddress(&self.addr),
612        )
613    }
614}
615
616impl ufmt::uDisplay for IceParameter<'_> {
617    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
618    where
619        W: uWrite + ?Sized,
620    {
621        match self {
622            IceParameter::Ufrag(ufrag) => uwrite!(f, "a=ice-ufrag:{}", ufrag.as_ref()),
623            IceParameter::Pwd(pwd) => uwrite!(f, "a=ice-pwd:{}", pwd.as_ref()),
624            IceParameter::Options(options) => uwrite!(f, "a=ice-options:{}", options.as_ref()),
625            IceParameter::Mismatch => uwrite!(f, "a=ice-mismatch"),
626            IceParameter::Lite => uwrite!(f, "a=ice-lite"),
627        }
628    }
629}
630
631impl ufmt::uDisplay for Extmap<'_> {
632    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
633    where
634        W: uWrite + ?Sized,
635    {
636        if let Some(direction) = self.direction {
637            uwrite!(f, "a=extmap:{}/", self.value,)?;
638
639            match direction {
640                Direction::SendOnly => uwrite!(f, "sendonly")?,
641                Direction::SendRecv => uwrite!(f, "sendrecv")?,
642                Direction::RecvOnly => uwrite!(f, "recvonly")?,
643                Direction::Inactive => uwrite!(f, "inactive")?,
644            }
645
646            uwrite!(f, " {}", self.uri.as_ref())?;
647        } else {
648            uwrite!(f, "a=extmap:{} {}", self.value, self.uri.as_ref())?;
649        }
650        for a in &self.attributes {
651            uwrite!(f, " {}", a.as_ref())?;
652        }
653        Ok(())
654    }
655}
656impl ufmt::uDisplay for BandWidthType {
657    #[rustfmt::skip]
658    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
659    where
660        W: uWrite + ?Sized, {
661        use BandWidthType::*;
662        uwrite!( f, "{}", match self { TIAS => "TIAS", AS => "AS", CT => "CT", RR => "RR", RS => "R" })
663    }
664}
665
666impl ufmt::uDisplay for BandWidth {
667    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
668    where
669        W: uWrite + ?Sized,
670    {
671        uwrite!(f, "b={}:{}", self.r#type, self.limit)
672    }
673}
674
675impl ufmt::uDisplay for Uri<'_> {
676    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
677    where
678        W: uWrite + ?Sized,
679    {
680        uwrite!(f, "u={}", self.0.as_ref())
681    }
682}
683impl ufmt::uDisplay for EmailAddress<'_> {
684    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
685    where
686        W: uWrite + ?Sized,
687    {
688        uwrite!(f, "e={}", self.0.as_ref())
689    }
690}
691impl ufmt::uDisplay for PhoneNumber<'_> {
692    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
693    where
694        W: uWrite + ?Sized,
695    {
696        uwrite!(f, "p={}", self.0.as_ref())
697    }
698}
699impl ufmt::uDisplay for Timing {
700    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
701    where
702        W: uWrite + ?Sized,
703    {
704        uwrite!(f, "t={} {}", self.start, self.stop)
705    }
706}
707
708impl ufmt::uDisplay for IpVer {
709    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
710    where
711        W: uWrite + ?Sized,
712    {
713        match self {
714            IpVer::Ip4 => uwrite!(f, "IP4"),
715            IpVer::Ip6 => uwrite!(f, "IP6"),
716        }
717    }
718}
719impl ufmt::uDisplay for CandidateComponent {
720    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
721    where
722        W: uWrite + ?Sized,
723    {
724        match self {
725            CandidateComponent::Rtp => uwrite!(f, "1"),
726            CandidateComponent::Rtcp => uwrite!(f, "2"),
727        }
728    }
729}
730
731impl ufmt::uDisplay for CandidateProtocol {
732    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
733    where
734        W: uWrite + ?Sized,
735    {
736        match self {
737            CandidateProtocol::Tcp => uwrite!(f, "tcp"),
738            CandidateProtocol::Udp => uwrite!(f, "udp"),
739            CandidateProtocol::Dccp => uwrite!(f, "dccp"),
740        }
741    }
742}
743
744impl ufmt::uDisplay for CandidateType {
745    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
746    where
747        W: uWrite + ?Sized,
748    {
749        match self {
750            CandidateType::Host => uwrite!(f, "host"),
751            CandidateType::Relay => uwrite!(f, "relay"),
752            CandidateType::Srflx => uwrite!(f, "srflx"),
753            CandidateType::Prflx => uwrite!(f, "prflx"),
754        }
755    }
756}
757
758impl ufmt::uDisplay for Candidate<'_> {
759    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
760    where
761        W: uWrite + ?Sized,
762    {
763        uwrite!(
764            f,
765            "a=candidate:{} {} {} {} {} {} typ {}",
766            self.foundation,
767            self.component,
768            self.protocol,
769            self.priority,
770            IpAddress(&self.addr),
771            self.port,
772            self.r#type,
773        )?;
774        if let Some(x) = self.raddr {
775            uwrite!(f, " raddr {}", IpAddress(&x))?;
776        }
777        if let Some(x) = self.rport {
778            uwrite!(f, " rport {}", x)?;
779        }
780        if let Some(x) = self.tcptype.as_ref() {
781            uwrite!(f, " tcptype {}", x.as_ref())?;
782        }
783        if let Some(x) = self.generation {
784            uwrite!(f, " generation {}", x)?;
785        }
786        if let Some(x) = self.network_id {
787            uwrite!(f, " network-id {}", x)?;
788        }
789        Ok(())
790    }
791}
792
793impl ufmt::uDisplay for SetupRole {
794    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>
795    where
796        W: uWrite + ?Sized,
797    {
798        match self {
799            SetupRole::Active => uwrite!(f, "a=setup:active"),
800            SetupRole::Passive => uwrite!(f, "a=setup:passive"),
801            SetupRole::ActPass => uwrite!(f, "a=setup:actpass"),
802        }
803    }
804}