architect_api/cpty/
cpty_id.rs1use anyhow::bail;
2use ecow::EcoString;
3use serde_with::{DeserializeFromStr, SerializeDisplay};
4
5#[derive(
9 Debug,
10 Clone,
11 PartialEq,
12 Eq,
13 PartialOrd,
14 Ord,
15 Hash,
16 SerializeDisplay,
17 DeserializeFromStr,
18)]
19pub struct CptyId {
20 pub kind: EcoString,
21 pub instance: Option<EcoString>,
22}
23
24impl CptyId {
25 pub const fn inline(kind: &'static str, instance: Option<&'static str>) -> Self {
26 Self {
27 kind: EcoString::inline(kind),
28 instance: match instance {
29 Some(s) => Some(EcoString::inline(s)),
30 None => None,
31 },
32 }
33 }
34}
35
36impl std::fmt::Display for CptyId {
37 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38 write!(f, "{}", self.kind)?;
39 if let Some(instance) = &self.instance {
40 write!(f, "({instance})")?;
41 }
42 Ok(())
43 }
44}
45
46impl std::str::FromStr for CptyId {
47 type Err = anyhow::Error;
48
49 fn from_str(s: &str) -> Result<Self, Self::Err> {
50 match s.split_once('(') {
51 Some((kind, instance_and_paren)) => {
52 match instance_and_paren.strip_suffix(')') {
53 Some(instance) => {
54 Ok(Self { kind: kind.into(), instance: Some(instance.into()) })
55 }
56 None => bail!("invalid cpty id, missing closing paren: {s}"),
57 }
58 }
59 None => Ok(Self { kind: s.into(), instance: None }),
60 }
61 }
62}