use atrium_api::types::string::{ AtIdentifier, RecordKey, }; use regex::Regex; pub use atrium_api::types::string::{ Nsid, Did, Handle, }; enum Authority { Did(Did), Handle(Handle), } impl Authority { pub fn new(authority: String) -> Result { } } // This implementation does not support Query or Fragments, and thus follows // the following schema: "at://" AUTHORITY [ "/" COLLECTION [ "/" RKEY ] ] pub struct Uri { authority: Authority, collection: Option, rkey: Option, } // TODO: Replace super basic URI regex with real uri parsing const URI_REGEX: Regex = Regex::new( r"/^at:\/\/([\w\.\-_~:]+)(?:\/([\w\.\-_~:]+)(?:)\/([\w\.\-_~:]+))?$/i" ).expect("valid regex"); impl Uri { pub fn new(uri: String) -> Result { let Some(captures) = URI_REGEX.captures(&uri) else { return Err("Invalid Uri"); }; // TODO: Convert authority if its a did or a handle let Some(Ok(authority)) = captures.get(1).map(|mtch| { Authority::new(mtch.as_str().to_string()) }) else { return Err("Invalid Authority") }; let collection = captures.get(2).map(|mtch| { Nsid::new(mtch.as_str().to_string()) }); let rkey = captures.get(3).map(|mtch| { RecordKey::new(mtch.as_str().to_string()) }); Ok(Uri { authority, collection, rkey }) } pub fn as_string(&self) -> String { let mut uri = String::from("at://"); uri.push_str(match &self.authority { Authority::Handle(h) => &*h, Authority::Did(d) => &*d, }); if let Some(nsid) = &self.collection { uri.push_str(&*nsid); } if let Some(rkey) = &self.rkey { uri.push_str(&*rkey); } uri } }