ftth_rsip/headers/typed/
via.rs

1#[doc(hidden)]
2pub use super::tokenizers::ViaTokenizer as Tokenizer;
3
4use crate::{
5    common::{
6        uri::{self, param::Branch, Param, Uri},
7        Transport, Version,
8    },
9    Error,
10};
11use rsip_derives::{TypedHeader, UriAndParamsHelpers};
12use std::{
13    convert::{TryFrom, TryInto},
14    net::IpAddr,
15};
16
17/// The `Via` header in its [typed](super) form.
18#[derive(TypedHeader, UriAndParamsHelpers, Eq, PartialEq, Clone, Debug)]
19pub struct Via {
20    pub version: Version,
21    pub transport: Transport,
22    //TODO: rename to sent-by ?
23    pub uri: Uri,
24    pub params: Vec<uri::Param>,
25}
26
27impl Via {
28    pub fn branch(&self) -> Result<&Branch, Error> {
29        self.params
30            .iter()
31            .find_map(|param| match param {
32                Param::Branch(branch) => Some(branch),
33                _ => None,
34            })
35            .ok_or_else(|| Error::missing_param("branch"))
36    }
37
38    pub fn received(&self) -> Result<Option<IpAddr>, std::net::AddrParseError> {
39        self.params
40            .iter()
41            .find_map(|param| match param {
42                Param::Received(received) => Some(received.parse()),
43                _ => None,
44            })
45            .transpose()
46    }
47
48    pub fn sent_by(&self) -> &Uri {
49        &self.uri
50    }
51
52    pub fn sent_protocol(&self) -> &Transport {
53        &self.transport
54    }
55}
56
57impl<'a> TryFrom<Tokenizer<'a>> for Via {
58    type Error = crate::Error;
59
60    fn try_from(tokenizer: Tokenizer) -> Result<Self, Self::Error> {
61        Ok(Via {
62            version: tokenizer.version.try_into()?,
63            transport: tokenizer.transport.try_into()?,
64            uri: tokenizer.uri.try_into()?,
65            params: tokenizer
66                .params
67                .into_iter()
68                .map(TryInto::try_into)
69                .collect::<Result<Vec<_>, _>>()?,
70        })
71    }
72}
73
74impl std::fmt::Display for Via {
75    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76        write!(
77            f,
78            "{}/{} {}{}",
79            self.version,
80            self.transport,
81            self.uri,
82            self.params
83                .iter()
84                .map(|s| s.to_string())
85                .collect::<Vec<_>>()
86                .join("")
87        )
88    }
89}
90
91impl std::convert::From<crate::common::Uri> for Via {
92    fn from(uri: crate::common::Uri) -> Self {
93        Self {
94            version: Default::default(),
95            transport: Default::default(),
96            uri,
97            params: vec![Param::Branch(Default::default())],
98        }
99    }
100}