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};
14use mz_lowertest::MzReflect;
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    Arbitrary,
24    Clone,
25    Copy,
26    Debug,
27    Eq,
28    PartialEq,
29    Ord,
30    PartialOrd,
31    Hash,
32    Serialize,
33    Deserialize,
34    MzReflect
35)]
36pub enum NetworkPolicyId {
37    System(u64),
38    User(u64),
39}
40
41impl NetworkPolicyId {
42    pub fn is_system(&self) -> bool {
43        matches!(self, Self::System(_))
44    }
45
46    pub fn is_user(&self) -> bool {
47        matches!(self, Self::User(_))
48    }
49
50    pub fn is_builtin(&self) -> bool {
51        self.is_system()
52    }
53}
54
55impl FromStr for NetworkPolicyId {
56    type Err = Error;
57
58    fn from_str(s: &str) -> Result<Self, Self::Err> {
59        fn parse_u64(s: &str) -> Result<u64, Error> {
60            if s.len() < 2 {
61                return Err(anyhow!("couldn't parse network policy id '{s}'"));
62            }
63            s[1..]
64                .parse()
65                .map_err(|_| anyhow!("couldn't parse network policy  id '{s}'"))
66        }
67
68        match s.chars().next() {
69            Some(SYSTEM_CHAR) => {
70                let val = parse_u64(s)?;
71                Ok(Self::System(val))
72            }
73            Some(USER_CHAR) => {
74                let val = parse_u64(s)?;
75                Ok(Self::User(val))
76            }
77            _ => Err(anyhow!("couldn't parse network policy  id '{s}'")),
78        }
79    }
80}
81
82impl fmt::Display for NetworkPolicyId {
83    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
84        match self {
85            Self::System(id) => write!(f, "{SYSTEM_CHAR}{id}"),
86            Self::User(id) => write!(f, "{USER_CHAR}{id}"),
87        }
88    }
89}
90
91#[mz_ore::test]
92fn test_network_policy_id_parsing() {
93    let s = "s42";
94    let network_policy_id: NetworkPolicyId = s.parse().unwrap();
95    assert_eq!(NetworkPolicyId::System(42), network_policy_id);
96    assert_eq!(s, network_policy_id.to_string());
97
98    let s = "u666";
99    let network_policy_id: NetworkPolicyId = s.parse().unwrap();
100    assert_eq!(NetworkPolicyId::User(666), network_policy_id);
101    assert_eq!(s, network_policy_id.to_string());
102
103    let s = "d23";
104    mz_ore::assert_err!(s.parse::<NetworkPolicyId>());
105
106    let s = "asfje90uf23i";
107    mz_ore::assert_err!(s.parse::<NetworkPolicyId>());
108
109    let s = "";
110    mz_ore::assert_err!(s.parse::<NetworkPolicyId>());
111}