1use crate::{
2 ReferenceError, ResourceIdentity, ResourceType, derive_service_origin,
3 is_local_resource_identifier,
4};
5
6impl ResourceIdentity {
7 pub fn new(
8 service_document_url: &str,
9 resource_type: ResourceType,
10 id: impl Into<String>,
11 ) -> Result<Self, ReferenceError> {
12 let id = id.into();
13 if !is_local_resource_identifier(&id) {
14 return Err(ReferenceError::InvalidResourceIdentifier(
15 match resource_type {
16 ResourceType::Collection => crate::Operation::GetCollection,
17 ResourceType::Offering => crate::Operation::GetOffering,
18 },
19 ));
20 }
21 Ok(Self {
22 id,
23 service: derive_service_origin(service_document_url)?,
24 resource_type,
25 })
26 }
27
28 pub fn key(&self) -> String {
29 let resource_type = match self.resource_type {
30 ResourceType::Collection => "collection",
31 ResourceType::Offering => "offering",
32 };
33 format!("{}\0{}\0{}", self.service, resource_type, self.id)
34 }
35}
36
37#[cfg(test)]
38mod tests {
39 use super::*;
40
41 #[test]
42 fn composes_global_resource_identity() {
43 let identity = ResourceIdentity::new(
44 "https://shop.example/.well-known/odp",
45 ResourceType::Offering,
46 "plant-1",
47 )
48 .unwrap();
49 assert_eq!(identity.service, "https://shop.example");
50 assert_eq!(identity.key(), "https://shop.example\0offering\0plant-1");
51 }
52}