// AT-identifier -- "a DID or a handle", the type of every `actor`, `repo` and
// `identifier` parameter in the protocol.
//
// https://atproto.com/specs/at-uri-scheme
// Ported from @atproto/syntax packages/syntax/src/at-identifier.ts.
//
// A sum type rather than a validated string, because the two halves behave
// differently and the difference matters at every call site: a DID is stable
// and a handle is not, so code that caches, keys or compares must know which
// one it has. Upstream models this as a union of two branded strings and then
// re-tests the prefix wherever it needs to know; here the answer is in the
// value.
///|
pub(all) enum AtIdentifier {
Did(Did)
Handle(Handle)
} derive(Eq, Debug)
///|
pub impl Show for AtIdentifier with fn output(self, logger) {
logger.write_string(self.to_string())
}
///|
pub fn AtIdentifier::to_string(self : Self) -> String {
match self {
Did(d) => d.to_string()
Handle(h) => h.to_string()
}
}
///|
/// The DID, if this is one. `None` for a handle -- resolving a handle to a DID
/// needs the network and is a client call, not a syntax operation.
pub fn AtIdentifier::as_did(self : Self) -> Did? {
match self {
Did(d) => Some(d)
Handle(_) => None
}
}
///|
pub fn AtIdentifier::as_handle(self : Self) -> Handle? {
match self {
Did(_) => None
Handle(h) => Some(h)
}
}
///|
pub fn AtIdentifier::is_valid(input : String) -> Bool {
try {
AtIdentifier::parse(input) |> ignore
true
} catch {
_ => false
}
}
///|
/// The `did:` prefix decides which validator runs, so a malformed DID is
/// reported as a bad DID rather than as a bad handle -- `did:thing` is not a
/// handle that happens to contain a colon.
pub fn AtIdentifier::parse(input : String) -> AtIdentifier raise SyntaxError {
if input.has_prefix("did:") {
Did(Did::parse(input))
} else {
Handle(Handle::parse(input))
}
}