shex_ast/ast/
iri_or_str.rs

1use iri_s::{IriS, IriSError};
2use serde::{Deserialize, Serialize};
3use std::fmt::Display;
4use std::str::FromStr;
5use void::Void;
6
7/// IriOrStr represents either an IRI or a String.
8/// This enum is used mainly for parsing ShEx schemas which contain an import declaration
9/// The value of the import declaration can be a well formed IRI or a relative IRI which is kept as a string
10#[derive(Deserialize, Serialize, Debug, PartialEq, Hash, Eq, Clone)]
11#[serde(try_from = "String", into = "String")]
12pub enum IriOrStr {
13    String(String),
14    IriS(IriS),
15}
16
17impl IriOrStr {
18    pub fn new(str: &str) -> IriOrStr {
19        IriOrStr::String(str.to_string())
20    }
21
22    pub fn iri(iri: IriS) -> IriOrStr {
23        IriOrStr::IriS(iri)
24    }
25
26    /// Converts a `Iri`` represented as a `String` into an parsed Iri represented by a `IriS`
27    /// `base` is useful to obtain an absolute Iri
28    pub fn resolve(&mut self, base: Option<IriS>) -> Result<IriOrStr, IriSError> {
29        match self {
30            IriOrStr::String(s) => match base {
31                None => {
32                    let iri = IriS::from_str(s.as_str())?;
33                    Ok(IriOrStr::IriS(iri))
34                }
35                Some(base) => {
36                    let iri = base.clone().extend(s)?;
37                    Ok(IriOrStr::IriS(iri))
38                }
39            },
40            IriOrStr::IriS(_) => Ok(self.clone()),
41        }
42    }
43}
44
45impl Display for IriOrStr {
46    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47        let str = match self {
48            IriOrStr::String(s) => s,
49            IriOrStr::IriS(iri_s) => iri_s.as_str(),
50        };
51        write!(f, "{}", str)
52    }
53}
54
55// This is required by serde serialization
56impl From<IriOrStr> for String {
57    fn from(val: IriOrStr) -> Self {
58        match val {
59            IriOrStr::String(s) => s,
60            IriOrStr::IriS(iri_s) => iri_s.as_str().to_string(),
61        }
62    }
63}
64
65impl TryFrom<String> for IriOrStr {
66    type Error = Void;
67    fn try_from(s: String) -> Result<Self, Self::Error> {
68        Ok(IriOrStr::String(s))
69    }
70}