scim_server/resource/value_objects/
mod.rs

1//! Value objects for SCIM resource domain primitives.
2//!
3//! This module contains immutable value objects that encapsulate validation logic
4//! for core SCIM domain concepts. Each value object enforces invariants at construction
5//! time, making invalid states unrepresentable.
6//!
7//! ## Design Principles
8//!
9//! - **Immutable**: Once created, value objects cannot be modified
10//! - **Self-validating**: Validation happens at construction time via explicit constructors
11//! - **Type-safe**: Invalid states are unrepresentable at compile time
12//! - **Domain-focused**: Each type represents a specific business concept
13//!
14//! ## Usage Pattern
15//!
16/// ```rust
17/// use scim_server::resource::value_objects::ResourceId;
18///
19/// fn main() -> Result<(), Box<dyn std::error::Error>> {
20///     // Explicit validation at construction
21///     let id = ResourceId::new("2819c223-7f76-453a-919d-413861904646".to_string())?;
22///
23///     // Safe access to validated value
24///     println!("Resource ID: {}", id.as_str());
25///     Ok(())
26/// }
27/// ```
28mod address;
29mod composite_validation;
30mod email_address;
31mod extension;
32mod external_id;
33mod factory;
34mod group_member;
35mod meta;
36mod multi_valued;
37mod name;
38mod phone_number;
39mod resource_id;
40mod schema_uri;
41mod user_name;
42mod value_object_trait;
43
44pub use address::Address;
45pub use composite_validation::{
46    CompositeValidatorChain, EmailConsistencyValidator, IdentityConsistencyValidator,
47    NameConsistencyValidator, UniquePrimaryValidator, UserNameUniquenessValidator,
48};
49pub use email_address::EmailAddress;
50pub use extension::{ExtensionAttributeValue, ExtensionCollection};
51pub use external_id::ExternalId;
52pub use factory::{GenericMultiValuedAttribute, ValueObjectFactory};
53pub use group_member::{
54    GroupMember, GroupMembers, MultiValuedAddresses, MultiValuedEmails, MultiValuedPhoneNumbers,
55};
56pub use meta::Meta;
57pub use multi_valued::MultiValuedAttribute;
58pub use name::Name;
59pub use phone_number::PhoneNumber;
60pub use resource_id::ResourceId;
61pub use schema_uri::SchemaUri;
62pub use user_name::UserName;
63pub use value_object_trait::{
64    CompositeValidator, ExtensionAttribute, SchemaConstructible, ValueObject,
65    ValueObjectConstructor, ValueObjectRegistry,
66};
67
68#[cfg(test)]
69mod tests {
70    use super::*;
71
72    #[test]
73    fn test_value_objects_are_immutable() {
74        // Once created, value objects cannot be modified
75        let id = ResourceId::new("test-id".to_string()).unwrap();
76        let id_str = id.as_str();
77
78        // The only way to get a different value is to create a new instance
79        let new_id = ResourceId::new("different-id".to_string()).unwrap();
80        assert_ne!(id_str, new_id.as_str());
81    }
82
83    #[test]
84    fn test_value_objects_enforce_invariants() {
85        // Invalid values cannot be constructed
86        assert!(ResourceId::new("".to_string()).is_err());
87
88        // Valid values can be constructed
89        assert!(ResourceId::new("valid-id".to_string()).is_ok());
90    }
91}