1use std::str::FromStr;
2use dcbor::prelude::*;
3use url::Url;
4use anyhow::{ bail, Result, Error };
5
6use crate::tags;
7
8#[derive(Clone, Debug, Eq, PartialEq, Hash)]
19pub struct URI(String);
20
21impl URI {
22 pub fn new(uri: impl Into<String>) -> Result<Self> {
26 let uri = uri.into();
27 if Url::parse(&uri).is_ok() {
28 Ok(Self(uri))
29 } else {
30 bail!("Invalid URI")
31 }
32 }
33}
34
35impl FromStr for URI {
37 type Err = Error;
38
39 fn from_str(s: &str) -> Result<Self, Self::Err> {
40 Self::new(s)
41 }
42}
43
44impl AsRef<str> for URI {
46 fn as_ref(&self) -> &str {
47 &self.0
48 }
49}
50
51impl AsRef<String> for URI {
53 fn as_ref(&self) -> &String {
54 &self.0
55 }
56}
57
58impl AsRef<URI> for URI {
60 fn as_ref(&self) -> &URI {
61 self
62 }
63}
64
65impl CBORTagged for URI {
67 fn cbor_tags() -> Vec<Tag> {
68 tags_for_values(&[tags::TAG_URI])
69 }
70}
71
72impl From<URI> for CBOR {
74 fn from(value: URI) -> Self {
75 value.tagged_cbor()
76 }
77}
78
79impl CBORTaggedEncodable for URI {
81 fn untagged_cbor(&self) -> CBOR {
82 self.0.clone().into()
83 }
84}
85
86impl TryFrom<CBOR> for URI {
88 type Error = dcbor::Error;
89
90 fn try_from(cbor: CBOR) -> dcbor::Result<Self> {
91 Self::from_tagged_cbor(cbor)
92 }
93}
94
95impl CBORTaggedDecodable for URI {
97 fn from_untagged_cbor(cbor: CBOR) -> dcbor::Result<Self> {
98 let uri: String = cbor.try_into()?;
99 Ok(Self::new(uri)?)
100 }
101}
102
103impl std::fmt::Display for URI {
105 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
106 write!(f, "{}", self.0)
107 }
108}
109
110impl TryFrom<&str> for URI {
112 type Error = Error;
113
114 fn try_from(uri: &str) -> Result<Self, Self::Error> {
115 Self::new(uri)
116 }
117}
118
119impl TryFrom<String> for URI {
121 type Error = Error;
122
123 fn try_from(uri: String) -> Result<Self, Self::Error> {
124 Self::try_from(uri.as_str())
125 }
126}
127
128impl From<URI> for String {
130 fn from(uri: URI) -> Self {
131 uri.0
132 }
133}
134
135impl From<&URI> for String {
137 fn from(uri: &URI) -> Self {
138 uri.0.clone()
139 }
140}