1use crate::PrefixMap;
2use crate::error::{DerefError, IriRefError, PrefixMapError};
3use crate::iri::deref_iri::DerefIri;
4use iri_s::IriS;
5use iri_s::error::IriSError;
6use serde::Serialize;
7use std::borrow::Cow;
8use std::{fmt::Display, str::FromStr};
9
10#[derive(Serialize, Debug, PartialEq, Hash, Eq, Clone, PartialOrd, Ord)]
13#[serde(into = "String")]
14pub enum IriRef {
15 Iri(IriS),
16 Prefixed { prefix: String, local: String },
17}
18
19impl IriRef {
21 pub fn get_iri(&self) -> Result<&IriS, IriRefError> {
27 match self {
28 IriRef::Iri(iri) => Ok(iri),
29 IriRef::Prefixed { prefix, local } => Err(IriRefError {
30 prefix: prefix.clone(),
31 local: local.clone(),
32 }),
33 }
34 }
35
36 pub fn get_iri_prefixmap(&self, prefixmap: &PrefixMap) -> Result<Cow<'_, IriS>, PrefixMapError> {
41 match self {
42 IriRef::Iri(iri) => Ok(Cow::Borrowed(iri)),
43 IriRef::Prefixed { prefix, local } => prefixmap.resolve_prefix_local(prefix, local).map(Cow::Owned),
44 }
45 }
46
47 pub fn prefixed<S: Into<String>>(prefix: S, local: S) -> IriRef {
49 IriRef::Prefixed {
50 prefix: prefix.into(),
51 local: local.into(),
52 }
53 }
54
55 pub fn iri(iri: IriS) -> IriRef {
57 IriRef::Iri(iri)
58 }
59}
60
61impl DerefIri for IriRef {
62 fn deref_iri(self, base: Option<&IriS>, prefixmap: Option<&PrefixMap>) -> Result<Self, DerefError> {
63 match self {
64 IriRef::Iri(iri_s) => {
65 let resolved = match base {
66 None => iri_s,
67 Some(base) => base.resolve(iri_s)?,
68 };
69 Ok(IriRef::Iri(resolved))
70 },
71 IriRef::Prefixed { prefix, local } => {
72 let prefixmap = match prefixmap {
73 None => return Err(DerefError::NoPrefixMapPrefixedName { prefix, local }),
74 Some(pm) => pm,
75 };
76
77 let iri =
78 prefixmap
79 .resolve_prefix_local(&prefix, &local)
80 .map_err(|e| DerefError::DerefPrefixMapError {
81 alias: prefix,
82 local,
83 error: Box::new(e),
84 })?;
85
86 Ok(IriRef::Iri(iri))
87 },
88 }
89 }
90}
91
92impl TryFrom<&str> for IriRef {
93 type Error = IriSError;
94
95 fn try_from(value: &str) -> Result<Self, Self::Error> {
96 FromStr::from_str(value)
97 }
98}
99
100impl FromStr for IriRef {
101 type Err = IriSError;
102
103 fn from_str(s: &str) -> Result<Self, Self::Err> {
104 Ok(IriRef::Iri(IriS::from_str(s)?))
105 }
106}
107
108impl From<IriRef> for IriS {
109 fn from(iri_ref: IriRef) -> IriS {
110 match iri_ref {
111 IriRef::Iri(iri_s) => iri_s,
112 IriRef::Prefixed { prefix, local } => {
113 panic!("Cannot convert prefixed name {prefix}:{local} to IriS without context")
114 },
115 }
116 }
117}
118
119impl From<IriS> for IriRef {
120 fn from(i: IriS) -> IriRef {
121 IriRef::Iri(i)
122 }
123}
124
125impl From<IriRef> for String {
126 fn from(iri_ref: IriRef) -> String {
127 match iri_ref {
128 IriRef::Iri(i) => i.as_str().to_string(),
129 IriRef::Prefixed { prefix, local } => format!("{prefix}:{local}"),
130 }
131 }
132}
133
134impl Display for IriRef {
135 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
136 match self {
137 IriRef::Iri(i) => write!(f, "{i}"),
138 IriRef::Prefixed { prefix, local } => write!(f, "{prefix}:{local}"),
139 }
140 }
141}