1use std::{error::Error, fmt, str::FromStr};
6
7#[derive(Clone, Debug, PartialEq, Eq, Hash)]
9pub struct Urn {
10 pub owner: String,
15
16 pub id: String,
19}
20
21impl fmt::Display for Urn {
22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 write!(f, "extension:{}:{}", self.owner, self.id)
24 }
25}
26
27#[derive(Debug, PartialEq)]
29pub struct InvalidUrn;
30
31impl fmt::Display for InvalidUrn {
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 write!(f, "invalid urn")
34 }
35}
36
37impl Error for InvalidUrn {}
38
39impl FromStr for Urn {
40 type Err = InvalidUrn;
41
42 fn from_str(s: &str) -> Result<Self, Self::Err> {
43 if let Some(("extension", segments)) = s.split_once(":")
44 && let Some((owner, id)) = segments.split_once(":")
45 && !owner.is_empty()
46 && !id.is_empty()
47 {
48 Ok(Urn {
49 owner: owner.to_string(),
50 id: id.to_string(),
51 })
52 } else {
53 Err(InvalidUrn)
54 }
55 }
56}