pub struct LpgStore { /* private fields */ }Expand description
The core in-memory graph storage.
Everything lives here: nodes, edges, properties, adjacency indexes, and version chains for MVCC. Concurrent reads never block each other.
Most users should go through GrafeoDB (from the grafeo_engine crate) which
adds transaction management and query execution. Use LpgStore directly
when you need raw performance for algorithm implementations.
§Example
use grafeo_core::graph::lpg::LpgStore;
use grafeo_core::graph::Direction;
let store = LpgStore::new();
// Create a small social network
let alice = store.create_node(&["Person"]);
let bob = store.create_node(&["Person"]);
store.create_edge(alice, bob, "KNOWS");
// Traverse outgoing edges
for neighbor in store.neighbors(alice, Direction::Outgoing) {
println!("Alice knows node {:?}", neighbor);
}§Lock Ordering
LpgStore contains multiple RwLock fields that must be acquired in a
consistent order to prevent deadlocks. Always acquire locks in this order:
§Level 1 - Entity Storage (mutually exclusive via feature flag)
nodes/node_versionsedges/edge_versions
§Level 2 - Catalogs (acquire as pairs when writing)
label_to_id+id_to_labeledge_type_to_id+id_to_edge_type
§Level 3 - Indexes
label_indexnode_labelsproperty_indexes
§Level 4 - Statistics
statistics
§Level 5 - Nested Locks (internal to other structs)
PropertyStorage::columns(vianode_properties/edge_properties)ChunkedAdjacency::lists(viaforward_adj/backward_adj)
§Rules
- Catalog pairs must be acquired together when writing.
- Never hold entity locks while acquiring catalog locks in a different scope.
- Statistics lock is always last.
- Read locks are generally safe, but avoid read-to-write upgrades.
Implementations§
Source§impl LpgStore
impl LpgStore
Sourcepub fn with_config(config: LpgStoreConfig) -> Self
pub fn with_config(config: LpgStoreConfig) -> Self
Creates a new LPG store with custom configuration.
Sourcepub fn current_epoch(&self) -> EpochId
pub fn current_epoch(&self) -> EpochId
Returns the current epoch.
Sourcepub fn create_node(&self, labels: &[&str]) -> NodeId
pub fn create_node(&self, labels: &[&str]) -> NodeId
Creates a new node with the given labels.
Uses the system transaction for non-transactional operations.
Sourcepub fn create_node_versioned(
&self,
labels: &[&str],
epoch: EpochId,
tx_id: TxId,
) -> NodeId
pub fn create_node_versioned( &self, labels: &[&str], epoch: EpochId, tx_id: TxId, ) -> NodeId
Creates a new node with the given labels within a transaction context.
Sourcepub fn create_node_with_props(
&self,
labels: &[&str],
properties: impl IntoIterator<Item = (impl Into<PropertyKey>, impl Into<Value>)>,
) -> NodeId
pub fn create_node_with_props( &self, labels: &[&str], properties: impl IntoIterator<Item = (impl Into<PropertyKey>, impl Into<Value>)>, ) -> NodeId
Creates a new node with labels and properties.
Sourcepub fn create_node_with_props_versioned(
&self,
labels: &[&str],
properties: impl IntoIterator<Item = (impl Into<PropertyKey>, impl Into<Value>)>,
epoch: EpochId,
tx_id: TxId,
) -> NodeId
pub fn create_node_with_props_versioned( &self, labels: &[&str], properties: impl IntoIterator<Item = (impl Into<PropertyKey>, impl Into<Value>)>, epoch: EpochId, tx_id: TxId, ) -> NodeId
Creates a new node with labels and properties within a transaction context.
Sourcepub fn get_node_at_epoch(&self, id: NodeId, epoch: EpochId) -> Option<Node>
pub fn get_node_at_epoch(&self, id: NodeId, epoch: EpochId) -> Option<Node>
Gets a node by ID at a specific epoch.
Sourcepub fn get_node_versioned(
&self,
id: NodeId,
epoch: EpochId,
tx_id: TxId,
) -> Option<Node>
pub fn get_node_versioned( &self, id: NodeId, epoch: EpochId, tx_id: TxId, ) -> Option<Node>
Gets a node visible to a specific transaction.
Sourcepub fn delete_node(&self, id: NodeId) -> bool
pub fn delete_node(&self, id: NodeId) -> bool
Deletes a node and all its edges (using latest epoch).
Sourcepub fn delete_node_at_epoch(&self, id: NodeId, epoch: EpochId) -> bool
pub fn delete_node_at_epoch(&self, id: NodeId, epoch: EpochId) -> bool
Deletes a node at a specific epoch.
Sourcepub fn delete_node_edges(&self, node_id: NodeId)
pub fn delete_node_edges(&self, node_id: NodeId)
Deletes all edges connected to a node (implements DETACH DELETE).
Call this before delete_node() if you want to remove a node that
has edges. Grafeo doesn’t auto-delete edges - you have to be explicit.
Sourcepub fn set_node_property(&self, id: NodeId, key: &str, value: Value)
pub fn set_node_property(&self, id: NodeId, key: &str, value: Value)
Sets a property on a node.
Sourcepub fn set_edge_property(&self, id: EdgeId, key: &str, value: Value)
pub fn set_edge_property(&self, id: EdgeId, key: &str, value: Value)
Sets a property on an edge.
Sourcepub fn remove_node_property(&self, id: NodeId, key: &str) -> Option<Value>
pub fn remove_node_property(&self, id: NodeId, key: &str) -> Option<Value>
Removes a property from a node.
Returns the previous value if it existed, or None if the property didn’t exist.
Sourcepub fn remove_edge_property(&self, id: EdgeId, key: &str) -> Option<Value>
pub fn remove_edge_property(&self, id: EdgeId, key: &str) -> Option<Value>
Removes a property from an edge.
Returns the previous value if it existed, or None if the property didn’t exist.
Sourcepub fn get_node_property(&self, id: NodeId, key: &PropertyKey) -> Option<Value>
pub fn get_node_property(&self, id: NodeId, key: &PropertyKey) -> Option<Value>
Gets a single property from a node without loading all properties.
This is O(1) vs O(properties) for get_node().get_property().
Use this for filter predicates where you only need one property value.
§Example
// Fast: Direct single-property lookup
let age = store.get_node_property(node_id, "age");
// Slow: Loads all properties, then extracts one
let age = store.get_node(node_id).and_then(|n| n.get_property("age").cloned());Sourcepub fn get_edge_property(&self, id: EdgeId, key: &PropertyKey) -> Option<Value>
pub fn get_edge_property(&self, id: EdgeId, key: &PropertyKey) -> Option<Value>
Gets a single property from an edge without loading all properties.
This is O(1) vs O(properties) for get_edge().get_property().
Sourcepub fn get_node_property_batch(
&self,
ids: &[NodeId],
key: &PropertyKey,
) -> Vec<Option<Value>>
pub fn get_node_property_batch( &self, ids: &[NodeId], key: &PropertyKey, ) -> Vec<Option<Value>>
Gets a property for multiple nodes in a single batch operation.
More efficient than calling Self::get_node_property in a loop because it
reduces lock overhead and enables better cache utilization.
§Example
use grafeo_core::graph::lpg::LpgStore;
use grafeo_common::types::{NodeId, PropertyKey, Value};
let store = LpgStore::new();
let n1 = store.create_node(&["Person"]);
let n2 = store.create_node(&["Person"]);
store.set_node_property(n1, "age", Value::from(25i64));
store.set_node_property(n2, "age", Value::from(30i64));
let ages = store.get_node_property_batch(&[n1, n2], &PropertyKey::new("age"));
assert_eq!(ages, vec![Some(Value::from(25i64)), Some(Value::from(30i64))]);Sourcepub fn get_nodes_properties_batch(
&self,
ids: &[NodeId],
) -> Vec<FxHashMap<PropertyKey, Value>> ⓘ
pub fn get_nodes_properties_batch( &self, ids: &[NodeId], ) -> Vec<FxHashMap<PropertyKey, Value>> ⓘ
Gets all properties for multiple nodes in a single batch operation.
Returns a vector of property maps, one per node ID (empty map if no properties).
More efficient than calling Self::get_node in a loop.
Sourcepub fn get_nodes_properties_selective_batch(
&self,
ids: &[NodeId],
keys: &[PropertyKey],
) -> Vec<FxHashMap<PropertyKey, Value>> ⓘ
pub fn get_nodes_properties_selective_batch( &self, ids: &[NodeId], keys: &[PropertyKey], ) -> Vec<FxHashMap<PropertyKey, Value>> ⓘ
Gets selected properties for multiple nodes (projection pushdown).
This is more efficient than Self::get_nodes_properties_batch when you only
need a subset of properties. It only iterates the requested columns instead of
all columns.
Use this for: Queries with explicit projections like RETURN n.name, n.age
instead of RETURN n (which requires all properties).
§Example
use grafeo_core::graph::lpg::LpgStore;
use grafeo_common::types::{PropertyKey, Value};
let store = LpgStore::new();
let n1 = store.create_node(&["Person"]);
store.set_node_property(n1, "name", Value::from("Alice"));
store.set_node_property(n1, "age", Value::from(30i64));
store.set_node_property(n1, "email", Value::from("alice@example.com"));
// Only fetch name and age (faster than get_nodes_properties_batch)
let keys = vec![PropertyKey::new("name"), PropertyKey::new("age")];
let props = store.get_nodes_properties_selective_batch(&[n1], &keys);
assert_eq!(props[0].len(), 2); // Only name and age, not emailSourcepub fn get_edges_properties_selective_batch(
&self,
ids: &[EdgeId],
keys: &[PropertyKey],
) -> Vec<FxHashMap<PropertyKey, Value>> ⓘ
pub fn get_edges_properties_selective_batch( &self, ids: &[EdgeId], keys: &[PropertyKey], ) -> Vec<FxHashMap<PropertyKey, Value>> ⓘ
Gets selected properties for multiple edges (projection pushdown).
Edge-property version of Self::get_nodes_properties_selective_batch.
Sourcepub fn find_nodes_in_range(
&self,
property: &str,
min: Option<&Value>,
max: Option<&Value>,
min_inclusive: bool,
max_inclusive: bool,
) -> Vec<NodeId>
pub fn find_nodes_in_range( &self, property: &str, min: Option<&Value>, max: Option<&Value>, min_inclusive: bool, max_inclusive: bool, ) -> Vec<NodeId>
Finds nodes where a property value is in a range.
This is useful for queries like n.age > 30 or n.price BETWEEN 10 AND 100.
Uses zone maps to skip scanning when the range definitely doesn’t match.
§Arguments
property- The property to checkmin- Optional lower bound (None for unbounded)max- Optional upper bound (None for unbounded)min_inclusive- Whether lower bound is inclusive (>= vs >)max_inclusive- Whether upper bound is inclusive (<= vs <)
§Example
use grafeo_core::graph::lpg::LpgStore;
use grafeo_common::types::Value;
let store = LpgStore::new();
let n1 = store.create_node(&["Person"]);
let n2 = store.create_node(&["Person"]);
store.set_node_property(n1, "age", Value::from(25i64));
store.set_node_property(n2, "age", Value::from(35i64));
// Find nodes where age > 30
let result = store.find_nodes_in_range(
"age",
Some(&Value::from(30i64)),
None,
false, // exclusive lower bound
true, // inclusive upper bound (doesn't matter since None)
);
assert_eq!(result.len(), 1); // Only n2 matchesSourcepub fn find_nodes_by_properties(
&self,
conditions: &[(&str, Value)],
) -> Vec<NodeId>
pub fn find_nodes_by_properties( &self, conditions: &[(&str, Value)], ) -> Vec<NodeId>
Finds nodes matching multiple property equality conditions.
This is more efficient than intersecting multiple single-property lookups because it can use indexes when available and short-circuits on the first miss.
§Example
use grafeo_core::graph::lpg::LpgStore;
use grafeo_common::types::Value;
let store = LpgStore::new();
let alice = store.create_node(&["Person"]);
store.set_node_property(alice, "name", Value::from("Alice"));
store.set_node_property(alice, "city", Value::from("NYC"));
// Find nodes where name = "Alice" AND city = "NYC"
let matches = store.find_nodes_by_properties(&[
("name", Value::from("Alice")),
("city", Value::from("NYC")),
]);
assert!(matches.contains(&alice));Sourcepub fn create_property_index(&self, property: &str)
pub fn create_property_index(&self, property: &str)
Creates an index on a node property for O(1) lookups by value.
After creating an index, calls to Self::find_nodes_by_property will be
O(1) instead of O(n) for this property. The index is automatically
maintained when properties are set or removed.
§Example
use grafeo_core::graph::lpg::LpgStore;
use grafeo_common::types::Value;
let store = LpgStore::new();
// Create nodes with an 'id' property
let alice = store.create_node(&["Person"]);
store.set_node_property(alice, "id", Value::from("alice_123"));
// Create an index on the 'id' property
store.create_property_index("id");
// Now lookups by 'id' are O(1)
let found = store.find_nodes_by_property("id", &Value::from("alice_123"));
assert!(found.contains(&alice));Sourcepub fn drop_property_index(&self, property: &str) -> bool
pub fn drop_property_index(&self, property: &str) -> bool
Drops an index on a node property.
Returns true if the index existed and was removed.
Sourcepub fn has_property_index(&self, property: &str) -> bool
pub fn has_property_index(&self, property: &str) -> bool
Returns true if the property has an index.
Sourcepub fn find_nodes_by_property(
&self,
property: &str,
value: &Value,
) -> Vec<NodeId>
pub fn find_nodes_by_property( &self, property: &str, value: &Value, ) -> Vec<NodeId>
Finds all nodes that have a specific property value.
If the property is indexed, this is O(1). Otherwise, it scans all nodes
which is O(n). Use Self::create_property_index for frequently queried properties.
§Example
use grafeo_core::graph::lpg::LpgStore;
use grafeo_common::types::Value;
let store = LpgStore::new();
store.create_property_index("city"); // Optional but makes lookups fast
let alice = store.create_node(&["Person"]);
let bob = store.create_node(&["Person"]);
store.set_node_property(alice, "city", Value::from("NYC"));
store.set_node_property(bob, "city", Value::from("NYC"));
let nyc_people = store.find_nodes_by_property("city", &Value::from("NYC"));
assert_eq!(nyc_people.len(), 2);Sourcepub fn add_label(&self, node_id: NodeId, label: &str) -> bool
pub fn add_label(&self, node_id: NodeId, label: &str) -> bool
Adds a label to a node.
Returns true if the label was added, false if the node doesn’t exist or already has the label.
Sourcepub fn remove_label(&self, node_id: NodeId, label: &str) -> bool
pub fn remove_label(&self, node_id: NodeId, label: &str) -> bool
Removes a label from a node.
Returns true if the label was removed, false if the node doesn’t exist or doesn’t have the label.
Sourcepub fn node_count(&self) -> usize
pub fn node_count(&self) -> usize
Returns the number of nodes (non-deleted at current epoch).
Sourcepub fn node_ids(&self) -> Vec<NodeId>
pub fn node_ids(&self) -> Vec<NodeId>
Returns all node IDs in the store.
This returns a snapshot of current node IDs. The returned vector excludes deleted nodes. Results are sorted by NodeId for deterministic iteration order.
Sourcepub fn create_edge(&self, src: NodeId, dst: NodeId, edge_type: &str) -> EdgeId
pub fn create_edge(&self, src: NodeId, dst: NodeId, edge_type: &str) -> EdgeId
Creates a new edge.
Sourcepub fn create_edge_versioned(
&self,
src: NodeId,
dst: NodeId,
edge_type: &str,
epoch: EpochId,
tx_id: TxId,
) -> EdgeId
pub fn create_edge_versioned( &self, src: NodeId, dst: NodeId, edge_type: &str, epoch: EpochId, tx_id: TxId, ) -> EdgeId
Creates a new edge within a transaction context.
Sourcepub fn create_edge_with_props(
&self,
src: NodeId,
dst: NodeId,
edge_type: &str,
properties: impl IntoIterator<Item = (impl Into<PropertyKey>, impl Into<Value>)>,
) -> EdgeId
pub fn create_edge_with_props( &self, src: NodeId, dst: NodeId, edge_type: &str, properties: impl IntoIterator<Item = (impl Into<PropertyKey>, impl Into<Value>)>, ) -> EdgeId
Creates a new edge with properties.
Sourcepub fn get_edge(&self, id: EdgeId) -> Option<Edge>
pub fn get_edge(&self, id: EdgeId) -> Option<Edge>
Gets an edge by ID (latest visible version).
Sourcepub fn get_edge_at_epoch(&self, id: EdgeId, epoch: EpochId) -> Option<Edge>
pub fn get_edge_at_epoch(&self, id: EdgeId, epoch: EpochId) -> Option<Edge>
Gets an edge by ID at a specific epoch.
Sourcepub fn get_edge_versioned(
&self,
id: EdgeId,
epoch: EpochId,
tx_id: TxId,
) -> Option<Edge>
pub fn get_edge_versioned( &self, id: EdgeId, epoch: EpochId, tx_id: TxId, ) -> Option<Edge>
Gets an edge visible to a specific transaction.
Sourcepub fn delete_edge(&self, id: EdgeId) -> bool
pub fn delete_edge(&self, id: EdgeId) -> bool
Deletes an edge (using latest epoch).
Sourcepub fn delete_edge_at_epoch(&self, id: EdgeId, epoch: EpochId) -> bool
pub fn delete_edge_at_epoch(&self, id: EdgeId, epoch: EpochId) -> bool
Deletes an edge at a specific epoch.
Sourcepub fn edge_count(&self) -> usize
pub fn edge_count(&self) -> usize
Returns the number of edges (non-deleted at current epoch).
Sourcepub fn discard_uncommitted_versions(&self, tx_id: TxId)
pub fn discard_uncommitted_versions(&self, tx_id: TxId)
Discards all uncommitted versions created by a transaction.
This is called during transaction rollback to clean up uncommitted changes. The method removes version chain entries created by the specified transaction.
Sourcepub fn label_count(&self) -> usize
pub fn label_count(&self) -> usize
Returns the number of distinct labels in the store.
Sourcepub fn property_key_count(&self) -> usize
pub fn property_key_count(&self) -> usize
Returns the number of distinct property keys in the store.
This counts unique property keys across both nodes and edges.
Sourcepub fn edge_type_count(&self) -> usize
pub fn edge_type_count(&self) -> usize
Returns the number of distinct edge types in the store.
Sourcepub fn neighbors(
&self,
node: NodeId,
direction: Direction,
) -> impl Iterator<Item = NodeId> + '_
pub fn neighbors( &self, node: NodeId, direction: Direction, ) -> impl Iterator<Item = NodeId> + '_
Iterates over neighbors of a node in the specified direction.
This is the fast path for graph traversal - goes straight to the adjacency index without loading full node data.
Sourcepub fn edges_from(
&self,
node: NodeId,
direction: Direction,
) -> impl Iterator<Item = (NodeId, EdgeId)> + '_
pub fn edges_from( &self, node: NodeId, direction: Direction, ) -> impl Iterator<Item = (NodeId, EdgeId)> + '_
Returns edges from a node with their targets.
Returns an iterator of (target_node, edge_id) pairs.
Sourcepub fn out_degree(&self, node: NodeId) -> usize
pub fn out_degree(&self, node: NodeId) -> usize
Returns the out-degree of a node (number of outgoing edges).
Uses the forward adjacency index for O(1) lookup.
Sourcepub fn in_degree(&self, node: NodeId) -> usize
pub fn in_degree(&self, node: NodeId) -> usize
Returns the in-degree of a node (number of incoming edges).
Uses the backward adjacency index for O(1) lookup if available, otherwise falls back to scanning edges.
Sourcepub fn nodes_by_label(&self, label: &str) -> Vec<NodeId>
pub fn nodes_by_label(&self, label: &str) -> Vec<NodeId>
Returns all nodes with a specific label.
Uses the label index for O(1) lookup per label. Returns a snapshot - concurrent modifications won’t affect the returned vector. Results are sorted by NodeId for deterministic iteration order.
Sourcepub fn all_nodes(&self) -> impl Iterator<Item = Node> + '_
pub fn all_nodes(&self) -> impl Iterator<Item = Node> + '_
Returns an iterator over all nodes in the database.
This creates a snapshot of all visible nodes at the current epoch. Useful for dump/export operations.
Sourcepub fn all_edges(&self) -> impl Iterator<Item = Edge> + '_
pub fn all_edges(&self) -> impl Iterator<Item = Edge> + '_
Returns an iterator over all edges in the database.
This creates a snapshot of all visible edges at the current epoch. Useful for dump/export operations.
Sourcepub fn all_labels(&self) -> Vec<String>
pub fn all_labels(&self) -> Vec<String>
Returns all label names in the database.
Sourcepub fn all_edge_types(&self) -> Vec<String>
pub fn all_edge_types(&self) -> Vec<String>
Returns all edge type names in the database.
Sourcepub fn all_property_keys(&self) -> Vec<String>
pub fn all_property_keys(&self) -> Vec<String>
Returns all property keys used in the database.
Sourcepub fn nodes_with_label<'a>(
&'a self,
label: &str,
) -> impl Iterator<Item = Node> + 'a
pub fn nodes_with_label<'a>( &'a self, label: &str, ) -> impl Iterator<Item = Node> + 'a
Returns an iterator over nodes with a specific label.
Sourcepub fn edges_with_type<'a>(
&'a self,
edge_type: &str,
) -> impl Iterator<Item = Edge> + 'a
pub fn edges_with_type<'a>( &'a self, edge_type: &str, ) -> impl Iterator<Item = Edge> + 'a
Returns an iterator over edges with a specific type.
Sourcepub fn node_property_might_match(
&self,
property: &PropertyKey,
op: CompareOp,
value: &Value,
) -> bool
pub fn node_property_might_match( &self, property: &PropertyKey, op: CompareOp, value: &Value, ) -> bool
Checks if a node property predicate might match any nodes.
Uses zone maps for early filtering. Returns true if there might be
matching nodes, false if there definitely aren’t.
Sourcepub fn edge_property_might_match(
&self,
property: &PropertyKey,
op: CompareOp,
value: &Value,
) -> bool
pub fn edge_property_might_match( &self, property: &PropertyKey, op: CompareOp, value: &Value, ) -> bool
Checks if an edge property predicate might match any edges.
Sourcepub fn node_property_zone_map(
&self,
property: &PropertyKey,
) -> Option<ZoneMapEntry>
pub fn node_property_zone_map( &self, property: &PropertyKey, ) -> Option<ZoneMapEntry>
Gets the zone map for a node property.
Sourcepub fn edge_property_zone_map(
&self,
property: &PropertyKey,
) -> Option<ZoneMapEntry>
pub fn edge_property_zone_map( &self, property: &PropertyKey, ) -> Option<ZoneMapEntry>
Gets the zone map for an edge property.
Sourcepub fn rebuild_zone_maps(&self)
pub fn rebuild_zone_maps(&self)
Rebuilds zone maps for all properties.
Sourcepub fn statistics(&self) -> Statistics
pub fn statistics(&self) -> Statistics
Returns the current statistics.
Sourcepub fn compute_statistics(&self)
pub fn compute_statistics(&self)
Recomputes statistics from current data.
Scans all labels and edge types to build cardinality estimates for the query optimizer. Call this periodically or after bulk data loads.
Sourcepub fn estimate_label_cardinality(&self, label: &str) -> f64
pub fn estimate_label_cardinality(&self, label: &str) -> f64
Estimates cardinality for a label scan.
Sourcepub fn estimate_avg_degree(&self, edge_type: &str, outgoing: bool) -> f64
pub fn estimate_avg_degree(&self, edge_type: &str, outgoing: bool) -> f64
Estimates average degree for an edge type.
Sourcepub fn create_node_with_id(&self, id: NodeId, labels: &[&str])
pub fn create_node_with_id(&self, id: NodeId, labels: &[&str])
Creates a node with a specific ID during recovery.
This is used for WAL recovery to restore nodes with their original IDs. The caller must ensure IDs don’t conflict with existing nodes.
Trait Implementations§
Auto Trait Implementations§
impl !Freeze for LpgStore
impl !RefUnwindSafe for LpgStore
impl Send for LpgStore
impl Sync for LpgStore
impl Unpin for LpgStore
impl UnwindSafe for LpgStore
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
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more