Enum valuable::StructDef[][src]

#[non_exhaustive]
pub enum StructDef<'a> {
    Static {
        name: &'static str,
        fields: Fields<'static>,
    },
    Dynamic {
        name: &'a str,
        fields: Fields<'a>,
    },
}
Expand description

A struct’s name, fields, and other struct-level information.

Returned by Structable::definition(), StructDef provides the caller with information about the struct’s definition.

Variants (Non-exhaustive)

This enum is marked as non-exhaustive
Non-exhaustive enums could have additional variants added in future. Therefore, when matching against variants of non-exhaustive enums, an extra wildcard arm must be added to account for any future variants.

Static

Fields

This variant is marked as non-exhaustive
Non-exhaustive enum variants could have additional fields added in future. Therefore, non-exhaustive enum variants cannot be constructed in external crates and cannot be matched against.
name: &'static str

The struct’s name.

fields: Fields<'static>

The struct’s fields.

The struct is statically-defined, all fields are known ahead of time.

Most Structable definitions for Rust struct types will be StructDef::Static.

Examples

A statically defined struct

use valuable::{Fields, Valuable, Structable, StructDef};

#[derive(Valuable)]
struct MyStruct {
    foo: &'static str,
}

let my_struct = MyStruct { foo: "Hello" };
let fields = match my_struct.definition() {
    StructDef::Static { name, fields, ..} => {
        assert_eq!("MyStruct", name);
        fields
    }
    _ => unreachable!(),
};

match fields {
    Fields::Named(named_fields) => {
        assert_eq!(1, named_fields.len());
        assert_eq!("foo", named_fields[0].name());
    }
    _ => unreachable!(),
}

Dynamic

Fields

This variant is marked as non-exhaustive
Non-exhaustive enum variants could have additional fields added in future. Therefore, non-exhaustive enum variants cannot be constructed in external crates and cannot be matched against.
name: &'a str

The struct’s name

fields: Fields<'a>

The struct’s fields.

The struct is dynamically-defined, not all fields are known ahead of time.

A dynamically-defined struct could be represented using Mappable, though, using Structable offers benefits in a couple of cases. For example, when serializing a Value, some formats will serialize maps and structs differently. In this case, differentiating the two is required. There also are times when some struct fields are known statically, but not all of them (see second example).

Examples

The struct stores field values in a HashMap.

use valuable::{Fields, NamedField, NamedValues, Structable, StructDef, Value, Valuable, Visit};
use std::collections::HashMap;

/// A dynamic struct
struct Dyn {
    // The struct name
    name: String,

    // Named values.
    values: HashMap<String, Box<dyn Valuable>>,
}

impl Valuable for Dyn {
    fn as_value(&self) -> Value<'_> {
        Value::Structable(self)
    }

    fn visit(&self, visit: &mut dyn Visit) {
        // This could be optimized to batch some.
        for (field, value) in self.values.iter() {
            visit.visit_named_fields(&NamedValues::new(
                &[NamedField::new(field)],
                &[value.as_value()],
            ));
        }
    }
}

impl Structable for Dyn {
    fn definition(&self) -> StructDef<'_> {
        StructDef::new_dynamic(&self.name, Fields::Named(&[]))
    }
}

Some fields are known statically.

use valuable::{Fields, NamedField, NamedValues, Structable, StructDef, Value, Valuable, Visit};
use std::collections::HashMap;

struct HalfStatic {
    foo: u32,
    bar: u32,
    extra_values: HashMap<String, Box<dyn Valuable>>,
}

impl Valuable for HalfStatic {
    fn as_value(&self) -> Value<'_> {
        Value::Structable(self)
    }

    fn visit(&self, visit: &mut dyn Visit) {
        // First, visit static fields
        visit.visit_named_fields(&NamedValues::new(
            FIELDS,
            &[self.foo.as_value(), self.bar.as_value()],
        ));

        // This could be optimized to batch some.
        for (field, value) in self.extra_values.iter() {
            visit.visit_named_fields(&NamedValues::new(
                &[NamedField::new(field)],
                &[value.as_value()],
            ));
        }
    }
}

static FIELDS: &[NamedField<'static>] = &[
    NamedField::new("foo"),
    NamedField::new("bar"),
];

impl Structable for HalfStatic {
    fn definition(&self) -> StructDef<'_> {
        // Include known fields.
        StructDef::new_dynamic(
            "HalfStatic",
            Fields::Named(FIELDS))
    }
}

Implementations

Create a new StructDef::Static instance.

This should be used when a struct’s fields are fixed and known ahead of time.

Examples
use valuable::{StructDef, Fields};

let def = StructDef::new_static("Foo", Fields::Unnamed(2));

Create a new StructDef::Dynamic instance.

This is used when the struct’s fields may vary at runtime.

Examples
use valuable::{StructDef, Fields};

let def = StructDef::new_dynamic("Foo", Fields::Unnamed(3));

Returns the struct’s name

Examples

With a static struct

use valuable::{StructDef, Fields};

let def = StructDef::new_static("Foo", Fields::Unnamed(1));
assert_eq!("Foo", def.name());

With a dynamic struct

use valuable::{StructDef, Fields};

let def = StructDef::new_dynamic("Foo", Fields::Unnamed(2));
assert_eq!("Foo", def.name());

Returns the struct’s fields

Examples

With a static struct

use valuable::{StructDef, Fields};

let def = StructDef::new_static("Foo", Fields::Unnamed(3));
assert!(matches!(def.fields(), Fields::Unnamed(_)));

With a dynamic struct

use valuable::{StructDef, Fields};

let def = StructDef::new_dynamic("Foo", Fields::Unnamed(1));
assert!(matches!(def.fields(), Fields::Unnamed(_)));

Returns true if the struct is statically defined.

Examples

With a static struct

use valuable::{StructDef, Fields};

let def = StructDef::new_static("Foo", Fields::Unnamed(2));
assert!(def.is_static());

With a dynamic struct

use valuable::{StructDef, Fields};

let def = StructDef::new_dynamic("Foo", Fields::Unnamed(4));
assert!(!def.is_static());

Returns true if the struct is dynamically defined.

Examples

With a static struct

use valuable::{StructDef, Fields};

let def = StructDef::new_static("Foo", Fields::Unnamed(1));
assert!(!def.is_dynamic());

With a dynamic struct

use valuable::{StructDef, Fields};

let def = StructDef::new_dynamic("Foo", Fields::Unnamed(1));
assert!(def.is_dynamic());

Trait Implementations

Formats the value using the given formatter. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Performs the conversion.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.