prefixmap/
iri_ref.rs

1use std::{fmt::Display, str::FromStr};
2
3use crate::PrefixMap;
4use crate::{Deref, DerefError};
5use iri_s::{IriS, IriSError};
6use serde::{Deserialize, Serialize};
7use thiserror::Error;
8
9#[derive(Deserialize, Serialize, Debug, PartialEq, Hash, Eq, Clone)]
10#[serde(try_from = "&str", into = "String")]
11pub enum IriRef {
12    Iri(IriS),
13    Prefixed { prefix: String, local: String },
14}
15
16#[derive(Debug, Error)]
17#[error("Cannot obtain IRI from prefixed name IriRef {prefix}:{local}")]
18pub struct Underef {
19    prefix: String,
20    local: String,
21}
22
23impl IriRef {
24    pub fn get_iri(&self) -> Result<IriS, Underef> {
25        match self {
26            IriRef::Iri(iri) => Ok(iri.clone()),
27            IriRef::Prefixed { prefix, local } => Err(Underef {
28                prefix: prefix.clone(),
29                local: local.clone(),
30            }),
31        }
32    }
33    pub fn prefixed(prefix: &str, local: &str) -> IriRef {
34        IriRef::Prefixed {
35            prefix: prefix.to_string(),
36            local: local.to_string(),
37        }
38    }
39
40    pub fn iri(iri: IriS) -> IriRef {
41        IriRef::Iri(iri)
42    }
43}
44
45impl Deref for IriRef {
46    fn deref(
47        &self,
48        base: &Option<IriS>,
49        prefixmap: &Option<PrefixMap>,
50    ) -> Result<Self, DerefError> {
51        match self {
52            IriRef::Iri(iri_s) => match base {
53                None => Ok(IriRef::Iri(iri_s.clone())),
54                Some(base_iri) => {
55                    let iri = base_iri.resolve(iri_s.clone())?;
56                    Ok(IriRef::Iri(iri))
57                }
58            },
59            IriRef::Prefixed { prefix, local } => match prefixmap {
60                None => Err(DerefError::NoPrefixMapPrefixedName {
61                    prefix: prefix.clone(),
62                    local: local.clone(),
63                }),
64                Some(prefixmap) => {
65                    let iri = prefixmap.resolve_prefix_local(prefix, local)?;
66                    Ok(IriRef::Iri(iri))
67                }
68            },
69        }
70    }
71}
72
73impl TryFrom<&str> for IriRef {
74    type Error = IriSError;
75
76    fn try_from(value: &str) -> Result<Self, Self::Error> {
77        FromStr::from_str(value)
78    }
79}
80
81impl FromStr for IriRef {
82    type Err = IriSError;
83
84    fn from_str(s: &str) -> Result<Self, Self::Err> {
85        let iri_s = IriS::from_str(s)?;
86        Ok(IriRef::Iri(iri_s))
87    }
88}
89
90impl From<IriRef> for IriS {
91    fn from(iri_ref: IriRef) -> IriS {
92        match iri_ref {
93            IriRef::Iri(iri_s) => iri_s,
94            IriRef::Prefixed { prefix, local } => {
95                panic!("Cannot convert prefixed name {prefix}:{local} to IriS without context")
96            }
97        }
98    }
99}
100
101impl From<IriS> for IriRef {
102    fn from(i: IriS) -> IriRef {
103        IriRef::Iri(i)
104    }
105}
106
107impl From<IriRef> for String {
108    fn from(iri_ref: IriRef) -> String {
109        match iri_ref {
110            IriRef::Iri(i) => i.as_str().to_string(),
111            IriRef::Prefixed { prefix, local } => format!("{prefix}:{local}"),
112        }
113    }
114}
115
116impl Display for IriRef {
117    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
118        match self {
119            IriRef::Iri(i) => write!(f, "{i}")?,
120            IriRef::Prefixed { prefix, local } => write!(f, "{prefix}:{local}")?,
121        }
122        Ok(())
123    }
124}