Trait valuable::Visit[][src]

pub trait Visit {
    fn visit_value(&mut self, value: Value<'_>);

    fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) { ... }
fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) { ... }
fn visit_primitive_slice(&mut self, slice: Slice<'_>) { ... }
fn visit_entry(&mut self, key: Value<'_>, value: Value<'_>) { ... } }
Expand description

Traverse a value’s fields and variants.

Each method of the Visit trait is a hook that enables the implementor to observe value fields. By default, most methods are implemented as a no-op. The visit_primitive_slice default implementation will iterate the slice, calling visit_value with each item.

To recurse, the implementor must implement methods to visit the arguments.

Examples

Recursively printing a Rust value.

use valuable::{NamedValues, Valuable, Value, Visit};

struct Print(String);

impl Print {
    fn indent(&self) -> Print {
       Print(format!("{}    ", self.0))
    }
}

impl Visit for Print {
    fn visit_value(&mut self, value: Value<'_>) {
        match value {
            Value::Structable(v) => {
                let def = v.definition();
                // Print the struct name
                println!("{}{}:", self.0, def.name());

                // Visit fields
                let mut visit = self.indent();
                v.visit(&mut visit);
            }
            Value::Enumerable(v) => {
                let def = v.definition();
                let variant = v.variant();
                // Print the enum name
                println!("{}{}::{}:", self.0, def.name(), variant.name());

                // Visit fields
                let mut visit = self.indent();
                v.visit(&mut visit);
            }
            Value::Listable(v) => {
                println!("{}", self.0);

                // Visit fields
                let mut visit = self.indent();
                v.visit(&mut visit);
            }
            Value::Mappable(v) => {
                println!("{}", self.0);

                // Visit fields
                let mut visit = self.indent();
                v.visit(&mut visit);
            }
            // Primitive or unknown type, just render Debug
            v => println!("{:?}", v),
        }
    }

    fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) {
        for (field, value) in named_values {
            print!("{}- {}: ", self.0, field.name());
            value.visit(self);
        }
    }

    fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) {
        for value in values {
            print!("{}- ", self.0);
            value.visit(self);
        }
    }

    fn visit_entry(&mut self, key: Value<'_>, value: Value<'_>) {
        print!("{}- {:?}: ", self.0, key);
        value.visit(self);
    }
}

#[derive(Valuable)]
struct Person {
    name: String,
    age: u32,
    addresses: Vec<Address>,
}

#[derive(Valuable)]
struct Address {
    street: String,
    city: String,
    zip: String,
}

let person = Person {
    name: "Angela Ashton".to_string(),
    age: 31,
    addresses: vec![
        Address {
            street: "123 1st Ave".to_string(),
            city: "Townsville".to_string(),
            zip: "12345".to_string(),
        },
        Address {
            street: "555 Main St.".to_string(),
            city: "New Old Town".to_string(),
            zip: "55555".to_string(),
        },
    ],
};

let mut print = Print("".to_string());
valuable::visit(&person, &mut print);

Required methods

Visit a single value.

The visit_value method is called once when visiting single primitive values. When visiting Listable types, the visit_value method is called once per item in the listable type.

Note, in the case of Listable types containing primitive types, visit_primitive_slice can be implemented instead for less overhead.

Examples

Visiting a single value.

use valuable::{Valuable, Visit, Value};

struct Print;

impl Visit for Print {
    fn visit_value(&mut self, value: Value<'_>) {
        println!("{:?}", value);
    }
}

let my_val = 123;
my_val.visit(&mut Print);

Visiting multiple values in a list.

use valuable::{Valuable, Value, Visit};

struct PrintList { comma: bool };

impl Visit for PrintList {
    fn visit_value(&mut self, value: Value<'_>) {
        match value {
            Value::Listable(v) => v.visit(self),
            value => {
                if self.comma {
                    println!(", {:?}", value);
                } else {
                    print!("{:?}", value);
                    self.comma = true;
                }
            }
        }
    }
}

let my_list = vec![1, 2, 3, 4, 5];
valuable::visit(&my_list, &mut PrintList { comma: false });

Provided methods

Visit a struct or enum’s named fields.

When the struct/enum is statically defined, all fields are known ahead of time and visit_named_fields is called once with all field values. When the struct/enum is dynamic, then the visit_named_fields method may be called multiple times.

See Structable and Enumerable for static vs. dynamic details.

Examples

Visiting all fields in a struct.

use valuable::{NamedValues, Valuable, Value, Visit};

#[derive(Valuable)]
struct MyStruct {
    hello: String,
    world: u32,
}

struct Print;

impl Visit for Print {
    fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) {
        for (field, value) in named_values {
            println!("{:?}: {:?}", field, value);
        }
    }

    fn visit_value(&mut self, value: Value<'_>) {
        match value {
            Value::Structable(v) => v.visit(self),
            _ => {} // do nothing for other types
        }
    }
}

let my_struct = MyStruct {
    hello: "Hello world".to_string(),
    world: 42,
};

valuable::visit(&my_struct, &mut Print);

Visit a struct or enum’s unnamed fields.

When the struct/enum is statically defined, all fields are known ahead of time and visit_unnamed_fields is called once with all field values. When the struct/enum is dynamic, then the visit_unnamed_fields method may be called multiple times.

See Structable and Enumerable for static vs. dynamic details.

Examples

Visiting all fields in a struct.

use valuable::{Valuable, Value, Visit};

#[derive(Valuable)]
struct MyStruct(String, u32);

struct Print;

impl Visit for Print {
    fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) {
        for value in values {
            println!("{:?}", value);
        }
    }

    fn visit_value(&mut self, value: Value<'_>) {
        match value {
            Value::Structable(v) => v.visit(self),
            _ => {} // do nothing for other types
        }
    }
}

let my_struct = MyStruct("Hello world".to_string(), 42);

valuable::visit(&my_struct, &mut Print);

Visit a primitive slice.

This method exists as an optimization when visiting Listable types. By default, Listable types are visited by passing each item to visit_value. However, if the listable stores a primitive type within contiguous memory, then visit_primitive_slice is called instead.

When implementing visit_primitive_slice, be aware that the method may be called multiple times for a single Listable type.

Examples

A vec calls visit_primitive_slice one time, but a VecDeque will call visit_primitive_slice twice.

use valuable::{Valuable, Value, Visit, Slice};
use std::collections::VecDeque;

struct Count(u32);

impl Visit for Count {
    fn visit_primitive_slice(&mut self, slice: Slice<'_>) {
        self.0 += 1;
    }

    fn visit_value(&mut self, value: Value<'_>) {
        match value {
            Value::Listable(v) => v.visit(self),
            _ => {} // do nothing for other types
        }
    }
}

let vec = vec![1, 2, 3, 4, 5];

let mut count = Count(0);
valuable::visit(&vec, &mut count);
assert_eq!(1, count.0);

let mut vec_deque = VecDeque::from(vec);

let mut count = Count(0);
valuable::visit(&vec_deque, &mut count);

assert_eq!(2, count.0);

fn visit_entry(&mut self, key: Value<'_>, value: Value<'_>)

Visit a Mappable’s entries.

The visit_entry method is called once for each entry contained by a Mappable.

Examples

Visit a map’s entries

use valuable::{Valuable, Value, Visit};
use std::collections::HashMap;

let mut map = HashMap::new();
map.insert("hello", 123);
map.insert("world", 456);

struct Print;

impl Visit for Print {
    fn visit_entry(&mut self, key: Value<'_>, value: Value<'_>) {
        println!("{:?} => {:?}", key, value);
    }

    fn visit_value(&mut self, value: Value<'_>) {
        match value {
            Value::Mappable(v) => v.visit(self),
            _ => {} // do nothing for other types
        }
    }
}

valuable::visit(&map, &mut Print);

Implementations on Foreign Types

fn visit_entry(&mut self, key: Value<'_>, value: Value<'_>)

fn visit_entry(&mut self, key: Value<'_>, value: Value<'_>)

Implementors