obj-db 1.0.2

Embedded document database. Stable file format, full ACID, single-file portability.
Documentation
//! Macro hygiene gate for `#[derive(obj::Document)]` (M9 #80).
//!
//! The derive must use absolute paths (`::obj::Document`,
//! `::obj::IndexSpec`, `::obj::IndexKind`, `::std::vec::Vec`,
//! `::std::string::String`) so that a user crate that locally
//! shadows any of these names still compiles. This test sets up the
//! adversarial environment — a deeply-nested module path with local
//! types that match every name the derive references — and verifies
//! the emitted impl resolves to the real items.

// The local shadows below are intentionally unused — they exist only
// to break the derive if it forgets to use absolute paths.
#![allow(dead_code)]

use obj::Document;

// Outer module so the derive lands beneath a non-empty path.
mod outer {
    pub mod middle {
        pub mod inner {
            use serde::{Deserialize, Serialize};

            // Local types that shadow every crate-level item the
            // derive references. None of them are used by anything in
            // this module — they exist solely to poison the namespace
            // and break the derive if it ever emits a non-absolute
            // path. The derive uses `::obj::IndexSpec` (absolute), so
            // these shadows are inert.
            #[allow(dead_code)] // intentional shadow
            pub struct IndexSpec;
            #[allow(dead_code)] // intentional shadow
            pub struct IndexKind;
            #[allow(dead_code)] // intentional shadow
            pub struct Document;
            #[allow(dead_code)] // intentional shadow
            pub struct Vec;
            #[allow(dead_code)] // intentional shadow
            pub struct String;

            // Apply the derive to a struct in this poisoned module.
            // The struct uses fully-qualified types for its real
            // fields so the shadowed names don't break the field
            // resolution itself.
            #[derive(Serialize, Deserialize, obj::Document)]
            #[obj(version = 2, collection = "shadowed")]
            #[obj(index_composite(fields = ("a", "b"), name = "by_a_b"))]
            pub struct Shadowed {
                #[obj(index = unique)]
                pub a: ::std::string::String,
                #[obj(index)]
                pub b: u32,
                #[obj(index = each)]
                pub c: ::std::vec::Vec<u32>,
            }
        }
    }
}

#[test]
fn derive_resolves_absolute_paths_under_local_shadows() {
    type S = outer::middle::inner::Shadowed;
    assert_eq!(<S as Document>::COLLECTION, "shadowed");
    assert_eq!(<S as Document>::VERSION, 2);

    let specs = <S as Document>::indexes();
    // 3 field indexes (a / b / c) + 1 composite (by_a_b) = 4.
    assert_eq!(specs.len(), 4);
    assert_eq!(specs[0].name, "a");
    assert_eq!(specs[1].name, "b");
    assert_eq!(specs[2].name, "c");
    assert_eq!(specs[3].name, "by_a_b");
}