rust_prelude_plus/
traits.rs

1//! Core traits for keypath operations
2//!
3//! This module provides extension traits that enable keypath operations on various types.
4//! It includes iterator extensions, collection extensions, and memory-efficient operations
5//! using `Rc` and `Arc`.
6//!
7//! ## Examples
8//!
9//! ### Basic KeyPath Operations
10//!
11//! ```rust
12//! use rust_prelude_plus::prelude::*;
13//! use key_paths_derive::Keypath;
14//! use std::rc::Rc;
15//!
16//! #[derive(Keypath, Debug, Clone)]
17//! struct Person {
18//!     name: String,
19//!     age: u32,
20//! }
21//!
22//! let person = Rc::new(Person { name: "Alice".to_string(), age: 30 });
23//! let name = person.get_at_keypath(Person::name()).unwrap();
24//! assert_eq!(name, "Alice");
25//! ```
26//!
27//! ### Iterator Extensions
28//!
29//! ```rust
30//! use rust_prelude_plus::prelude::*;
31//! use key_paths_derive::Keypath;
32//! use std::rc::Rc;
33//!
34//! #[derive(Keypath, Debug, Clone)]
35//! struct Product {
36//!     name: String,
37//!     price: f64,
38//! }
39//!
40//! let products = vec![
41//!     Rc::new(Product { name: "Laptop".to_string(), price: 999.99 }),
42//!     Rc::new(Product { name: "Book".to_string(), price: 19.99 }),
43//! ];
44//!
45//! // Lazy evaluation with iterator extensions
46//! let expensive_products: Vec<Rc<Product>> = products
47//!     .iter()
48//!     .filter_by_keypath(Product::price(), |&price| price > 100.0)
49//!     .map(|item| item.clone())
50//!     .collect();
51//! ```
52
53use key_paths_core::KeyPaths;
54use crate::error::{KeyPathResult, KeyPathError};
55
56/// Trait for types that can be operated on with keypaths
57pub trait KeyPathsOperable: Sized {
58    /// Get a value at a keypath
59    fn get_at_keypath<'a, V>(&'a self, keypath: &'a KeyPaths<Self, V>) -> KeyPathResult<&'a V> {
60        keypath.get(self).ok_or_else(|| KeyPathError::InvalidAccess { 
61            message: "KeyPath access failed".to_string() 
62        })
63    }
64    
65    /// Set a value at a keypath (if the keypath supports mutation)
66    fn set_at_keypath<V>(&mut self, _keypath: KeyPaths<Self, V>, _value: V) -> KeyPathResult<()> {
67        // Note: This is a simplified implementation
68        // In practice, you'd need to handle the specific keypath type
69        Err(KeyPathError::InvalidAccess { 
70            message: "KeyPath mutation not supported in this context".to_string() 
71        })
72    }
73}
74
75/// Trait for iterators that support keypath operations
76pub trait KeyPathsIterator: Iterator {
77    /// Map over a keypath in the iterator
78    fn map_keypath<V, F, R>(self, keypath: KeyPaths<Self::Item, V>, f: F) -> Vec<R>
79    where
80        Self: Sized,
81        Self::Item: KeyPathsOperable,
82        F: Fn(&V) -> R,
83    {
84        self.map(|item| {
85            let value = item.get_at_keypath(&keypath).unwrap_or_else(|_| {
86                panic!("KeyPath access failed in map_keypath")
87            });
88            f(value)
89        }).collect()
90    }
91    
92    /// Filter by a keypath predicate
93    fn filter_by_keypath<V, F>(self, keypath: KeyPaths<Self::Item, V>, predicate: F) -> Vec<Self::Item>
94    where
95        Self: Sized,
96        Self::Item: KeyPathsOperable,
97        F: Fn(&V) -> bool,
98    {
99        self.filter(|item| {
100            let value = item.get_at_keypath(&keypath).unwrap_or_else(|_| {
101                panic!("KeyPath access failed in filter_by_keypath")
102            });
103            predicate(value)
104        }).collect()
105    }
106    
107    /// Find an element by keypath predicate
108    fn find_by_keypath<V, F>(self, keypath: KeyPaths<Self::Item, V>, predicate: F) -> KeyPathResult<Option<Self::Item>>
109    where
110        Self: Sized,
111        Self::Item: KeyPathsOperable,
112        F: Fn(&V) -> bool,
113    {
114        for item in self {
115            if let Ok(value) = item.get_at_keypath(&keypath) {
116                if predicate(value) {
117                    return Ok(Some(item));
118                }
119            }
120        }
121        Ok(None)
122    }
123    
124    /// Fold over a keypath
125    fn fold_keypath<V, F, B>(self, keypath: KeyPaths<Self::Item, V>, init: B, mut f: F) -> KeyPathResult<B>
126    where
127        Self: Sized,
128        Self::Item: KeyPathsOperable,
129        F: FnMut(B, &V) -> B,
130    {
131        let mut acc = init;
132        for item in self {
133            if let Ok(value) = item.get_at_keypath(&keypath) {
134                acc = f(acc, value);
135            }
136        }
137        Ok(acc)
138    }
139    
140    /// Collect values from a keypath
141    fn collect_keypath<V>(self, keypath: KeyPaths<Self::Item, V>) -> KeyPathResult<Vec<V>>
142    where
143        Self: Sized,
144        Self::Item: KeyPathsOperable,
145        V: Clone,
146    {
147        let mut result = Vec::new();
148        for item in self {
149            if let Ok(value) = item.get_at_keypath(&keypath) {
150                result.push(value.clone());
151            }
152        }
153        Ok(result)
154    }
155}
156
157/// Trait for collections that support keypath operations
158pub trait KeyPathsCollection<T> {
159    /// Group elements by keypath values
160    fn group_by_keypath<V, F>(&self, keypath: KeyPaths<T, V>, f: F) -> KeyPathResult<std::collections::HashMap<V, Vec<T>>>
161    where
162        V: std::hash::Hash + Eq + Clone,
163        T: Clone + KeyPathsOperable,
164        F: Fn(&V) -> V;
165    
166    /// Partition elements by keypath predicate
167    fn partition_by_keypath<V, F>(&self, keypath: KeyPaths<T, V>, predicate: F) -> KeyPathResult<(Vec<T>, Vec<T>)>
168    where
169        T: Clone + KeyPathsOperable,
170        F: Fn(&V) -> bool;
171    
172    /// Sort elements by keypath values
173    fn sort_by_keypath<V, F>(&mut self, keypath: KeyPaths<T, V>, compare: F) -> KeyPathResult<()>
174    where
175        T: KeyPathsOperable,
176        F: Fn(&V, &V) -> std::cmp::Ordering;
177}
178
179// Implement KeyPathsOperable for all types
180impl<T> KeyPathsOperable for T {}
181
182// Implement KeyPathsIterator for all iterators
183impl<I: Iterator> KeyPathsIterator for I {}
184
185// Implement KeyPathsCollection for Vec
186impl<T> KeyPathsCollection<T> for Vec<T> {
187    fn group_by_keypath<V, F>(&self, keypath: KeyPaths<T, V>, f: F) -> KeyPathResult<std::collections::HashMap<V, Vec<T>>>
188    where
189        V: std::hash::Hash + Eq + Clone,
190        T: Clone + KeyPathsOperable,
191        F: Fn(&V) -> V,
192    {
193        let mut groups = std::collections::HashMap::new();
194        for item in self {
195            if let Ok(value) = item.get_at_keypath(&keypath) {
196                let key = f(value);
197                groups.entry(key).or_insert_with(Vec::new).push(item.clone());
198            }
199        }
200        Ok(groups)
201    }
202    
203    fn partition_by_keypath<V, F>(&self, keypath: KeyPaths<T, V>, predicate: F) -> KeyPathResult<(Vec<T>, Vec<T>)>
204    where
205        T: Clone + KeyPathsOperable,
206        F: Fn(&V) -> bool,
207    {
208        let mut left = Vec::new();
209        let mut right = Vec::new();
210        
211        for item in self {
212            if let Ok(value) = item.get_at_keypath(&keypath) {
213                if predicate(value) {
214                    left.push(item.clone());
215                } else {
216                    right.push(item.clone());
217                }
218            }
219        }
220        
221        Ok((left, right))
222    }
223    
224    fn sort_by_keypath<V, F>(&mut self, keypath: KeyPaths<T, V>, compare: F) -> KeyPathResult<()>
225    where
226        T: KeyPathsOperable,
227        F: Fn(&V, &V) -> std::cmp::Ordering,
228    {
229        self.sort_by(|a, b| {
230            let a_val = keypath.get(a).unwrap_or_else(|| {
231                panic!("KeyPath access failed in sort")
232            });
233            let b_val = keypath.get(b).unwrap_or_else(|| {
234                panic!("KeyPath access failed in sort")
235            });
236            compare(a_val, b_val)
237        });
238        Ok(())
239    }
240}