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