///|
/// An anchor within a `Resource` (Python's `referencing.Anchor`, and more
/// generally the `referencing.typing.Anchor` protocol).
///
/// Plain anchors resolve to their resource's contents. Other kinds of anchors
/// (such as JSON Schema 2020-12's dynamic anchors, see `dynamic_anchor`) carry
/// a `kind` tag (Python's class name) and their own resolution closure.
pub struct Anchor {
/// The name of this anchor.
name : String
/// The resource this anchor points at.
resource : Resource
priv kind : String
priv resolve_impl : ((Anchor, Resolver) -> Resolved raise)?
}
///|
/// Create a simple anchor in a `Resource`.
pub fn Anchor::new(name~ : String, resource~ : Resource) -> Anchor {
{ name, resource, kind: "Anchor", resolve_impl: None, }
}
///|
/// Create a custom kind of anchor (Python: any object implementing the
/// `referencing.typing.Anchor` protocol). `kind` plays the role of the Python
/// class name (used for equality and display), and `resolve` is called with
/// the anchor itself and the resolver.
pub fn Anchor::custom(
name~ : String,
resource~ : Resource,
kind~ : String,
resolve~ : (Anchor, Resolver) -> Resolved raise,
) -> Anchor {
{ name, resource, kind, resolve_impl: Some(resolve), }
}
///|
/// The kind of the anchor: `"Anchor"` for simple anchors, `"DynamicAnchor"`
/// for JSON Schema dynamic anchors, or a custom kind.
pub fn Anchor::kind(self : Anchor) -> String {
self.kind
}
///|
/// Return the resource for this anchor.
pub fn Anchor::resolve(self : Anchor, resolver : Resolver) -> Resolved raise {
match self.resolve_impl {
None => { contents: self.resource.contents, resolver, }
Some(f) => f(self, resolver)
}
}
///|
/// Anchors are equal when they have the same kind, name and resource, and the
/// same resolution callback (compared by identity, as for `Specification`
/// callbacks and registry retrievers).
pub impl Eq for Anchor with fn equal(self, other) {
self.kind == other.kind &&
self.name == other.name &&
self.resource == other.resource &&
(match (self.resolve_impl, other.resolve_impl) {
(None, None) => true
(Some(a), Some(b)) => physical_equal(a, b)
_ => false
})
}
///|
/// `Anchor(name='...', resource=Resource(...))`, as Python's `repr`.
pub impl Show for Anchor with fn output(self, logger) {
logger.write_string(
"\{self.kind}(name=\{py_str_repr(self.name)}, resource=\{self.resource})",
)
}