Skip to main content

firebase_admin/core/
project.rs

1//! Firebase/GCP project identifier handling.
2
3use crate::core::error::CoreError;
4
5/// A validated Firebase/GCP project identifier.
6#[derive(Debug, Clone, PartialEq, Eq, Hash)]
7pub struct ProjectId(String);
8
9impl ProjectId {
10    /// Creates a new [`ProjectId`], rejecting empty strings.
11    pub fn new(id: impl Into<String>) -> Result<Self, CoreError> {
12        let id = id.into();
13        if id.trim().is_empty() {
14            return Err(CoreError::InvalidProjectId(
15                "project id must not be empty".to_string(),
16            ));
17        }
18        Ok(Self(id))
19    }
20
21    /// Returns the project id as a string slice.
22    pub fn as_str(&self) -> &str {
23        &self.0
24    }
25}
26
27impl std::fmt::Display for ProjectId {
28    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29        f.write_str(&self.0)
30    }
31}
32
33#[cfg(test)]
34mod tests {
35    use super::*;
36
37    #[test]
38    fn accepts_a_non_empty_id() {
39        let id = ProjectId::new("my-project").unwrap();
40        assert_eq!(id.as_str(), "my-project");
41        assert_eq!(id.to_string(), "my-project");
42    }
43
44    #[test]
45    fn rejects_an_empty_id() {
46        assert!(matches!(
47            ProjectId::new(""),
48            Err(CoreError::InvalidProjectId(_))
49        ));
50    }
51
52    #[test]
53    fn rejects_a_whitespace_only_id() {
54        assert!(matches!(
55            ProjectId::new("   "),
56            Err(CoreError::InvalidProjectId(_))
57        ));
58    }
59}