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//! - Validation error type: [`MetadataValidationError`] — aggregate schema validation issues
36//!
37//! ## Example
38//!
39//! ```rust
40//! use qubit_metadata::{Metadata, MetadataFilter};
41//!
42//! let meta = Metadata::new()
43//!     .with("author", "alice")
44//!     .with("priority", 3_i64);
45//!
46//! // Convenience API: missing key and type mismatch both collapse to None.
47//! let author: Option<String> = meta.get("author");
48//! assert_eq!(author.as_deref(), Some("alice"));
49//!
50//! // Explicit API: preserve failure reasons for diagnostics.
51//! let priority = meta.try_get::<i64>("priority").unwrap();
52//! assert_eq!(priority, 3);
53//!
54//! let filter = MetadataFilter::builder()
55//!     .eq("author", "alice")
56//!     .and_ge("priority", 1_i64)
57//!     .build()
58//!     .unwrap();
59//! assert!(filter.matches(&meta));
60//! ```
61//!
62
63#![deny(missing_docs)]
64
65mod filter;
66mod from_metadata_value;
67mod into_metadata_value;
68mod metadata;
69mod metadata_error;
70mod metadata_result;
71mod metadata_validation_error;
72mod schema;
73
74pub use filter::Condition;
75pub use filter::FilterMatchOptions;
76pub use filter::MetadataFilter;
77pub use filter::MetadataFilterBuilder;
78pub use filter::MissingKeyPolicy;
79pub use filter::NumberComparisonPolicy;
80pub use from_metadata_value::FromMetadataValue;
81pub use into_metadata_value::IntoMetadataValue;
82pub use metadata::Metadata;
83pub use metadata_error::MetadataError;
84pub use metadata_result::MetadataResult;
85pub use metadata_result::MetadataValidationResult;
86pub use metadata_validation_error::MetadataValidationError;
87pub use schema::MetadataField;
88pub use schema::MetadataSchema;
89pub use schema::MetadataSchemaBuilder;
90pub use schema::UnknownFieldPolicy;