1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
use std::{
    fmt::{self, Display, Formatter},
    str::FromStr,
};

use str_reader::StringReader;

use crate::{AddressType, NetworkType, ParseError};

/// SDP origin.
#[derive(Clone)]
pub struct Origin {
    username: String,
    session_id: u64,
    session_version: u64,
    network_type: NetworkType,
    address_type: AddressType,
    unicast_address: String,
}

impl Origin {
    /// Create a new origin.
    #[inline]
    pub fn new<U, A>(
        username: U,
        session_id: u64,
        session_version: u64,
        network_type: NetworkType,
        address_type: AddressType,
        unicast_address: A,
    ) -> Self
    where
        U: ToString,
        A: ToString,
    {
        Self {
            username: username.to_string(),
            session_id,
            session_version,
            network_type,
            address_type,
            unicast_address: unicast_address.to_string(),
        }
    }

    /// Get the username.
    #[inline]
    pub fn username(&self) -> &str {
        &self.username
    }

    /// Get the session ID.
    #[inline]
    pub fn session_id(&self) -> u64 {
        self.session_id
    }

    /// Get the session version.
    #[inline]
    pub fn session_version(&self) -> u64 {
        self.session_version
    }

    /// Get the network type.
    #[inline]
    pub fn network_type(&self) -> &NetworkType {
        &self.network_type
    }

    /// Get the address type.
    #[inline]
    pub fn address_type(&self) -> &AddressType {
        &self.address_type
    }

    /// Get the unicast address.
    #[inline]
    pub fn unicast_address(&self) -> &str {
        &self.unicast_address
    }
}

impl Default for Origin {
    #[inline]
    fn default() -> Self {
        Self {
            username: String::from("-"),
            session_id: 0,
            session_version: 0,
            network_type: NetworkType::Internet,
            address_type: AddressType::IPv4,
            unicast_address: String::from("0.0.0.0"),
        }
    }
}

impl Display for Origin {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(
            f,
            "{} {} {} {} {} {}",
            self.username,
            self.session_id,
            self.session_version,
            self.network_type,
            self.address_type,
            self.unicast_address
        )
    }
}

impl FromStr for Origin {
    type Err = ParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut reader = StringReader::new(s);

        let username = reader.read_word().to_string();
        let session_id = reader.read_u64()?;
        let session_version = reader.read_u64()?;
        let network_type = reader.parse_word()?;
        let address_type = reader.parse_word()?;
        let unicast_address = reader.read_word().to_string();

        reader.skip_whitespace();

        if unicast_address.is_empty() || !reader.is_empty() {
            return Err(ParseError::plain());
        }

        let res = Self {
            username,
            session_id,
            session_version,
            network_type,
            address_type,
            unicast_address,
        };

        Ok(res)
    }
}