Skip to main content

mz_repr/
network_policy_id.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10use std::fmt;
11use std::str::FromStr;
12
13use anyhow::{Error, anyhow};
14#[cfg(any(test, feature = "proptest"))]
15use proptest_derive::Arbitrary;
16use serde::{Deserialize, Serialize};
17
18const SYSTEM_CHAR: char = 's';
19const USER_CHAR: char = 'u';
20
21/// The identifier for a network policy.
22#[derive(
23    Clone,
24    Copy,
25    Debug,
26    Eq,
27    PartialEq,
28    Ord,
29    PartialOrd,
30    Hash,
31    Serialize,
32    Deserialize
33)]
34#[cfg_attr(any(test, feature = "proptest"), derive(Arbitrary))]
35pub enum NetworkPolicyId {
36    System(u64),
37    User(u64),
38}
39
40impl NetworkPolicyId {
41    pub fn is_system(&self) -> bool {
42        matches!(self, Self::System(_))
43    }
44
45    pub fn is_user(&self) -> bool {
46        matches!(self, Self::User(_))
47    }
48
49    pub fn is_builtin(&self) -> bool {
50        self.is_system()
51    }
52}
53
54impl FromStr for NetworkPolicyId {
55    type Err = Error;
56
57    fn from_str(s: &str) -> Result<Self, Self::Err> {
58        fn parse_u64(s: &str) -> Result<u64, Error> {
59            if s.len() < 2 {
60                return Err(anyhow!("couldn't parse network policy id '{s}'"));
61            }
62            s[1..]
63                .parse()
64                .map_err(|_| anyhow!("couldn't parse network policy  id '{s}'"))
65        }
66
67        match s.chars().next() {
68            Some(SYSTEM_CHAR) => {
69                let val = parse_u64(s)?;
70                Ok(Self::System(val))
71            }
72            Some(USER_CHAR) => {
73                let val = parse_u64(s)?;
74                Ok(Self::User(val))
75            }
76            _ => Err(anyhow!("couldn't parse network policy  id '{s}'")),
77        }
78    }
79}
80
81impl fmt::Display for NetworkPolicyId {
82    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
83        match self {
84            Self::System(id) => write!(f, "{SYSTEM_CHAR}{id}"),
85            Self::User(id) => write!(f, "{USER_CHAR}{id}"),
86        }
87    }
88}
89
90#[mz_ore::test]
91fn test_network_policy_id_parsing() {
92    let s = "s42";
93    let network_policy_id: NetworkPolicyId = s.parse().unwrap();
94    assert_eq!(NetworkPolicyId::System(42), network_policy_id);
95    assert_eq!(s, network_policy_id.to_string());
96
97    let s = "u666";
98    let network_policy_id: NetworkPolicyId = s.parse().unwrap();
99    assert_eq!(NetworkPolicyId::User(666), network_policy_id);
100    assert_eq!(s, network_policy_id.to_string());
101
102    let s = "d23";
103    mz_ore::assert_err!(s.parse::<NetworkPolicyId>());
104
105    let s = "asfje90uf23i";
106    mz_ore::assert_err!(s.parse::<NetworkPolicyId>());
107
108    let s = "";
109    mz_ore::assert_err!(s.parse::<NetworkPolicyId>());
110}