···66pub mod handle;77pub mod nsid;88pub mod tid;99+pub mod uri;9101011pub use did::Did;1112pub use handle::Handle;1213pub use nsid::Nsid;1414+pub use uri::RecordUri;13151416#[cfg(feature = "serde")]1517pub mod serde;
+74
crates/atproto/src/uri.rs
···11+use crate::did::OwnedDid;22+33+/// A fully defined Atmosphere URI pointing to a record.44+///55+/// For example: "at://did:plc:65gha4t3avpfpzmvpbwovss7/sh.tangled.repo/3m24udbjajf22"66+///77+#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]88+pub struct RecordUri {99+ pub authority: OwnedDid,1010+ pub collection: String,1111+ pub rkey: String,1212+}1313+1414+#[derive(Debug, PartialEq, thiserror::Error)]1515+pub enum Error {1616+ #[error("Invalid authority: {0}")]1717+ InvalidAuthority(#[from] crate::did::Error),1818+ #[error("Could not parse AT URI")]1919+ Error,2020+}2121+2222+fn parse(s: &str) -> Result<RecordUri, Error> {2323+ let Some(uri) = s.strip_prefix("at://") else {2424+ return Err(Error::Error);2525+ };2626+2727+ let mut parts = uri.splitn(3, '/');2828+ let authority = parts2929+ .next()3030+ .map(OwnedDid::parse)3131+ .transpose()?3232+ .ok_or(Error::Error)?;3333+ let collection = parts.next().ok_or(Error::Error)?.to_string();3434+ let rkey = parts.next().ok_or(Error::Error)?.to_string();3535+3636+ Ok(RecordUri {3737+ authority,3838+ collection,3939+ rkey,4040+ })4141+}4242+4343+#[cfg(feature = "serde")]4444+mod impl_serde {4545+ use super::RecordUri;4646+4747+ #[derive(Default)]4848+ pub struct RecordUriVisitor;4949+5050+ impl<'de> serde::de::Visitor<'de> for RecordUriVisitor {5151+ type Value = RecordUri;5252+5353+ fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {5454+ formatter.write_str("ATproto record URI")5555+ }5656+5757+ fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>5858+ where5959+ E: serde::de::Error,6060+ {6161+ let uri = super::parse(v).map_err(serde::de::Error::custom)?;6262+ Ok(uri)6363+ }6464+ }6565+6666+ impl<'de> serde::Deserialize<'de> for RecordUri {6767+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>6868+ where6969+ D: serde::Deserializer<'de>,7070+ {7171+ deserializer.deserialize_str(RecordUriVisitor::default())7272+ }7373+ }7474+}