Skip to main content

qubit_metadata/
lib.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 *    SPDX-License-Identifier: Apache-2.0
6 *
7 *    Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10//! # qubit-metadata
11//!
12//! A general-purpose, type-safe, extensible metadata model for Rust.
13//!
14//! This crate provides a [`Metadata`] type — a structured key-value store
15//! designed for any domain that needs to attach typed annotations to its data
16//! models. It is not a plain `HashMap` — it is a structured extensibility point
17//! with type-safe access, [`qubit_value::Value`] backing, and first-class
18//! `serde` support.
19//!
20//! ## Design Goals
21//!
22//! - **Type Safety**: Typed get/set API backed by [`qubit_value::Value`]
23//! - **Generality**: No domain-specific assumptions — usable in any Rust project
24//! - **Schema Support**: Optional [`MetadataSchema`] validation for metadata and filters
25//! - **Serialization**: First-class `serde` support for JSON interchange
26//! - **Filtering**: [`MetadataFilter`] for composable query conditions
27//!
28//! ## Features
29//!
30//! - Core type: [`Metadata`] — an ordered key-value store with typed accessors
31//! - Schema type: [`MetadataSchema`] — field definitions based on [`qubit_datatype::DataType`]
32//! - Filter type: [`MetadataFilter`] — composable filter expressions for metadata queries
33//! - Condition type: [`Condition`] — individual comparison predicates
34//! - Error type: [`MetadataError`] — explicit failure reporting for `try_*` APIs
35//!
36//! ## Example
37//!
38//! ```rust
39//! use qubit_metadata::{Metadata, MetadataFilter};
40//!
41//! let meta = Metadata::new()
42//!     .with("author", "alice")
43//!     .with("priority", 3_i64);
44//!
45//! // Convenience API: missing key and type mismatch both collapse to None.
46//! let author: Option<String> = meta.get("author");
47//! assert_eq!(author.as_deref(), Some("alice"));
48//!
49//! // Explicit API: preserve failure reasons for diagnostics.
50//! let priority = meta.try_get::<i64>("priority").unwrap();
51//! assert_eq!(priority, 3);
52//!
53//! let filter = MetadataFilter::builder()
54//!     .eq("author", "alice")
55//!     .and_ge("priority", 1_i64)
56//!     .build()
57//!     .unwrap();
58//! assert!(filter.matches(&meta));
59//! ```
60//!
61
62#![deny(missing_docs)]
63
64mod filter;
65mod from_metadata_value;
66mod into_metadata_value;
67mod metadata;
68mod metadata_error;
69mod metadata_result;
70mod schema;
71
72pub use filter::Condition;
73pub use filter::FilterMatchOptions;
74pub use filter::MetadataFilter;
75pub use filter::MetadataFilterBuilder;
76pub use filter::MissingKeyPolicy;
77pub use filter::NumberComparisonPolicy;
78pub use from_metadata_value::FromMetadataValue;
79pub use into_metadata_value::IntoMetadataValue;
80pub use metadata::Metadata;
81pub use metadata_error::MetadataError;
82pub use metadata_result::MetadataResult;
83pub use schema::MetadataField;
84pub use schema::MetadataSchema;
85pub use schema::MetadataSchemaBuilder;
86pub use schema::UnknownFieldPolicy;