inspect-core 0.1.0

Core types and traits for the inspect-rs introspection system
Documentation
//! Inspect implementations for standard library types.

#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, string::ToString, vec::Vec};
#[cfg(feature = "std")]
use std::collections::{HashMap, HashSet};

use crate::{Children, FieldInfo, Inspect, InspectCx, Kind, TypeInfo, ValueRef, VariantInfo};

// Option<T>
impl<T: Inspect> Inspect for Option<T> {
    fn inspect(&self, cx: &mut InspectCx<'_>) -> ValueRef<'_> {
        cx.visit_node();

        match self {
            Some(value) => {
                let variant = VariantInfo::new("Some", 1);
                let child = value.inspect(cx);
                let field = FieldInfo::tuple(0);

                ValueRef::with_children(
                    Kind::Option,
                    TypeInfo::new("Option"),
                    Children::direct(vec![(field, child)]),
                )
                .with_variant(variant)
            }
            None => {
                let variant = VariantInfo::new("None", 0);
                ValueRef::with_children(
                    Kind::Option,
                    TypeInfo::new("Option"),
                    Children::direct(vec![]),
                )
                .with_variant(variant)
            }
        }
    }
}

// Result<T, E>
impl<T: Inspect, E: Inspect> Inspect for Result<T, E> {
    fn inspect(&self, cx: &mut InspectCx<'_>) -> ValueRef<'_> {
        cx.visit_node();

        match self {
            Ok(value) => {
                let variant = VariantInfo::new("Ok", 0);
                let child = value.inspect(cx);
                let field = FieldInfo::tuple(0);

                ValueRef::with_children(
                    Kind::Result,
                    TypeInfo::new("Result"),
                    Children::direct(vec![(field, child)]),
                )
                .with_variant(variant)
            }
            Err(error) => {
                let variant = VariantInfo::new("Err", 1);
                let child = error.inspect(cx);
                let field = FieldInfo::tuple(0);

                ValueRef::with_children(
                    Kind::Result,
                    TypeInfo::new("Result"),
                    Children::direct(vec![(field, child)]),
                )
                .with_variant(variant)
            }
        }
    }
}

// Vec<T>
impl<T: Inspect> Inspect for Vec<T> {
    fn inspect(&self, cx: &mut InspectCx<'_>) -> ValueRef<'_> {
        cx.visit_node();

        let len = self.len();
        let max_items = cx.limits().max_items;
        let display_len = len.min(max_items);

        let children: Vec<_> = self
            .iter()
            .take(display_len)
            .enumerate()
            .map(|(idx, item)| {
                let field = FieldInfo::tuple(idx);
                (field, item.inspect(cx))
            })
            .collect();

        ValueRef::with_children(Kind::Sequence, TypeInfo::new("Vec"), Children::direct(children))
    }
}

// Array [T; N]
impl<T: Inspect, const N: usize> Inspect for [T; N] {
    fn inspect(&self, cx: &mut InspectCx<'_>) -> ValueRef<'_> {
        cx.visit_node();

        let max_items = cx.limits().max_items;
        let display_len = N.min(max_items);

        let children: Vec<_> = self
            .iter()
            .take(display_len)
            .enumerate()
            .map(|(idx, item)| {
                let field = FieldInfo::tuple(idx);
                (field, item.inspect(cx))
            })
            .collect();

        ValueRef::with_children(Kind::Sequence, TypeInfo::new("[T; N]"), Children::direct(children))
    }
}

// Tuples
impl<T0: Inspect> Inspect for (T0,) {
    fn inspect(&self, cx: &mut InspectCx<'_>) -> ValueRef<'_> {
        cx.visit_node();
        let children = vec![(FieldInfo::tuple(0), self.0.inspect(cx))];
        ValueRef::with_children(Kind::Tuple, TypeInfo::new("tuple"), Children::direct(children))
    }
}

impl<T0: Inspect, T1: Inspect> Inspect for (T0, T1) {
    fn inspect(&self, cx: &mut InspectCx<'_>) -> ValueRef<'_> {
        cx.visit_node();
        let children = vec![
            (FieldInfo::tuple(0), self.0.inspect(cx)),
            (FieldInfo::tuple(1), self.1.inspect(cx)),
        ];
        ValueRef::with_children(Kind::Tuple, TypeInfo::new("tuple"), Children::direct(children))
    }
}

impl<T0: Inspect, T1: Inspect, T2: Inspect> Inspect for (T0, T1, T2) {
    fn inspect(&self, cx: &mut InspectCx<'_>) -> ValueRef<'_> {
        cx.visit_node();
        let children = vec![
            (FieldInfo::tuple(0), self.0.inspect(cx)),
            (FieldInfo::tuple(1), self.1.inspect(cx)),
            (FieldInfo::tuple(2), self.2.inspect(cx)),
        ];
        ValueRef::with_children(Kind::Tuple, TypeInfo::new("tuple"), Children::direct(children))
    }
}

// HashMap (std only)
#[cfg(feature = "std")]
impl<K: Inspect, V: Inspect> Inspect for HashMap<K, V> {
    fn inspect(&self, cx: &mut InspectCx<'_>) -> ValueRef<'_> {
        cx.visit_node();

        let max_items = cx.limits().max_items;
        let display_len = self.len().min(max_items);

        let children: Vec<_> = self
            .iter()
            .take(display_len)
            .enumerate()
            .map(|(idx, (_k, v))| {
                let field = FieldInfo::tuple(idx);
                (field, v.inspect(cx))
            })
            .collect();

        ValueRef::with_children(Kind::Map, TypeInfo::new("HashMap"), Children::direct(children))
    }
}

// HashSet (std only)
#[cfg(feature = "std")]
impl<T: Inspect> Inspect for HashSet<T> {
    fn inspect(&self, cx: &mut InspectCx<'_>) -> ValueRef<'_> {
        cx.visit_node();

        let max_items = cx.limits().max_items;
        let display_len = self.len().min(max_items);

        let children: Vec<_> = self
            .iter()
            .take(display_len)
            .enumerate()
            .map(|(idx, item)| {
                let field = FieldInfo::tuple(idx);
                (field, item.inspect(cx))
            })
            .collect();

        ValueRef::with_children(Kind::Set, TypeInfo::new("HashSet"), Children::direct(children))
    }
}

// References
impl<T: Inspect + ?Sized> Inspect for &T {
    fn inspect(&self, cx: &mut InspectCx<'_>) -> ValueRef<'_> {
        (*self).inspect(cx)
    }
}

impl<T: Inspect + ?Sized> Inspect for &mut T {
    fn inspect(&self, cx: &mut InspectCx<'_>) -> ValueRef<'_> {
        (**self).inspect(cx)
    }
}

// Box
impl<T: Inspect + ?Sized> Inspect for Box<T> {
    fn inspect(&self, cx: &mut InspectCx<'_>) -> ValueRef<'_> {
        (**self).inspect(cx)
    }
}