pub struct EdgeRef { /* private fields */ }Expand description
One end of an edge in an adjacency list — interned (0.8.0, B2, D-115).
Five fields, no heap payload, size_of 24 bytes against 104 bytes of struct
plus around 250 of strings before. Every field but the weight is an index
into its Subgraph’s pool, so reading one needs the graph:
for e in graph.out_edges("a") {
println!("{} {} {}", e.node(&graph), e.edge_type(&graph), e.weight());
}That is the visible cost of the change, and it is the reason B1 had to
privatise these fields first: a public node: String cannot become a u32.
The win is reachability, not speed (D-073’s
category): graphs that did not fit the byte budget start fitting.
§Invariants
An EdgeRef is tied to the specific Subgraph it was retrieved from.
Querying it against a different one — via an accessor like Self::node,
or via derived PartialEq — is a logic error that will silently return
incorrect data or report equality where none exists. Because the handle is
Copy it can be stored in a struct that outlives the graph; it stays
well-formed and becomes meaningless without its pool.
PartialEq is the sharp edge, and it is kept rather than removed: within
one graph, index equality is exactly the comparison a caller wants, and it
is cheaper and stricter than comparing five strings. Across two graphs it
compares indices that mean different things — a wrong answer that needs no
accessor call at all, so it sits outside the mental model of “querying”.
Before interning, == compared the strings and could not be wrong this way.
This logic error does not result in undefined behaviour — every index goes
through bounds-checked slice indexing and there is no unsafe here — but
the results are otherwise unspecified.
The handle is intentionally not lifetime-branded, which would make the
invariant a compile error, because that propagates a generic parameter
through every algorithm and every signature that mentions a Subgraph. See
D-115 for the argument and for what to do if this is ever hit in practice.
Implementations§
Source§impl EdgeRef
impl EdgeRef
Sourcepub fn node<'a>(&self, graph: &'a Subgraph) -> &'a str
pub fn node<'a>(&self, graph: &'a Subgraph) -> &'a str
The far end of the edge: the target in out_edges, the source in
in_edges.
Takes the graph because the string lives in its pool. graph must be
the one this edge came from; passing another is a programming error and
will panic or answer nonsense, exactly as indexing the wrong slice would.
pub fn edge_type<'a>(&self, graph: &'a Subgraph) -> &'a str
Sourcepub fn weight(&self) -> f64
pub fn weight(&self) -> f64
The only field that is not interned, because an f64 is already 8 bytes
and a pool of them would cost more than it saved.
pub fn valid_from<'a>(&self, graph: &'a Subgraph) -> &'a str
pub fn valid_to<'a>(&self, graph: &'a Subgraph) -> &'a str
Trait Implementations§
impl Copy for EdgeRef
Source§impl Debug for EdgeRef
Written by hand so a failing assert_eq! cannot be mistaken for one about
strings.
impl Debug for EdgeRef
Written by hand so a failing assert_eq! cannot be mistaken for one about
strings.
The derived form printed EdgeRef { node: 3, edge_type: 1, .. }, which
reads as data and is not: those are pool indices, meaningless without the
graph. The # is there to say so at a glance.
impl StructuralPartialEq for EdgeRef
Auto Trait Implementations§
impl Freeze for EdgeRef
impl RefUnwindSafe for EdgeRef
impl Send for EdgeRef
impl Sync for EdgeRef
impl Unpin for EdgeRef
impl UnsafeUnpin for EdgeRef
impl UnwindSafe for EdgeRef
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request