Expression

Struct Expression 

Source
pub struct Expression<T> { /* private fields */ }
Expand description

A self-contained, optimized Boolean logic graph.

Expression stores logic in a deduplicated Directed Acyclic Graph (DAG). It is the immutable, optimized output of an ExpressionBuilder.

§Key Features

  • Interning: Every unique node (e.g., A | B) is stored exactly once.
  • Flat Memory: Nodes are stored in a dense Vec, improving CPU cache locality.
  • Safe: Constructed via append-only logic, ensuring no cycles exist.

§Example: Boolean Evaluation

This example builds a simple logic gate (A AND NOT B) and evaluates it against a set of active keys.

use logify::{ExpressionBuilder, Expression, Evaluator};
use std::collections::HashSet;

// --- 1. Build the Logic ---
let builder = ExpressionBuilder::new();
let a = builder.leaf("A");
let b = builder.leaf("B");

// Logic: A AND (NOT B)
builder.add_root(a & !b);

let expr: Expression<&str> = builder.build();

// --- 2. Define a Solver ---
// A simple struct that holds which keys are "Active" (True).
struct TruthContext(HashSet<&'static str>);

impl Evaluator<&str, bool, ()> for TruthContext {
    // Base truths
    fn get_universal(&mut self) -> Result<bool, ()> { Ok(true) }
    fn get_empty(&mut self) -> Result<bool, ()> { Ok(false) }
     
    // Leaf lookup: True if the set contains the key
    fn eval_set(&mut self, key: &&str) -> Result<bool, ()> {
        Ok(self.0.contains(key))
    }
     
    // Boolean Logic: OR
    fn eval_union<'a, I>(&mut self, i: I) -> Result<bool, ()>
        where I: IntoIterator<Item=&'a bool>, I::IntoIter: ExactSizeIterator
    {
        Ok(i.into_iter().any(|&b| b))
    }
     
    // Boolean Logic: AND
    fn eval_intersection<'a, I>(&mut self, i: I) -> Result<bool, ()>
        where I: IntoIterator<Item=&'a bool>, I::IntoIter: ExactSizeIterator
    {
        Ok(i.into_iter().all(|&b| b))
    }
     
    // Boolean Logic: AND NOT
    fn eval_difference(&mut self, inc: &bool, exc: &bool) -> Result<bool, ()> {
        Ok(*inc && !*exc)
    }
}

// --- 3. Run Evaluation ---
// Case 1: "A" is present, "B" is missing. Result should be True.
let mut solver = TruthContext(HashSet::from(["A"]));
let results = expr.evaluate(&mut solver).unwrap();
assert_eq!(results[0], true);

// Case 2: "A" and "B" are present. Result should be False (because of NOT B).
let mut solver_2 = TruthContext(HashSet::from(["A", "B"]));
let results_2 = expr.evaluate(&mut solver_2).unwrap();
assert_eq!(results_2[0], false);

Implementations§

Source§

impl<T> Expression<T>

Source

pub fn evaluate<R, E, S>(&self, solver: &mut S) -> Result<Vec<R>, E>
where R: Clone, S: Evaluator<T, R, E>,

Evaluates the expression using a temporary cache.

This is a convenience wrapper around evaluate_with. It creates a fresh EvaluatorCache, runs the evaluation, and then drops the cache.

§Performance Note

Because this allocates memory for every call, it is not recommended for tight loops. Use evaluate_with for repeated evaluations.

Examples found in repository?
examples/permissions.rs (line 54)
52fn print_access<'a>(name: &str, rules: &Expression<&'a str>, user: &mut BoolEval<&'a str>) {
53    // Get the roots (Each representing a permission)
54    let perms = rules.evaluate(user).unwrap();
55
56    println!("Permissions for {}:", name);
57    println!("  [View]:   {}", perms[0]);
58    println!("  [Edit]:   {}", perms[1]);
59    println!("  [Delete]: {}", perms[2]);
60    println!("-----------------------------");
61}
More examples
Hide additional examples
examples/product_filter.rs (line 98)
79fn main() -> Result<(), ()> {
80    // 1. Build logic
81    let builder = ExpressionBuilder::new();
82    let red = builder.leaf("Red");
83    let blue = builder.leaf("Blue");
84    let expensive = builder.leaf("Expensive");
85
86    let filter = (red | blue) & !expensive;
87    builder.add_root(filter);
88
89    let expr = builder.build();
90
91    // 2. Setup Evaluator
92    let mut db = ProductDb::new();
93    db.add_tag("Red", &[1, 2]);
94    db.add_tag("Blue", &[3, 4]);
95    db.add_tag("Expensive", &[1, 4]);
96
97    // 5. Evaluate
98    let results = expr.evaluate(&mut db)?;
99
100    let mut matching_products: Vec<i32> = results[0].iter().copied().collect();
101    matching_products.sort();
102
103    println!("Matching Products: {:?}", matching_products);
104    assert_eq!(matching_products, vec![2, 3]);
105
106    Ok(())
107}
Source

pub fn evaluate_with<R, E, S>( &self, solver: &mut S, cache: &mut EvaluatorCache<R>, ) -> Result<Vec<R>, E>
where R: Clone, S: Evaluator<T, R, E>,

Evaluates the expression using a persistent, external cache.

This is the most efficient way to evaluate an expression multiple times.

§How it works
  1. Validation: Checks if the cache matches the current expression’s UUID. If not, it clears the cache.
  2. Execution: Iterates through the node graph. Intermediate results are stored in the cache.
  3. Reuse: If called again, the internal vectors (Vec<Option<R>>) are reused, preventing heap allocation overhead.
§Cache Invalidation

The cache is tied to the structure of the expression. Modifying the expression (e.g., via compress(), prune(), or optimize()) changes the UUID, causing the cache to reset on the next call.

Source

pub fn evaluate_with_pruning<R, E, S>( &self, solver: &mut S, ) -> Result<Vec<R>, E>
where R: Clone, S: Evaluator<T, R, E>,

Evaluates the expression while aggressively freeing memory.

Unlike standard evaluation, which keeps all intermediate results until the end, this method calculates reference counts for every node. As soon as a node’s result is consumed by all its parents, the memory is dropped.

§Trade-offs
  • Pros: Significantly lower peak memory usage. Ideal for very large result types (e.g., Bitmaps, Images).
  • Cons: Slower execution speed due to the overhead of calculating reference counts and dropping values during iteration.
Source§

impl<T> Expression<T>

Source

pub fn new() -> Self

Creates a new, empty Expression.

Source

pub fn add_root(&mut self, root: NodeId)

registers a node as a “Root” of the expression.

Roots are the entry points for evaluation and dependency iteration. Nodes not reachable from a root are considered dead code.

§Panics

Panics if root is not a valid ID belonging to this expression.

§Example
let mut expr = logify::Expression::new();
let a = expr.set("A");
expr.add_root(a);
Source

pub fn build_root(&mut self, root: impl FnOnce(&mut Self) -> NodeId)

A helper to build logic and add it as a root in one closure.

This pattern is often more ergonomic than manually creating variables and passing them to add_root.

§Example
let mut expr = logify::Expression::new();

// Build (A & B) and add it as a root immediately
expr.build_root(|e| {
    let a = e.set("A");
    let b = e.set("B");
    e.intersection([a, b])
});
Source

pub fn roots(&self) -> Iter<'_, NodeId>

Iterate over the registered root IDs.

Examples found in repository?
examples/optimizer.rs (line 71)
53fn main() {
54    let mut config = OptimizerConfig {
55        merger: GeoMerger,
56        merger_depth: 2,
57        max_iterations: 0,
58    };
59
60    // Example 1. California is inside of USA, so it will be redacted
61    {
62        let builder = ExpressionBuilder::new();
63        let rule = logic!(
64            builder,
65            any![{ Geo::California }, { Geo::USA }, { Geo::Paris }]
66        );
67        builder.add_root(rule);
68
69        let mut expr = builder.build();
70
71        let root = expr.roots().next().unwrap();
72        println!("1. Before: {}", expr.to_string(root));
73
74        expr.optimize(&mut config);
75
76        let new_root = expr.roots().next().unwrap();
77        println!("1. After:  {}", expr.to_string(new_root));
78    }
79    println!();
80
81    // Example 2. Texas and France are disjoint, so the result is EMPTY
82    {
83        let builder = ExpressionBuilder::new();
84        let rule = logic!(builder, all![{ Geo::Texas }, { Geo::France }]);
85        builder.add_root(rule);
86
87        let mut expr = builder.build();
88
89        let root = expr.roots().next().unwrap();
90        println!("2. Before: {}", expr.to_string(root));
91
92        expr.optimize(&mut config);
93
94        let new_root = expr.roots().next().unwrap();
95        println!("2. After:  {}", expr.to_string(new_root));
96    }
97    println!();
98
99    // Example 3. California and Texas are both within the USA, so USA is redundant
100    {
101        let builder = ExpressionBuilder::new();
102        let rule = logic!(
103            builder,
104            all![any![{ Geo::California }, { Geo::Texas }], { Geo::USA }]
105        );
106        builder.add_root(rule);
107
108        let mut expr = builder.build();
109
110        let root = expr.roots().next().unwrap();
111        println!("3. Before: {}", expr.to_string(root));
112
113        expr.optimize(&mut config);
114
115        let new_root = expr.roots().next().unwrap();
116        println!("3. After:  {}", expr.to_string(new_root));
117    }
118}
Source

pub fn root_count(&self) -> usize

Returns the number of roots.

Source

pub fn nodes(&self) -> Iter<'_, Node<T>>

Iterate linearly over the raw internal nodes.

Note: This iterates the storage vector directly. It includes dead nodes and does not respect topological order.

Source

pub fn node_count(&self) -> usize

Returns the total number of nodes (active and dead) in memory.

Source

pub fn iter_dependencies(&self) -> ExpressionDependencyIter<'_, T>

Returns an iterator that visits nodes in topological order.

This is useful for evaluation or compilation, as it guarantees that a node’s dependencies (children) are yielded before the node itself.

  • Post-Order: Children before Parents.
  • Pruned: Only visits nodes reachable from the roots.
  • Unique: Visits each reachable node exactly once.
Source§

impl<T: Hash + PartialEq> Expression<T>

Source

pub fn set(&mut self, value: T) -> NodeId

Creates a leaf node representing a specific value A.

If an identical set A already exists, the existing ID is returned.

§Example
let mut expr = logify::Expression::new();
let a1 = expr.set("TagA");
let a2 = expr.set("TagA");

assert_eq!(a1, a2); // Deduplication happens automatically
Source

pub fn union(&mut self, children: impl IntoIterator<Item = NodeId>) -> NodeId

Creates a logical Union (A OR B).

This method acts as a Smart Constructor. It performs immediate on-the-fly simplifications to keep the graph small.

§Simplifications Performed
  • Commutativity: B | A -> A | B (sorted).
  • Idempotence: A | A -> A.
  • Identity: A | Empty -> A.
  • Annihilation: A | Universal -> Universal.
  • Complements: A | !A -> Universal.
  • Singleton: Union([A]) -> A.
§Example
let mut expr = Expression::new();
let a = expr.set("A");
let b = expr.set("B");

// Standard Union
let a_or_b = expr.union([a, b]);

// Simplification: A | A == A
let a_or_a = expr.union([a, a]);
assert_eq!(a_or_a, a);
Source

pub fn intersection( &mut self, children: impl IntoIterator<Item = NodeId>, ) -> NodeId

Creates a logical Intersection (A AND B).

This method acts as a Smart Constructor. It performs immediate on-the-fly simplifications to keep the graph small.

§Simplifications Performed
  • Commutativity: B & A -> A & B (sorted).
  • Idempotence: A & A -> A.
  • Identity: A & Universal -> A.
  • Annihilation: A & Empty -> Empty.
  • Complements: A & !A -> Empty.
  • Singleton: Intersection([A]) -> A.
§Example
let mut expr = Expression::new();
let a = expr.set("A");
let not_a = expr.complement(a);

// Simplification: A & !A == Empty
let impossible = expr.intersection([a, not_a]);
assert_eq!(impossible, logify::NodeId::EMPTY);
Source

pub fn complement(&self, child: NodeId) -> NodeId

Returns the complement A => A’.

Source§

impl<T: Display> Expression<T>

Source

pub fn to_string(&self, root: &NodeId) -> String

Recursively formats the expression starting from the given root.

§Example
let mut expr = Expression::new();
let a = expr.set("A");
let b = expr.set("B");
let root = expr.intersection([a, b]);

assert_eq!(expr.to_string(&root), "([A] & [B])");
Examples found in repository?
examples/optimizer.rs (line 72)
53fn main() {
54    let mut config = OptimizerConfig {
55        merger: GeoMerger,
56        merger_depth: 2,
57        max_iterations: 0,
58    };
59
60    // Example 1. California is inside of USA, so it will be redacted
61    {
62        let builder = ExpressionBuilder::new();
63        let rule = logic!(
64            builder,
65            any![{ Geo::California }, { Geo::USA }, { Geo::Paris }]
66        );
67        builder.add_root(rule);
68
69        let mut expr = builder.build();
70
71        let root = expr.roots().next().unwrap();
72        println!("1. Before: {}", expr.to_string(root));
73
74        expr.optimize(&mut config);
75
76        let new_root = expr.roots().next().unwrap();
77        println!("1. After:  {}", expr.to_string(new_root));
78    }
79    println!();
80
81    // Example 2. Texas and France are disjoint, so the result is EMPTY
82    {
83        let builder = ExpressionBuilder::new();
84        let rule = logic!(builder, all![{ Geo::Texas }, { Geo::France }]);
85        builder.add_root(rule);
86
87        let mut expr = builder.build();
88
89        let root = expr.roots().next().unwrap();
90        println!("2. Before: {}", expr.to_string(root));
91
92        expr.optimize(&mut config);
93
94        let new_root = expr.roots().next().unwrap();
95        println!("2. After:  {}", expr.to_string(new_root));
96    }
97    println!();
98
99    // Example 3. California and Texas are both within the USA, so USA is redundant
100    {
101        let builder = ExpressionBuilder::new();
102        let rule = logic!(
103            builder,
104            all![any![{ Geo::California }, { Geo::Texas }], { Geo::USA }]
105        );
106        builder.add_root(rule);
107
108        let mut expr = builder.build();
109
110        let root = expr.roots().next().unwrap();
111        println!("3. Before: {}", expr.to_string(root));
112
113        expr.optimize(&mut config);
114
115        let new_root = expr.roots().next().unwrap();
116        println!("3. After:  {}", expr.to_string(new_root));
117    }
118}
Source§

impl<T: Hash + PartialEq> Expression<T>

Source

pub fn prune<R>(self) -> Self

Removes unreachable nodes (Garbage Collection).

When you modify an expression (e.g., via build_into or manual logic), nodes that are no longer connected to any root may be left behind. This method rebuilds the expression, keeping only the live nodes.

§Important
  • Invalidation: All existing NodeIds are invalidated. Do not use old IDs after calling this.
  • Cache Reset: This invalidates any attached EvaluatorCache (resetting its UUID).
  • Reordering: Nodes may be re-ordered in memory.
Source

pub fn prune_with_cache<R>(self, cache: Option<&mut EvaluatorCache<R>>) -> Self

Removes unreachable nodes while preserving an external cache.

Identical to prune, but attempts to remap the values inside cache so that expensive computations don’t need to be redone.

§Arguments
  • cache - The cache to update. If provided, its internal mapping is updated to match the new node layout.
Source

pub fn absorb_raw<I>(&mut self, exprs: I)
where T: Clone, I: IntoIterator<Item = Expression<T>>,

Moves the logic from other expressions into this one.

This consumes the source expressions.

§Performance
  • Fast: Operates directly on internal storage without traversing the graph.
  • Dirty: Includes dead nodes from the source. If the source expression contains garbage (nodes not connected to roots), that garbage is copied into self. Call prune afterwards if this is a concern.
Source

pub fn merge_raw<'a, I>(&mut self, exprs: I)
where T: 'a + Clone, I: IntoIterator<Item = &'a Expression<T>>,

Clones the logic from multiple expressions into this one.

Useful if you need to keep the original expressions intact.

§Performance
  • Fast: Linear copy of internal storage. May be slower than absorb_raw because it clones every term.
  • Dirty: Includes dead nodes from the source.
Source

pub fn compress<R>(self, cache: Option<&mut EvaluatorCache<R>>) -> Self

Globally deduplicates logic patterns (Common Subexpression Elimination).

While the builder deduplicates nodes (e.g., A & B is only stored once), it does not automatically refactor deeply nested structures. compress finds repeated patterns across the entire graph and factors them out.

§Example
  • Before: (A & B & C) and (A & B & D) are separate nodes.
  • After: (A & B) becomes a shared node, referenced by both parents.
§Use Case

Recommended to run after optimize, as optimization often exposes new structural similarities.

Source§

impl<T: Hash + PartialEq> Expression<T>

Source

pub fn optimize<M: Mergeable<T>>(&mut self, config: &mut OptimizerConfig<M>)

Applies logic reduction and domain-specific simplification to the expression.

This method performs operations such as:

  • Flattening: Union(A, Union(B, C)) becomes Union(A, B, C).
  • De Morgan’s Laws: Distributes negations to minimize depth.
  • Absorption: A & (A | B) simplifies to A.
  • Custom Merging: Uses the provided Mergeable implementation to combine sets.
§Dead Nodes

Optimization rewrites connections between nodes. This often leaves behind “dead” nodes (nodes that are no longer connected to any root). While this does not affect evaluation correctness, you may wish to call Expression::clean afterwards if memory footprint is a concern.

Examples found in repository?
examples/optimizer.rs (line 74)
53fn main() {
54    let mut config = OptimizerConfig {
55        merger: GeoMerger,
56        merger_depth: 2,
57        max_iterations: 0,
58    };
59
60    // Example 1. California is inside of USA, so it will be redacted
61    {
62        let builder = ExpressionBuilder::new();
63        let rule = logic!(
64            builder,
65            any![{ Geo::California }, { Geo::USA }, { Geo::Paris }]
66        );
67        builder.add_root(rule);
68
69        let mut expr = builder.build();
70
71        let root = expr.roots().next().unwrap();
72        println!("1. Before: {}", expr.to_string(root));
73
74        expr.optimize(&mut config);
75
76        let new_root = expr.roots().next().unwrap();
77        println!("1. After:  {}", expr.to_string(new_root));
78    }
79    println!();
80
81    // Example 2. Texas and France are disjoint, so the result is EMPTY
82    {
83        let builder = ExpressionBuilder::new();
84        let rule = logic!(builder, all![{ Geo::Texas }, { Geo::France }]);
85        builder.add_root(rule);
86
87        let mut expr = builder.build();
88
89        let root = expr.roots().next().unwrap();
90        println!("2. Before: {}", expr.to_string(root));
91
92        expr.optimize(&mut config);
93
94        let new_root = expr.roots().next().unwrap();
95        println!("2. After:  {}", expr.to_string(new_root));
96    }
97    println!();
98
99    // Example 3. California and Texas are both within the USA, so USA is redundant
100    {
101        let builder = ExpressionBuilder::new();
102        let rule = logic!(
103            builder,
104            all![any![{ Geo::California }, { Geo::Texas }], { Geo::USA }]
105        );
106        builder.add_root(rule);
107
108        let mut expr = builder.build();
109
110        let root = expr.roots().next().unwrap();
111        println!("3. Before: {}", expr.to_string(root));
112
113        expr.optimize(&mut config);
114
115        let new_root = expr.roots().next().unwrap();
116        println!("3. After:  {}", expr.to_string(new_root));
117    }
118}

Trait Implementations§

Source§

impl<T: Clone + Hash + PartialEq> Clone for Expression<T>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T> Default for Expression<T>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<'de, T> Deserialize<'de> for Expression<T>
where T: Serialize + for<'a> Deserialize<'a> + Hash + PartialEq,

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl<'a, T: Clone + Hash + PartialEq> Extend<&'a Expression<T>> for Expression<T>

Source§

fn extend<I: IntoIterator<Item = &'a Expression<T>>>(&mut self, iter: I)

Extends a collection with the contents of an iterator. Read more
Source§

fn extend_one(&mut self, item: A)

🔬This is a nightly-only experimental API. (extend_one)
Extends a collection with exactly one element.
Source§

fn extend_reserve(&mut self, additional: usize)

🔬This is a nightly-only experimental API. (extend_one)
Reserves capacity in a collection for the given number of additional elements. Read more
Source§

impl<'a, T: Hash + PartialEq + Clone> Extend<&'a ExpressionBuilder<T>> for Expression<T>

Source§

fn extend<I: IntoIterator<Item = &'a ExpressionBuilder<T>>>(&mut self, iter: I)

Extends a collection with the contents of an iterator. Read more
Source§

fn extend_one(&mut self, item: A)

🔬This is a nightly-only experimental API. (extend_one)
Extends a collection with exactly one element.
Source§

fn extend_reserve(&mut self, additional: usize)

🔬This is a nightly-only experimental API. (extend_one)
Reserves capacity in a collection for the given number of additional elements. Read more
Source§

impl<T: Hash + PartialEq> Extend<Expression<T>> for Expression<T>

Source§

fn extend<I: IntoIterator<Item = Expression<T>>>(&mut self, iter: I)

Extends a collection with the contents of an iterator. Read more
Source§

fn extend_one(&mut self, item: A)

🔬This is a nightly-only experimental API. (extend_one)
Extends a collection with exactly one element.
Source§

fn extend_reserve(&mut self, additional: usize)

🔬This is a nightly-only experimental API. (extend_one)
Reserves capacity in a collection for the given number of additional elements. Read more
Source§

impl<T: Hash + PartialEq> Extend<ExpressionBuilder<T>> for Expression<T>

Source§

fn extend<I: IntoIterator<Item = ExpressionBuilder<T>>>(&mut self, iter: I)

Extends a collection with the contents of an iterator. Read more
Source§

fn extend_one(&mut self, item: A)

🔬This is a nightly-only experimental API. (extend_one)
Extends a collection with exactly one element.
Source§

fn extend_reserve(&mut self, additional: usize)

🔬This is a nightly-only experimental API. (extend_one)
Reserves capacity in a collection for the given number of additional elements. Read more
Source§

impl<T> IntoIterator for &Expression<T>

Source§

type Item = &Expression<T>

The type of the elements being iterated over.
Source§

type IntoIter = Once<&Expression<T>>

Which kind of iterator are we turning this into?
Source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more
Source§

impl<T> IntoIterator for Expression<T>

Source§

type Item = Expression<T>

The type of the elements being iterated over.
Source§

type IntoIter = Once<Expression<T>>

Which kind of iterator are we turning this into?
Source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more
Source§

impl<T> Serialize for Expression<T>
where T: Serialize + for<'a> Deserialize<'a> + Hash + PartialEq,

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

§

impl<T> Freeze for Expression<T>

§

impl<T> RefUnwindSafe for Expression<T>
where T: RefUnwindSafe,

§

impl<T> Send for Expression<T>
where T: Send,

§

impl<T> Sync for Expression<T>
where T: Sync,

§

impl<T> Unpin for Expression<T>
where T: Unpin,

§

impl<T> UnwindSafe for Expression<T>
where T: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,