kotlin_poet_rs/spec/
package.rs

1use std::str::FromStr;
2use crate::io::{RenderKotlin};
3use crate::tokens::DOT;
4use crate::spec::{CodeBlock, Name};
5use crate::util::{SemanticConversionError, yolo_from_str};
6
7/// Fully qualified package name, may be parsed from [&str]
8///
9/// # Examples
10///
11/// ## Parse from string
12/// ```rust
13/// use std::str::FromStr;
14/// use kotlin_poet_rs::io::RenderKotlin;
15/// use kotlin_poet_rs::spec::Package;
16///
17/// let package = Package::from_str("io.github.lexadiky").unwrap();
18///
19/// assert_eq!(
20///     package.render_string(),
21///     "io.github.lexadiky"
22/// );
23/// ```
24///
25/// ## Create from [Vec<Name>]
26/// ```rust
27/// use std::str::FromStr;
28/// use kotlin_poet_rs::io::RenderKotlin;
29/// use kotlin_poet_rs::spec::{Name, Package};
30///
31/// let package = Package::from(vec![
32///     Name::from("io"),
33///     Name::from("github"),
34///     Name::from("lexadiky"),
35/// ]);
36///
37/// assert_eq!(
38///     package.render_string(),
39///     "io.github.lexadiky"
40/// );
41/// ```
42///
43/// ## Create root
44/// ```rust
45/// use std::str::FromStr;
46/// use kotlin_poet_rs::io::RenderKotlin;
47/// use kotlin_poet_rs::spec::{Name, Package};
48///
49/// let package = Package::root();
50///
51/// assert_eq!(
52///     package.render_string(),
53///     ""
54/// );
55/// ```
56#[derive(Debug, PartialEq, Clone)]
57pub struct Package {
58    pub(crate) parts: Vec<Name>,
59}
60
61impl Package {
62    /// Creates new package from [Name] parts
63    pub fn from(names: Vec<Name>) -> Package {
64        Package { parts: names }
65    }
66
67    /// Create root package
68    pub fn root() -> Package {
69        Package { parts: Vec::new() }
70    }
71}
72
73yolo_from_str!(Package);
74impl FromStr for Package {
75    type Err = SemanticConversionError;
76
77    fn from_str(s: &str) -> Result<Self, Self::Err> {
78        let parts = s.split(DOT)
79            .filter(|part| !part.is_empty())
80            .map(Name::from_str)
81            .collect::<Result<Vec<_>, SemanticConversionError>>()?;
82        Ok(Package::from(parts))
83    }
84}
85
86impl RenderKotlin for Package {
87    fn render_into(&self, block: &mut CodeBlock) {
88        for (index, part) in self.parts.iter().enumerate() {
89            block.push_renderable(part);
90            if index != self.parts.len() - 1 {
91                block.push_atom(DOT);
92            }
93        }
94    }
95}
96
97#[cfg(test)]
98mod tests {
99    use std::str::FromStr;
100    use crate::io::RenderKotlin;
101    use crate::spec::{Name, Package};
102
103    #[test]
104    fn parse_package() {
105        let package: Package = "io.github.lexadiky".parse().unwrap();
106        assert_eq!(package.parts, vec![
107            Name::from_str("io").unwrap(),
108            Name::from_str("github").unwrap(),
109            Name::from_str("lexadiky").unwrap(),
110        ]);
111    }
112
113    #[test]
114    fn parse_empty_package() {
115        let package: Package = "".parse().unwrap();
116        assert_eq!(package.parts, vec![]);
117    }
118
119    #[test]
120    fn render_kotlin() {
121        let package: Package = "io.github.lexadiky".parse().unwrap();
122        assert_eq!(package.render_string(), "io.github.lexadiky");
123    }
124
125    #[test]
126    fn render_empty() {
127        let package: Package = Package::from(vec![]);
128        assert_eq!(package.render_string(), "");
129    }
130}