prism3_function/readonly_consumer.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025.
4 * 3-Prism Co. Ltd.
5 *
6 * All rights reserved.
7 *
8 ******************************************************************************/
9//! # ReadonlyConsumer Types
10//!
11//! Provides implementations of readonly consumer interfaces for executing operations that neither modify their own state nor modify input values.
12//!
13//! This module provides a unified `ReadonlyConsumer` trait and three concrete implementations based on different ownership models:
14//!
15//! - **`BoxReadonlyConsumer<T>`**: Box-based single ownership implementation
16//! - **`ArcReadonlyConsumer<T>`**: Arc-based thread-safe shared ownership implementation
17//! - **`RcReadonlyConsumer<T>`**: Rc-based single-threaded shared ownership implementation
18//!
19//! # Design Philosophy
20//!
21//! ReadonlyConsumer uses `Fn(&T)` semantics, neither modifying its own state nor modifying input values.
22//! Suitable for pure observation, logging, notification and other scenarios. Compared to Consumer, ReadonlyConsumer
23//! does not require interior mutability (Mutex/RefCell), making it more efficient and easier to share.
24//!
25//! # Author
26//!
27//! Hu Haixing
28
29use std::fmt;
30use std::rc::Rc;
31use std::sync::Arc;
32
33// ============================================================================
34// 1. ReadonlyConsumer Trait - Unified ReadonlyConsumer Interface
35// ============================================================================
36
37/// ReadonlyConsumer trait - Unified readonly consumer interface
38///
39/// Defines the core behavior of all readonly consumer types. Unlike `Consumer`, `ReadonlyConsumer`
40/// neither modifies its own state nor modifies input values, making it a completely immutable operation.
41///
42/// # Auto-implementation
43///
44/// - All closures implementing `Fn(&T)`
45/// - `BoxReadonlyConsumer<T>`, `ArcReadonlyConsumer<T>`, `RcReadonlyConsumer<T>`
46///
47/// # Features
48///
49/// - **Unified Interface**: All readonly consumer types share the same `accept` method signature
50/// - **Auto-implementation**: Closures automatically implement this trait with zero overhead
51/// - **Type Conversion**: Easy conversion between different ownership models
52/// - **Generic Programming**: Write functions that work with any readonly consumer type
53/// - **No Interior Mutability**: No need for Mutex or RefCell, more efficient
54///
55/// # Examples
56///
57/// ```rust
58/// use prism3_function::{ReadonlyConsumer, BoxReadonlyConsumer};
59///
60/// fn apply_consumer<C: ReadonlyConsumer<i32>>(consumer: &C, value: &i32) {
61/// consumer.accept(value);
62/// }
63///
64/// let box_con = BoxReadonlyConsumer::new(|x: &i32| {
65/// println!("Value: {}", x);
66/// });
67/// apply_consumer(&box_con, &5);
68/// ```
69///
70/// # Author
71///
72/// Hu Haixing
73pub trait ReadonlyConsumer<T> {
74 /// Execute readonly consumption operation
75 ///
76 /// Performs an operation on the given reference. The operation typically reads input values or produces side effects,
77 /// but neither modifies the input value nor the consumer's own state.
78 ///
79 /// # Parameters
80 ///
81 /// * `value` - Reference to the value to consume
82 ///
83 /// # Examples
84 ///
85 /// ```rust
86 /// use prism3_function::{ReadonlyConsumer, BoxReadonlyConsumer};
87 ///
88 /// let consumer = BoxReadonlyConsumer::new(|x: &i32| println!("{}", x));
89 /// consumer.accept(&5);
90 /// ```
91 fn accept(&self, value: &T);
92
93 /// Convert to BoxReadonlyConsumer
94 ///
95 /// **⚠️ Consumes `self`**: The original consumer will be unavailable after calling this method.
96 ///
97 /// # Returns
98 ///
99 /// Returns the wrapped `BoxReadonlyConsumer<T>`
100 fn into_box(self) -> BoxReadonlyConsumer<T>
101 where
102 Self: Sized + 'static,
103 T: 'static;
104
105 /// Convert to RcReadonlyConsumer
106 ///
107 /// **⚠️ Consumes `self`**: The original consumer will be unavailable after calling this method.
108 ///
109 /// # Returns
110 ///
111 /// Returns the wrapped `RcReadonlyConsumer<T>`
112 fn into_rc(self) -> RcReadonlyConsumer<T>
113 where
114 Self: Sized + 'static,
115 T: 'static;
116
117 /// Convert to ArcReadonlyConsumer
118 ///
119 /// **⚠️ Consumes `self`**: The original consumer will be unavailable after calling this method.
120 ///
121 /// # Returns
122 ///
123 /// Returns the wrapped `ArcReadonlyConsumer<T>`
124 fn into_arc(self) -> ArcReadonlyConsumer<T>
125 where
126 Self: Sized + Send + Sync + 'static,
127 T: Send + Sync + 'static;
128
129 /// Convert to closure
130 ///
131 /// **⚠️ Consumes `self`**: The original consumer will be unavailable after calling this method.
132 ///
133 /// Converts a readonly consumer to a closure that can be used directly in places where the standard library requires `Fn`.
134 ///
135 /// # Returns
136 ///
137 /// Returns a closure implementing `Fn(&T)`
138 ///
139 /// # Examples
140 ///
141 /// ```rust
142 /// use prism3_function::{ReadonlyConsumer, BoxReadonlyConsumer};
143 ///
144 /// let consumer = BoxReadonlyConsumer::new(|x: &i32| {
145 /// println!("Value: {}", x);
146 /// });
147 /// let func = consumer.into_fn();
148 /// func(&5);
149 /// ```
150 fn into_fn(self) -> impl Fn(&T)
151 where
152 Self: Sized + 'static,
153 T: 'static;
154}
155
156// ============================================================================
157// 2. BoxReadonlyConsumer - Single Ownership Implementation
158// ============================================================================
159
160/// BoxReadonlyConsumer struct
161///
162/// Readonly consumer implementation based on `Box<dyn Fn(&T)>` for single ownership scenarios.
163///
164/// # Features
165///
166/// - **Single Ownership**: Not cloneable, transfers ownership when used
167/// - **Zero Overhead**: No reference counting or lock overhead
168/// - **Completely Immutable**: Neither modifies itself nor input
169/// - **No Interior Mutability**: No need for Mutex or RefCell
170///
171/// # Use Cases
172///
173/// Choose `BoxReadonlyConsumer` when:
174/// - Readonly consumer is used once or in a linear flow
175/// - No need to share consumer across contexts
176/// - Pure observation operations, such as logging
177///
178/// # Examples
179///
180/// ```rust
181/// use prism3_function::{ReadonlyConsumer, BoxReadonlyConsumer};
182///
183/// let consumer = BoxReadonlyConsumer::new(|x: &i32| {
184/// println!("Observed value: {}", x);
185/// });
186/// consumer.accept(&5);
187/// ```
188///
189/// # Author
190///
191/// Hu Haixing
192pub struct BoxReadonlyConsumer<T> {
193 function: Box<dyn Fn(&T)>,
194 name: Option<String>,
195}
196
197impl<T> BoxReadonlyConsumer<T>
198where
199 T: 'static,
200{
201 /// Create a new BoxReadonlyConsumer
202 ///
203 /// # Type Parameters
204 ///
205 /// * `F` - Closure type
206 ///
207 /// # Parameters
208 ///
209 /// * `f` - Closure to wrap
210 ///
211 /// # Returns
212 ///
213 /// Returns a new `BoxReadonlyConsumer<T>` instance
214 ///
215 /// # Examples
216 ///
217 /// ```rust
218 /// use prism3_function::{ReadonlyConsumer, BoxReadonlyConsumer};
219 ///
220 /// let consumer = BoxReadonlyConsumer::new(|x: &i32| {
221 /// println!("Value: {}", x);
222 /// });
223 /// consumer.accept(&5);
224 /// ```
225 pub fn new<F>(f: F) -> Self
226 where
227 F: Fn(&T) + 'static,
228 {
229 BoxReadonlyConsumer {
230 function: Box::new(f),
231 name: None,
232 }
233 }
234
235 /// Get the consumer's name
236 pub fn name(&self) -> Option<&str> {
237 self.name.as_deref()
238 }
239
240 /// Set the consumer's name
241 pub fn set_name(&mut self, name: impl Into<String>) {
242 self.name = Some(name.into());
243 }
244
245 /// Sequentially chain another readonly consumer
246 ///
247 /// Returns a new consumer that executes the current operation first, then the next operation. Consumes self.
248 ///
249 /// # Type Parameters
250 ///
251 /// * `C` - Type of the next consumer
252 ///
253 /// # Parameters
254 ///
255 /// * `next` - Consumer to execute after the current operation. **Note: This
256 /// parameter is passed by value and will transfer ownership.** If you need
257 /// to preserve the original consumer, clone it first (if it implements
258 /// `Clone`). Can be:
259 /// - A closure: `|x: &T|`
260 /// - A `BoxReadonlyConsumer<T>`
261 /// - An `RcReadonlyConsumer<T>`
262 /// - An `ArcReadonlyConsumer<T>`
263 /// - Any type implementing `ReadonlyConsumer<T>`
264 ///
265 /// # Returns
266 ///
267 /// Returns a new combined `BoxReadonlyConsumer<T>`
268 ///
269 /// # Examples
270 ///
271 /// ## Direct value passing (ownership transfer)
272 ///
273 /// ```rust
274 /// use prism3_function::{ReadonlyConsumer, BoxReadonlyConsumer};
275 ///
276 /// let first = BoxReadonlyConsumer::new(|x: &i32| {
277 /// println!("First: {}", x);
278 /// });
279 /// let second = BoxReadonlyConsumer::new(|x: &i32| {
280 /// println!("Second: {}", x);
281 /// });
282 ///
283 /// // second is moved here
284 /// let chained = first.and_then(second);
285 /// chained.accept(&5);
286 /// // second.accept(&3); // Would not compile - moved
287 /// ```
288 ///
289 /// ## Preserving original with clone
290 ///
291 /// ```rust
292 /// use prism3_function::{ReadonlyConsumer, BoxReadonlyConsumer, RcReadonlyConsumer};
293 ///
294 /// let first = BoxReadonlyConsumer::new(|x: &i32| {
295 /// println!("First: {}", x);
296 /// });
297 /// let second = RcReadonlyConsumer::new(|x: &i32| {
298 /// println!("Second: {}", x);
299 /// });
300 ///
301 /// // Clone to preserve original
302 /// let chained = first.and_then(second.clone());
303 /// chained.accept(&5);
304 ///
305 /// // Original still usable
306 /// second.accept(&3);
307 /// ```
308 pub fn and_then<C>(self, next: C) -> Self
309 where
310 C: ReadonlyConsumer<T> + 'static,
311 {
312 let first = self.function;
313 let second = next;
314 BoxReadonlyConsumer::new(move |t| {
315 first(t);
316 second.accept(t);
317 })
318 }
319
320 /// Create a no-op consumer
321 ///
322 /// # Returns
323 ///
324 /// Returns a no-op consumer
325 pub fn noop() -> Self {
326 BoxReadonlyConsumer::new(|_| {})
327 }
328}
329
330impl<T> ReadonlyConsumer<T> for BoxReadonlyConsumer<T> {
331 fn accept(&self, value: &T) {
332 (self.function)(value)
333 }
334
335 fn into_box(self) -> BoxReadonlyConsumer<T>
336 where
337 T: 'static,
338 {
339 self
340 }
341
342 fn into_rc(self) -> RcReadonlyConsumer<T>
343 where
344 T: 'static,
345 {
346 let func = self.function;
347 RcReadonlyConsumer::new(move |t| func(t))
348 }
349
350 fn into_arc(self) -> ArcReadonlyConsumer<T>
351 where
352 T: Send + Sync + 'static,
353 {
354 panic!("Cannot convert BoxReadonlyConsumer to ArcReadonlyConsumer: inner function may not be Send+Sync")
355 }
356
357 fn into_fn(self) -> impl Fn(&T)
358 where
359 T: 'static,
360 {
361 self.function
362 }
363}
364
365impl<T> fmt::Debug for BoxReadonlyConsumer<T> {
366 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
367 f.debug_struct("BoxReadonlyConsumer")
368 .field("name", &self.name)
369 .field("function", &"<function>")
370 .finish()
371 }
372}
373
374impl<T> fmt::Display for BoxReadonlyConsumer<T> {
375 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
376 match &self.name {
377 Some(name) => write!(f, "BoxReadonlyConsumer({})", name),
378 None => write!(f, "BoxReadonlyConsumer"),
379 }
380 }
381}
382
383// ============================================================================
384// 3. ArcReadonlyConsumer - Thread-safe Shared Ownership Implementation
385// ============================================================================
386
387/// ArcReadonlyConsumer struct
388///
389/// Readonly consumer implementation based on `Arc<dyn Fn(&T) + Send + Sync>`,
390/// for thread-safe shared ownership scenarios. No Mutex needed because operations are readonly.
391///
392/// # Features
393///
394/// - **Shared Ownership**: Cloneable through `Arc`, allows multiple owners
395/// - **Thread Safe**: Implements `Send + Sync`, can be safely used concurrently
396/// - **Lock-free**: No Mutex protection needed because it's readonly
397/// - **Non-consuming API**: `and_then` borrows `&self`, original object remains usable
398///
399/// # Use Cases
400///
401/// Choose `ArcReadonlyConsumer` when:
402/// - Need to share readonly consumer across multiple threads
403/// - Pure observation operations, such as logging, monitoring, notifications
404/// - Need high-concurrency reads with no lock overhead
405///
406/// # Performance Advantages
407///
408/// Compared to `ArcConsumer`, `ArcReadonlyConsumer` has no Mutex lock overhead,
409/// performing better in high-concurrency scenarios.
410///
411/// # Examples
412///
413/// ```rust
414/// use prism3_function::{ReadonlyConsumer, ArcReadonlyConsumer};
415///
416/// let consumer = ArcReadonlyConsumer::new(|x: &i32| {
417/// println!("Observed: {}", x);
418/// });
419/// let clone = consumer.clone();
420///
421/// consumer.accept(&5);
422/// clone.accept(&10);
423/// ```
424///
425/// # Author
426///
427/// Hu Haixing
428pub struct ArcReadonlyConsumer<T> {
429 function: Arc<dyn Fn(&T) + Send + Sync>,
430 name: Option<String>,
431}
432
433impl<T> ArcReadonlyConsumer<T>
434where
435 T: Send + Sync + 'static,
436{
437 /// Create a new ArcReadonlyConsumer
438 ///
439 /// # Type Parameters
440 ///
441 /// * `F` - Closure type
442 ///
443 /// # Parameters
444 ///
445 /// * `f` - Closure to wrap
446 ///
447 /// # Returns
448 ///
449 /// Returns a new `ArcReadonlyConsumer<T>` instance
450 ///
451 /// # Examples
452 ///
453 /// ```rust
454 /// use prism3_function::{ReadonlyConsumer, ArcReadonlyConsumer};
455 ///
456 /// let consumer = ArcReadonlyConsumer::new(|x: &i32| {
457 /// println!("Value: {}", x);
458 /// });
459 /// consumer.accept(&5);
460 /// ```
461 pub fn new<F>(f: F) -> Self
462 where
463 F: Fn(&T) + Send + Sync + 'static,
464 {
465 ArcReadonlyConsumer {
466 function: Arc::new(f),
467 name: None,
468 }
469 }
470
471 /// Get the consumer's name
472 pub fn name(&self) -> Option<&str> {
473 self.name.as_deref()
474 }
475
476 /// Set the consumer's name
477 pub fn set_name(&mut self, name: impl Into<String>) {
478 self.name = Some(name.into());
479 }
480
481 /// Convert to closure (without consuming self)
482 ///
483 /// Creates a new closure that calls the underlying function through Arc.
484 ///
485 /// # Returns
486 ///
487 /// Returns a closure implementing `Fn(&T)`
488 ///
489 /// # Examples
490 ///
491 /// ```rust
492 /// use prism3_function::{ReadonlyConsumer, ArcReadonlyConsumer};
493 ///
494 /// let consumer = ArcReadonlyConsumer::new(|x: &i32| {
495 /// println!("Value: {}", x);
496 /// });
497 ///
498 /// let func = consumer.to_fn();
499 /// func(&5);
500 /// ```
501 pub fn to_fn(&self) -> impl Fn(&T)
502 where
503 T: 'static,
504 {
505 let func = Arc::clone(&self.function);
506 move |t: &T| {
507 func(t);
508 }
509 }
510
511 /// Sequentially chain another ArcReadonlyConsumer
512 ///
513 /// Returns a new consumer that executes the current operation first, then the next operation.
514 /// Borrows &self, does not consume the original consumer.
515 ///
516 /// # Parameters
517 ///
518 /// * `next` - Consumer to execute after the current operation. **Note: This
519 /// parameter is passed by reference, so the original consumer remains
520 /// usable.** Can be:
521 /// - An `ArcReadonlyConsumer<T>` (passed by reference)
522 /// - Any type implementing `ReadonlyConsumer<T> + Send + Sync`
523 ///
524 /// # Returns
525 ///
526 /// Returns a new combined `ArcReadonlyConsumer<T>`
527 ///
528 /// # Examples
529 ///
530 /// ```rust
531 /// use prism3_function::{ReadonlyConsumer, ArcReadonlyConsumer};
532 ///
533 /// let first = ArcReadonlyConsumer::new(|x: &i32| {
534 /// println!("First: {}", x);
535 /// });
536 /// let second = ArcReadonlyConsumer::new(|x: &i32| {
537 /// println!("Second: {}", x);
538 /// });
539 ///
540 /// // second is passed by reference, so it remains usable
541 /// let chained = first.and_then(&second);
542 ///
543 /// // first and second remain usable after chaining
544 /// chained.accept(&5);
545 /// first.accept(&3); // Still usable
546 /// second.accept(&7); // Still usable
547 /// ```
548 pub fn and_then(&self, next: &ArcReadonlyConsumer<T>) -> ArcReadonlyConsumer<T> {
549 let first = Arc::clone(&self.function);
550 let second = Arc::clone(&next.function);
551 ArcReadonlyConsumer {
552 function: Arc::new(move |t: &T| {
553 first(t);
554 second(t);
555 }),
556 name: None,
557 }
558 }
559}
560
561impl<T> ReadonlyConsumer<T> for ArcReadonlyConsumer<T> {
562 fn accept(&self, value: &T) {
563 (self.function)(value)
564 }
565
566 fn into_box(self) -> BoxReadonlyConsumer<T>
567 where
568 T: 'static,
569 {
570 let func = self.function;
571 BoxReadonlyConsumer::new(move |t| func(t))
572 }
573
574 fn into_rc(self) -> RcReadonlyConsumer<T>
575 where
576 T: 'static,
577 {
578 let func = self.function;
579 RcReadonlyConsumer::new(move |t| func(t))
580 }
581
582 fn into_arc(self) -> ArcReadonlyConsumer<T>
583 where
584 T: Send + Sync + 'static,
585 {
586 self
587 }
588
589 fn into_fn(self) -> impl Fn(&T)
590 where
591 T: 'static,
592 {
593 let func = self.function;
594 move |t: &T| {
595 func(t);
596 }
597 }
598}
599
600impl<T> Clone for ArcReadonlyConsumer<T> {
601 /// Clone ArcReadonlyConsumer
602 ///
603 /// Creates a new ArcReadonlyConsumer that shares the underlying function with the original instance.
604 fn clone(&self) -> Self {
605 Self {
606 function: Arc::clone(&self.function),
607 name: self.name.clone(),
608 }
609 }
610}
611
612impl<T> fmt::Debug for ArcReadonlyConsumer<T> {
613 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
614 f.debug_struct("ArcReadonlyConsumer")
615 .field("name", &self.name)
616 .field("function", &"<function>")
617 .finish()
618 }
619}
620
621impl<T> fmt::Display for ArcReadonlyConsumer<T> {
622 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
623 match &self.name {
624 Some(name) => write!(f, "ArcReadonlyConsumer({})", name),
625 None => write!(f, "ArcReadonlyConsumer"),
626 }
627 }
628}
629
630// ============================================================================
631// 4. RcReadonlyConsumer - Single-threaded Shared Ownership Implementation
632// ============================================================================
633
634/// RcReadonlyConsumer struct
635///
636/// Readonly consumer implementation based on `Rc<dyn Fn(&T)>` for single-threaded shared ownership scenarios.
637/// No RefCell needed because operations are readonly.
638///
639/// # Features
640///
641/// - **Shared Ownership**: Cloneable through `Rc`, allows multiple owners
642/// - **Single-threaded**: Not thread-safe, cannot be sent across threads
643/// - **No Interior Mutability Overhead**: No RefCell needed because it's readonly
644/// - **Non-consuming API**: `and_then` borrows `&self`, original object remains usable
645///
646/// # Use Cases
647///
648/// Choose `RcReadonlyConsumer` when:
649/// - Need to share readonly consumer within a single thread
650/// - Pure observation operations, performance critical
651/// - Event handling in single-threaded UI frameworks
652///
653/// # Performance Advantages
654///
655/// `RcReadonlyConsumer` has neither Arc's atomic operation overhead nor RefCell's
656/// runtime borrow checking overhead, making it the most performant of the three readonly consumers.
657///
658/// # Examples
659///
660/// ```rust
661/// use prism3_function::{ReadonlyConsumer, RcReadonlyConsumer};
662///
663/// let consumer = RcReadonlyConsumer::new(|x: &i32| {
664/// println!("Observed: {}", x);
665/// });
666/// let clone = consumer.clone();
667///
668/// consumer.accept(&5);
669/// clone.accept(&10);
670/// ```
671///
672/// # Author
673///
674/// Hu Haixing
675pub struct RcReadonlyConsumer<T> {
676 function: Rc<dyn Fn(&T)>,
677 name: Option<String>,
678}
679
680impl<T> RcReadonlyConsumer<T>
681where
682 T: 'static,
683{
684 /// Create a new RcReadonlyConsumer
685 ///
686 /// # Type Parameters
687 ///
688 /// * `F` - Closure type
689 ///
690 /// # Parameters
691 ///
692 /// * `f` - Closure to wrap
693 ///
694 /// # Returns
695 ///
696 /// Returns a new `RcReadonlyConsumer<T>` instance
697 ///
698 /// # Examples
699 ///
700 /// ```rust
701 /// use prism3_function::{ReadonlyConsumer, RcReadonlyConsumer};
702 ///
703 /// let consumer = RcReadonlyConsumer::new(|x: &i32| {
704 /// println!("Value: {}", x);
705 /// });
706 /// consumer.accept(&5);
707 /// ```
708 pub fn new<F>(f: F) -> Self
709 where
710 F: Fn(&T) + 'static,
711 {
712 RcReadonlyConsumer {
713 function: Rc::new(f),
714 name: None,
715 }
716 }
717
718 /// Get the consumer's name
719 pub fn name(&self) -> Option<&str> {
720 self.name.as_deref()
721 }
722
723 /// Set the consumer's name
724 pub fn set_name(&mut self, name: impl Into<String>) {
725 self.name = Some(name.into());
726 }
727
728 /// Convert to closure (without consuming self)
729 ///
730 /// Creates a new closure that calls the underlying function through Rc.
731 ///
732 /// # Returns
733 ///
734 /// Returns a closure implementing `Fn(&T)`
735 ///
736 /// # Examples
737 ///
738 /// ```rust
739 /// use prism3_function::{ReadonlyConsumer, RcReadonlyConsumer};
740 ///
741 /// let consumer = RcReadonlyConsumer::new(|x: &i32| {
742 /// println!("Value: {}", x);
743 /// });
744 ///
745 /// let func = consumer.to_fn();
746 /// func(&5);
747 /// ```
748 pub fn to_fn(&self) -> impl Fn(&T)
749 where
750 T: 'static,
751 {
752 let func = Rc::clone(&self.function);
753 move |t: &T| {
754 func(t);
755 }
756 }
757
758 /// Sequentially chain another RcReadonlyConsumer
759 ///
760 /// Returns a new consumer that executes the current operation first, then the next operation.
761 /// Borrows &self, does not consume the original consumer.
762 ///
763 /// # Parameters
764 ///
765 /// * `next` - Consumer to execute after the current operation. **Note: This
766 /// parameter is passed by reference, so the original consumer remains
767 /// usable.** Can be:
768 /// - An `RcReadonlyConsumer<T>` (passed by reference)
769 /// - Any type implementing `ReadonlyConsumer<T>`
770 ///
771 /// # Returns
772 ///
773 /// Returns a new combined `RcReadonlyConsumer<T>`
774 ///
775 /// # Examples
776 ///
777 /// ```rust
778 /// use prism3_function::{ReadonlyConsumer, RcReadonlyConsumer};
779 ///
780 /// let first = RcReadonlyConsumer::new(|x: &i32| {
781 /// println!("First: {}", x);
782 /// });
783 /// let second = RcReadonlyConsumer::new(|x: &i32| {
784 /// println!("Second: {}", x);
785 /// });
786 ///
787 /// // second is passed by reference, so it remains usable
788 /// let chained = first.and_then(&second);
789 ///
790 /// // first and second remain usable after chaining
791 /// chained.accept(&5);
792 /// first.accept(&3); // Still usable
793 /// second.accept(&7); // Still usable
794 /// ```
795 pub fn and_then(&self, next: &RcReadonlyConsumer<T>) -> RcReadonlyConsumer<T> {
796 let first = Rc::clone(&self.function);
797 let second = Rc::clone(&next.function);
798 RcReadonlyConsumer {
799 function: Rc::new(move |t: &T| {
800 first(t);
801 second(t);
802 }),
803 name: None,
804 }
805 }
806}
807
808impl<T> ReadonlyConsumer<T> for RcReadonlyConsumer<T> {
809 fn accept(&self, value: &T) {
810 (self.function)(value)
811 }
812
813 fn into_box(self) -> BoxReadonlyConsumer<T>
814 where
815 T: 'static,
816 {
817 let func = self.function;
818 BoxReadonlyConsumer::new(move |t| func(t))
819 }
820
821 fn into_rc(self) -> RcReadonlyConsumer<T>
822 where
823 T: 'static,
824 {
825 self
826 }
827
828 fn into_arc(self) -> ArcReadonlyConsumer<T>
829 where
830 T: Send + Sync + 'static,
831 {
832 panic!("Cannot convert RcReadonlyConsumer to ArcReadonlyConsumer (not Send+Sync)")
833 }
834
835 fn into_fn(self) -> impl Fn(&T)
836 where
837 T: 'static,
838 {
839 let func = self.function;
840 move |t: &T| {
841 func(t);
842 }
843 }
844}
845
846impl<T> Clone for RcReadonlyConsumer<T> {
847 /// Clone RcReadonlyConsumer
848 ///
849 /// Creates a new RcReadonlyConsumer that shares the underlying function with the original instance.
850 fn clone(&self) -> Self {
851 Self {
852 function: Rc::clone(&self.function),
853 name: self.name.clone(),
854 }
855 }
856}
857
858impl<T> fmt::Debug for RcReadonlyConsumer<T> {
859 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
860 f.debug_struct("RcReadonlyConsumer")
861 .field("name", &self.name)
862 .field("function", &"<function>")
863 .finish()
864 }
865}
866
867impl<T> fmt::Display for RcReadonlyConsumer<T> {
868 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
869 match &self.name {
870 Some(name) => write!(f, "RcReadonlyConsumer({})", name),
871 None => write!(f, "RcReadonlyConsumer"),
872 }
873 }
874}
875
876// ============================================================================
877// 5. Implement ReadonlyConsumer trait for closures
878// ============================================================================
879
880/// Implement ReadonlyConsumer for all Fn(&T)
881impl<T, F> ReadonlyConsumer<T> for F
882where
883 F: Fn(&T),
884{
885 fn accept(&self, value: &T) {
886 self(value)
887 }
888
889 fn into_box(self) -> BoxReadonlyConsumer<T>
890 where
891 Self: Sized + 'static,
892 T: 'static,
893 {
894 BoxReadonlyConsumer::new(self)
895 }
896
897 fn into_rc(self) -> RcReadonlyConsumer<T>
898 where
899 Self: Sized + 'static,
900 T: 'static,
901 {
902 RcReadonlyConsumer::new(self)
903 }
904
905 fn into_arc(self) -> ArcReadonlyConsumer<T>
906 where
907 Self: Sized + Send + Sync + 'static,
908 T: Send + Sync + 'static,
909 {
910 ArcReadonlyConsumer::new(self)
911 }
912
913 fn into_fn(self) -> impl Fn(&T)
914 where
915 Self: Sized + 'static,
916 T: 'static,
917 {
918 self
919 }
920}
921
922// ============================================================================
923// 6. Provide extension methods for closures
924// ============================================================================
925
926/// Extension trait providing readonly consumer composition methods for closures
927///
928/// Provides `and_then` and other composition methods for all closures implementing `Fn(&T)`,
929/// allowing closures to directly chain methods without explicit wrapper types.
930///
931/// # Features
932///
933/// - **Natural Syntax**: Chain operations directly on closures
934/// - **Returns BoxReadonlyConsumer**: Combined results can continue chaining
935/// - **Zero Cost**: No overhead when composing closures
936/// - **Auto-implementation**: All `Fn(&T)` closures automatically get these methods
937///
938/// # Examples
939///
940/// ```rust
941/// use prism3_function::{ReadonlyConsumer, FnReadonlyConsumerOps};
942///
943/// let chained = (|x: &i32| {
944/// println!("First: {}", x);
945/// }).and_then(|x: &i32| {
946/// println!("Second: {}", x);
947/// });
948/// chained.accept(&5);
949/// ```
950///
951/// # Author
952///
953/// Hu Haixing
954pub trait FnReadonlyConsumerOps<T>: Fn(&T) + Sized {
955 /// Sequentially chain another readonly consumer
956 ///
957 /// Returns a new consumer that executes the current operation first, then the next operation.
958 /// Consumes the current closure and returns `BoxReadonlyConsumer<T>`.
959 ///
960 /// # Type Parameters
961 ///
962 /// * `C` - Type of the next consumer
963 ///
964 /// # Parameters
965 ///
966 /// * `next` - Consumer to execute after the current operation
967 ///
968 /// # Returns
969 ///
970 /// Returns a combined `BoxReadonlyConsumer<T>`
971 ///
972 /// # Examples
973 ///
974 /// ```rust
975 /// use prism3_function::{ReadonlyConsumer, FnReadonlyConsumerOps};
976 ///
977 /// let chained = (|x: &i32| {
978 /// println!("First: {}", x);
979 /// }).and_then(|x: &i32| {
980 /// println!("Second: {}", x);
981 /// }).and_then(|x: &i32| println!("Third: {}", x));
982 ///
983 /// chained.accept(&5);
984 /// ```
985 fn and_then<C>(self, next: C) -> BoxReadonlyConsumer<T>
986 where
987 Self: 'static,
988 C: ReadonlyConsumer<T> + 'static,
989 T: 'static,
990 {
991 let first = self;
992 let second = next;
993 BoxReadonlyConsumer::new(move |t| {
994 first(t);
995 second.accept(t);
996 })
997 }
998}
999
1000/// Implement FnReadonlyConsumerOps for all closure types
1001impl<T, F> FnReadonlyConsumerOps<T> for F where F: Fn(&T) {}