Skip to content

Commit b98e8e6

Browse files
authored
Expose Key Vault URI parsing (Azure#2101)
Makes deconstruct accessible through TryFrom, FromStr traits. I found this while dogfooding our crates.
1 parent e5cf33d commit b98e8e6

File tree

2 files changed

+127
-20
lines changed

2 files changed

+127
-20
lines changed

sdk/keyvault/azure_security_keyvault_keys/src/resource.rs

Lines changed: 62 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#[cfg(doc)]
55
use crate::{models::KeyBundle, KeyClient};
66
use azure_core::{error::ErrorKind, Result, Url};
7+
use std::str::FromStr;
78

89
/// Information about the resource.
910
///
@@ -23,6 +24,27 @@ pub struct ResourceId {
2324
pub version: Option<String>,
2425
}
2526

27+
impl FromStr for ResourceId {
28+
type Err = azure_core::Error;
29+
fn from_str(s: &str) -> Result<Self> {
30+
s.parse::<Url>()?.try_into()
31+
}
32+
}
33+
34+
impl TryFrom<Url> for ResourceId {
35+
type Error = azure_core::Error;
36+
fn try_from(url: Url) -> Result<Self> {
37+
ResourceId::try_from(&url)
38+
}
39+
}
40+
41+
impl TryFrom<&Url> for ResourceId {
42+
type Error = azure_core::Error;
43+
fn try_from(url: &Url) -> Result<Self> {
44+
deconstruct(url)
45+
}
46+
}
47+
2648
/// Extension methods to get a [`ResourceId`] from models in this crate.
2749
pub trait ResourceExt {
2850
/// Gets the [`ResourceId`] from this model.
@@ -64,11 +86,11 @@ where
6486
};
6587

6688
let url: Url = id.parse()?;
67-
deconstruct(url)
89+
deconstruct(&url)
6890
}
6991
}
7092

71-
fn deconstruct(url: Url) -> Result<ResourceId> {
93+
fn deconstruct(url: &Url) -> Result<ResourceId> {
7294
let vault_url = format!("{}://{}", url.scheme(), url.authority(),);
7395
let mut segments = url
7496
.path_segments()
@@ -147,17 +169,47 @@ mod tests {
147169

148170
use super::*;
149171

172+
#[test]
173+
fn try_from_str() {
174+
assert_eq!(
175+
"https://vault.azure.net/keys/name/version"
176+
.parse::<ResourceId>()
177+
.unwrap(),
178+
ResourceId {
179+
source_id: "https://vault.azure.net/keys/name/version".to_string(),
180+
vault_url: "https://vault.azure.net".into(),
181+
name: "name".into(),
182+
version: Some("version".into()),
183+
}
184+
);
185+
}
186+
187+
#[test]
188+
fn try_from_url() {
189+
let url: Url = "https://vault.azure.net/keys/name/version".parse().unwrap();
190+
let resource: ResourceId = url.try_into().unwrap();
191+
assert_eq!(
192+
resource,
193+
ResourceId {
194+
source_id: "https://vault.azure.net/keys/name/version".to_string(),
195+
vault_url: "https://vault.azure.net".into(),
196+
name: "name".into(),
197+
version: Some("version".into()),
198+
}
199+
);
200+
}
201+
150202
#[test]
151203
fn test_deconstruct() {
152-
deconstruct("file:///tmp".parse().unwrap()).expect_err("cannot-be-base url");
153-
deconstruct("https://vault.azure.net/".parse().unwrap()).expect_err("missing collection");
154-
deconstruct("https://vault.azure.net/collection/".parse().unwrap())
204+
deconstruct(&"file:///tmp".parse().unwrap()).expect_err("cannot-be-base url");
205+
deconstruct(&"https://vault.azure.net/".parse().unwrap()).expect_err("missing collection");
206+
deconstruct(&"https://vault.azure.net/collection/".parse().unwrap())
155207
.expect_err("invalid collection");
156-
deconstruct("https://vault.azure.net/keys/".parse().unwrap()).expect_err("missing name");
208+
deconstruct(&"https://vault.azure.net/keys/".parse().unwrap()).expect_err("missing name");
157209

158210
let url: Url = "https://vault.azure.net/keys/name".parse().unwrap();
159211
assert_eq!(
160-
deconstruct(url.clone()).unwrap(),
212+
deconstruct(&url).unwrap(),
161213
ResourceId {
162214
source_id: url.to_string(),
163215
vault_url: "https://vault.azure.net".into(),
@@ -168,7 +220,7 @@ mod tests {
168220

169221
let url: Url = "https://vault.azure.net/keys/name/version".parse().unwrap();
170222
assert_eq!(
171-
deconstruct(url.clone()).unwrap(),
223+
deconstruct(&url).unwrap(),
172224
ResourceId {
173225
source_id: url.to_string(),
174226
vault_url: "https://vault.azure.net".into(),
@@ -181,7 +233,7 @@ mod tests {
181233
.parse()
182234
.unwrap();
183235
assert_eq!(
184-
deconstruct(url.clone()).unwrap(),
236+
deconstruct(&url).unwrap(),
185237
ResourceId {
186238
source_id: url.to_string(),
187239
vault_url: "https://vault.azure.net".into(),
@@ -194,7 +246,7 @@ mod tests {
194246
.parse()
195247
.unwrap();
196248
assert_eq!(
197-
deconstruct(url.clone()).unwrap(),
249+
deconstruct(&url).unwrap(),
198250
ResourceId {
199251
source_id: url.to_string(),
200252
vault_url: "https://vault.azure.net:8443".into(),

sdk/keyvault/azure_security_keyvault_secrets/src/resource.rs

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#[cfg(doc)]
55
use crate::{models::SecretBundle, SecretClient};
66
use azure_core::{error::ErrorKind, Result, Url};
7+
use std::str::FromStr;
78

89
/// Information about the resource.
910
///
@@ -23,6 +24,27 @@ pub struct ResourceId {
2324
pub version: Option<String>,
2425
}
2526

27+
impl FromStr for ResourceId {
28+
type Err = azure_core::Error;
29+
fn from_str(s: &str) -> Result<Self> {
30+
s.parse::<Url>()?.try_into()
31+
}
32+
}
33+
34+
impl TryFrom<Url> for ResourceId {
35+
type Error = azure_core::Error;
36+
fn try_from(url: Url) -> Result<Self> {
37+
ResourceId::try_from(&url)
38+
}
39+
}
40+
41+
impl TryFrom<&Url> for ResourceId {
42+
type Error = azure_core::Error;
43+
fn try_from(url: &Url) -> Result<Self> {
44+
deconstruct(url)
45+
}
46+
}
47+
2648
/// Extension methods to get a [`ResourceId`] from models in this crate.
2749
pub trait ResourceExt {
2850
/// Gets the [`ResourceId`] from this model.
@@ -62,11 +84,11 @@ where
6284
};
6385

6486
let url: Url = id.parse()?;
65-
deconstruct(url)
87+
deconstruct(&url)
6688
}
6789
}
6890

69-
fn deconstruct(url: Url) -> Result<ResourceId> {
91+
fn deconstruct(url: &Url) -> Result<ResourceId> {
7092
let vault_url = format!("{}://{}", url.scheme(), url.authority(),);
7193
let mut segments = url
7294
.path_segments()
@@ -145,17 +167,50 @@ mod tests {
145167

146168
use super::*;
147169

170+
#[test]
171+
fn try_from_str() {
172+
assert_eq!(
173+
"https://vault.azure.net/secrets/name/version"
174+
.parse::<ResourceId>()
175+
.unwrap(),
176+
ResourceId {
177+
source_id: "https://vault.azure.net/secrets/name/version".to_string(),
178+
vault_url: "https://vault.azure.net".into(),
179+
name: "name".into(),
180+
version: Some("version".into()),
181+
}
182+
);
183+
}
184+
185+
#[test]
186+
fn try_from_url() {
187+
let url: Url = "https://vault.azure.net/secrets/name/version"
188+
.parse()
189+
.unwrap();
190+
let resource: ResourceId = url.try_into().unwrap();
191+
assert_eq!(
192+
resource,
193+
ResourceId {
194+
source_id: "https://vault.azure.net/secrets/name/version".to_string(),
195+
vault_url: "https://vault.azure.net".into(),
196+
name: "name".into(),
197+
version: Some("version".into()),
198+
}
199+
);
200+
}
201+
148202
#[test]
149203
fn test_deconstruct() {
150-
deconstruct("file:///tmp".parse().unwrap()).expect_err("cannot-be-base url");
151-
deconstruct("https://vault.azure.net/".parse().unwrap()).expect_err("missing collection");
152-
deconstruct("https://vault.azure.net/collection/".parse().unwrap())
204+
deconstruct(&"file:///tmp".parse().unwrap()).expect_err("cannot-be-base url");
205+
deconstruct(&"https://vault.azure.net/".parse().unwrap()).expect_err("missing collection");
206+
deconstruct(&"https://vault.azure.net/collection/".parse().unwrap())
153207
.expect_err("invalid collection");
154-
deconstruct("https://vault.azure.net/secrets/".parse().unwrap()).expect_err("missing name");
208+
deconstruct(&"https://vault.azure.net/secrets/".parse().unwrap())
209+
.expect_err("missing name");
155210

156211
let url: Url = "https://vault.azure.net/secrets/name".parse().unwrap();
157212
assert_eq!(
158-
deconstruct(url.clone()).unwrap(),
213+
deconstruct(&url).unwrap(),
159214
ResourceId {
160215
source_id: url.to_string(),
161216
vault_url: "https://vault.azure.net".into(),
@@ -168,7 +223,7 @@ mod tests {
168223
.parse()
169224
.unwrap();
170225
assert_eq!(
171-
deconstruct(url.clone()).unwrap(),
226+
deconstruct(&url).unwrap(),
172227
ResourceId {
173228
source_id: url.to_string(),
174229
vault_url: "https://vault.azure.net".into(),
@@ -181,7 +236,7 @@ mod tests {
181236
.parse()
182237
.unwrap();
183238
assert_eq!(
184-
deconstruct(url.clone()).unwrap(),
239+
deconstruct(&url).unwrap(),
185240
ResourceId {
186241
source_id: url.to_string(),
187242
vault_url: "https://vault.azure.net".into(),
@@ -194,7 +249,7 @@ mod tests {
194249
.parse()
195250
.unwrap();
196251
assert_eq!(
197-
deconstruct(url.clone()).unwrap(),
252+
deconstruct(&url).unwrap(),
198253
ResourceId {
199254
source_id: url.to_string(),
200255
vault_url: "https://vault.azure.net:8443".into(),

0 commit comments

Comments
 (0)