miniextendr_api/adapter_traits.rs
1//! Built-in adapter traits for common Rust standard library traits.
2//!
3//! These traits provide blanket implementations that allow any Rust type
4//! implementing standard traits to be exposed to R without boilerplate.
5//!
6//! # Example
7//!
8//! ```rust,ignore
9//! use miniextendr_api::prelude::*;
10//! use miniextendr_api::adapter_traits::RDebug;
11//!
12//! #[derive(Debug, ExternalPtr)]
13//! struct MyData {
14//! values: Vec<i32>,
15//! }
16//!
17//! // RDebug is automatically available for any Debug type
18//! #[miniextendr]
19//! impl RDebug for MyData {}
20//! ```
21//!
22//! In R:
23//! ```r
24//! data <- MyData$new(...)
25//! data$debug_str() # "MyData { values: [1, 2, 3] }"
26//! data$debug_str_pretty() # Pretty-printed with newlines
27//! ```
28
29use crate::miniextendr;
30use std::collections::hash_map::DefaultHasher;
31use std::fmt::{Debug, Display};
32use std::hash::{Hash, Hasher};
33use std::str::FromStr;
34
35/// Adapter trait for [`std::fmt::Debug`].
36///
37/// Provides string representations for debugging and inspection in R.
38/// Automatically implemented for any type that implements `Debug`.
39///
40/// # Methods
41///
42/// - `debug_str()` - Returns compact debug string (`:?` format)
43/// - `debug_str_pretty()` - Returns pretty-printed debug string (`:#?` format)
44///
45/// # Example
46///
47/// ```rust,ignore
48/// #[derive(Debug, ExternalPtr)]
49/// struct Config { name: String, value: i32 }
50///
51/// #[miniextendr]
52/// impl RDebug for Config {}
53/// ```
54#[miniextendr]
55pub trait RDebug {
56 /// Get a compact debug string representation.
57 fn debug_str(&self) -> String;
58
59 /// Get a pretty-printed debug string with indentation.
60 fn debug_str_pretty(&self) -> String;
61}
62
63impl<T: Debug> RDebug for T {
64 fn debug_str(&self) -> String {
65 format!("{:?}", self)
66 }
67
68 fn debug_str_pretty(&self) -> String {
69 format!("{:#?}", self)
70 }
71}
72
73/// Adapter trait for [`std::fmt::Display`].
74///
75/// Provides user-friendly string conversion for R.
76/// Automatically implemented for any type that implements `Display`.
77///
78/// # Methods
79///
80/// - `as_r_string()` - Returns the Display representation
81///
82/// # Example
83///
84/// ```rust,ignore
85/// struct Version(u32, u32, u32);
86///
87/// impl Display for Version {
88/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
89/// write!(f, "{}.{}.{}", self.0, self.1, self.2)
90/// }
91/// }
92///
93/// #[miniextendr]
94/// impl RDisplay for Version {}
95/// ```
96#[miniextendr]
97pub trait RDisplay {
98 /// Convert to a user-friendly string.
99 fn as_r_string(&self) -> String;
100}
101
102impl<T: Display> RDisplay for T {
103 fn as_r_string(&self) -> String {
104 self.to_string()
105 }
106}
107
108/// Adapter trait for [`std::hash::Hash`].
109///
110/// Provides hashing for deduplication and environment keys in R.
111/// Automatically implemented for any type that implements `Hash`.
112///
113/// # Methods
114///
115/// - `hash()` - Returns a 64-bit hash as i64
116///
117/// # Note
118///
119/// Hash values are deterministic within a single R session but may vary
120/// between sessions due to Rust's hasher implementation.
121///
122/// # Example
123///
124/// ```rust,ignore
125/// #[derive(Hash, ExternalPtr)]
126/// struct Record { id: String, value: i64 }
127///
128/// #[miniextendr]
129/// impl RHash for Record {}
130/// ```
131#[miniextendr]
132pub trait RHash {
133 /// Compute a hash of this value.
134 fn hash(&self) -> i64;
135}
136
137impl<T: Hash> RHash for T {
138 fn hash(&self) -> i64 {
139 let mut hasher = DefaultHasher::new();
140 self.hash(&mut hasher);
141 hasher.finish() as i64
142 }
143}
144
145/// Adapter trait for [`std::cmp::Ord`].
146///
147/// Provides total ordering comparison for R sorting operations.
148/// Automatically implemented for any type that implements `Ord`.
149///
150/// # Methods
151///
152/// - `cmp(&self, other: &Self)` - Returns -1, 0, or 1
153///
154/// # Example
155///
156/// ```rust,ignore
157/// #[derive(Ord, PartialOrd, Eq, PartialEq, ExternalPtr)]
158/// struct Priority(u32);
159///
160/// #[miniextendr]
161/// impl ROrd for Priority {}
162/// ```
163#[miniextendr]
164pub trait ROrd {
165 /// Compare with another value.
166 ///
167 /// Returns:
168 /// - `-1` if `self < other`
169 /// - `0` if `self == other`
170 /// - `1` if `self > other`
171 fn cmp(&self, other: &Self) -> i32;
172}
173
174impl<T: Ord> ROrd for T {
175 fn cmp(&self, other: &Self) -> i32 {
176 match self.cmp(other) {
177 std::cmp::Ordering::Less => -1,
178 std::cmp::Ordering::Equal => 0,
179 std::cmp::Ordering::Greater => 1,
180 }
181 }
182}
183
184/// Adapter trait for [`std::cmp::PartialOrd`].
185///
186/// Provides partial ordering comparison for R, handling incomparable values.
187/// Automatically implemented for any type that implements `PartialOrd`.
188///
189/// # Methods
190///
191/// - `partial_cmp(&self, other: &Self)` - Returns Some(-1/0/1) or None
192///
193/// # Example
194///
195/// ```rust,ignore
196/// // f64 has partial ordering (NaN is not comparable)
197/// #[derive(PartialOrd, PartialEq, ExternalPtr)]
198/// struct MyFloat(f64);
199///
200/// #[miniextendr]
201/// impl RPartialOrd for MyFloat {}
202/// ```
203#[miniextendr]
204pub trait RPartialOrd {
205 /// Compare with another value, returning None if incomparable.
206 ///
207 /// Returns:
208 /// - `Some(-1)` if `self < other`
209 /// - `Some(0)` if `self == other`
210 /// - `Some(1)` if `self > other`
211 /// - `None` if values are incomparable (maps to NA in R)
212 fn partial_cmp(&self, other: &Self) -> Option<i32>;
213}
214
215impl<T: PartialOrd> RPartialOrd for T {
216 fn partial_cmp(&self, other: &Self) -> Option<i32> {
217 self.partial_cmp(other).map(|ord| match ord {
218 std::cmp::Ordering::Less => -1,
219 std::cmp::Ordering::Equal => 0,
220 std::cmp::Ordering::Greater => 1,
221 })
222 }
223}
224
225/// Adapter trait for [`std::error::Error`].
226///
227/// Provides error message extraction and error chain walking for R.
228/// Automatically implemented for any type that implements `Error`.
229///
230/// # Methods
231///
232/// - `error_message()` - Returns the error's display message
233/// - `error_chain()` - Returns all messages in the error chain
234///
235/// # Example
236///
237/// ```rust,ignore
238/// use std::error::Error;
239/// use std::fmt;
240///
241/// #[derive(Debug)]
242/// struct MyError { msg: String, source: Option<Box<dyn Error + Send + Sync>> }
243///
244/// impl fmt::Display for MyError {
245/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
246/// write!(f, "{}", self.msg)
247/// }
248/// }
249///
250/// impl Error for MyError {
251/// fn source(&self) -> Option<&(dyn Error + 'static)> {
252/// self.source.as_ref().map(|e| e.as_ref() as _)
253/// }
254/// }
255///
256/// // Wrap in ExternalPtr for R access
257/// #[derive(ExternalPtr)]
258/// struct MyErrorWrapper(MyError);
259///
260/// #[miniextendr]
261/// impl RError for MyErrorWrapper {}
262/// ```
263#[miniextendr]
264pub trait RError {
265 /// Get the error message (Display representation).
266 fn error_message(&self) -> String;
267
268 /// Get all error messages in the chain, from outermost to innermost.
269 fn error_chain(&self) -> Vec<String>;
270
271 /// Get the number of errors in the chain.
272 fn error_chain_length(&self) -> i32;
273}
274
275impl<T: std::error::Error> RError for T {
276 fn error_message(&self) -> String {
277 self.to_string()
278 }
279
280 fn error_chain(&self) -> Vec<String> {
281 let mut chain = vec![self.to_string()];
282 let mut current: &dyn std::error::Error = self;
283 while let Some(source) = current.source() {
284 chain.push(source.to_string());
285 current = source;
286 }
287 chain
288 }
289
290 fn error_chain_length(&self) -> i32 {
291 let mut count = 1i32;
292 let mut current: &dyn std::error::Error = self;
293 while let Some(source) = current.source() {
294 count += 1;
295 current = source;
296 }
297 count
298 }
299}
300
301/// Adapter trait for [`std::str::FromStr`].
302///
303/// Provides string parsing for R, allowing R strings to be parsed into Rust types.
304/// Automatically implemented for any type that implements `FromStr`.
305///
306/// # Methods
307///
308/// - `from_str(s: &str)` - Parse a string into this type, returning None on failure
309///
310/// # Example
311///
312/// ```rust,ignore
313/// use std::net::IpAddr;
314///
315/// // IpAddr implements FromStr
316/// #[derive(ExternalPtr)]
317/// struct IpAddress(IpAddr);
318///
319/// #[miniextendr]
320/// impl RFromStr for IpAddress {}
321/// ```
322///
323/// In R:
324/// ```r
325/// ip <- IpAddress$from_str("192.168.1.1")
326/// ```
327#[miniextendr]
328pub trait RFromStr: Sized {
329 /// Parse a string into this type.
330 ///
331 /// Returns `Some(value)` on success, `None` on parse failure.
332 /// The None case maps to NULL in R.
333 fn from_str(s: &str) -> Option<Self>;
334}
335
336impl<T: FromStr> RFromStr for T {
337 fn from_str(s: &str) -> Option<Self> {
338 s.parse().ok()
339 }
340}
341
342/// Adapter trait for [`std::clone::Clone`].
343///
344/// Provides explicit deep copying for R. This is useful when R users need
345/// to create independent copies of Rust objects (which normally use reference
346/// semantics via `ExternalPtr`).
347///
348/// # Methods
349///
350/// - `clone()` - Create a deep copy of this value
351///
352/// # Example
353///
354/// ```rust,ignore
355/// #[derive(Clone, ExternalPtr)]
356/// struct Buffer { data: Vec<u8> }
357///
358/// #[miniextendr]
359/// impl RClone for Buffer {}
360/// ```
361///
362/// In R:
363/// ```r
364/// buf1 <- Buffer$new(...)
365/// buf2 <- buf1$clone() # Independent copy
366/// ```
367#[miniextendr]
368pub trait RClone {
369 /// Create a deep copy of this value.
370 fn clone(&self) -> Self;
371}
372
373impl<T: Clone> RClone for T {
374 fn clone(&self) -> Self {
375 self.clone()
376 }
377}
378
379/// Adapter trait for [`std::default::Default`].
380///
381/// Provides default value construction for R. This allows R users to create
382/// instances with default values without needing to specify all parameters.
383///
384/// # Methods
385///
386/// - `default()` - Create a new instance with default values
387///
388/// # Example
389///
390/// ```rust,ignore
391/// #[derive(Default, ExternalPtr)]
392/// struct Config {
393/// timeout: u32, // defaults to 0
394/// retries: u32, // defaults to 0
395/// verbose: bool, // defaults to false
396/// }
397///
398/// #[miniextendr]
399/// impl RDefault for Config {}
400/// ```
401///
402/// In R:
403/// ```r
404/// config <- Config$default() # All fields have default values
405/// ```
406#[miniextendr]
407pub trait RDefault {
408 /// Create a new instance with default values.
409 fn default() -> Self;
410}
411
412impl<T: Default> RDefault for T {
413 fn default() -> Self {
414 Self::default()
415 }
416}
417
418/// Adapter trait for [`std::marker::Copy`].
419///
420/// Indicates that a type can be cheaply copied (bitwise copy, no heap allocation).
421/// This is useful for R users to know that copying is O(1) and doesn't involve
422/// deep cloning of heap data.
423///
424/// # Methods
425///
426/// - `copy()` - Create a bitwise copy of this value
427/// - `is_copy()` - Returns true (useful for runtime type checking in R)
428///
429/// # Difference from RClone
430///
431/// Both `RCopy` and `RClone` create copies, but:
432/// - `RCopy`: Only for types where copying is cheap (stack-only, no heap)
433/// - `RClone`: For any clonable type (may involve heap allocation)
434///
435/// If a type implements both, prefer `copy()` when you know copies are frequent.
436///
437/// # Example
438///
439/// ```rust,ignore
440/// #[derive(Copy, Clone, ExternalPtr)]
441/// struct Point { x: f64, y: f64 }
442///
443/// #[miniextendr]
444/// impl RCopy for Point {}
445/// ```
446///
447/// In R:
448/// ```r
449/// p1 <- Point$new(1.0, 2.0)
450/// p2 <- p1$copy() # Cheap bitwise copy
451/// p1$is_copy() # TRUE
452/// ```
453#[miniextendr]
454pub trait RCopy {
455 /// Create a bitwise copy of this value.
456 ///
457 /// For Copy types, this is always cheap (O(1), no heap allocation).
458 fn copy(&self) -> Self;
459
460 /// Check if this type implements Copy.
461 ///
462 /// Always returns true for types implementing this trait.
463 /// Useful for runtime type checking in R.
464 fn is_copy(&self) -> bool;
465}
466
467impl<T: Copy> RCopy for T {
468 fn copy(&self) -> Self {
469 *self
470 }
471
472 fn is_copy(&self) -> bool {
473 true
474 }
475}
476
477/// Adapter trait for [`std::iter::Iterator`].
478///
479/// Provides iterator operations for R, allowing Rust iterators to be consumed
480/// element-by-element from R code. Since iterators are stateful, the wrapper
481/// type should use interior mutability (e.g., `RefCell`).
482///
483/// # Methods
484///
485/// - `next()` - Get the next element, or None if exhausted
486/// - `size_hint()` - Get estimated remaining elements as `c(lower, upper)`
487/// - `count()` - Consume and count remaining elements
488/// - `collect_n(n)` - Collect up to n elements into a vector
489/// - `skip(n)` - Skip n elements
490/// - `nth(n)` - Get the nth element (0-indexed)
491///
492/// # Example
493///
494/// ```rust,ignore
495/// use std::cell::RefCell;
496///
497/// #[derive(ExternalPtr)]
498/// struct MyIter(RefCell<std::vec::IntoIter<i32>>);
499///
500/// impl MyIter {
501/// fn new(data: Vec<i32>) -> Self {
502/// Self(RefCell::new(data.into_iter()))
503/// }
504/// }
505///
506/// impl RIterator for MyIter {
507/// type Item = i32;
508///
509/// fn next(&self) -> Option<Self::Item> {
510/// self.0.borrow_mut().next()
511/// }
512///
513/// fn size_hint(&self) -> (i64, Option<i64>) {
514/// let (lo, hi) = self.0.borrow().size_hint();
515/// (lo as i64, hi.map(|h| h as i64))
516/// }
517/// }
518///
519/// #[miniextendr]
520/// impl RIterator for MyIter {}
521/// ```
522///
523/// In R (note: `next` is a reserved word, so expose as `next_item` or similar):
524/// ```r
525/// it <- MyIter$new(c(1L, 2L, 3L))
526/// it$next_item() # 1L
527/// it$next_item() # 2L
528/// it$size_hint() # c(1, 1) - one element remaining
529/// it$next_item() # 3L
530/// it$next_item() # NULL (exhausted)
531/// ```
532///
533/// # Design Note
534///
535/// Unlike other adapter traits, `RIterator` does NOT have a blanket impl
536/// because iterators require `&mut self` for `next()`, but R's ExternalPtr
537/// pattern typically provides `&self`. Users must implement this trait
538/// manually using interior mutability (RefCell, Mutex, etc.).
539#[miniextendr]
540pub trait RIterator {
541 /// The type of elements yielded by this iterator.
542 type Item;
543
544 /// Get the next element from the iterator.
545 ///
546 /// Returns `Some(item)` if there are more elements, `None` if exhausted.
547 /// None maps to NULL in R.
548 #[miniextendr(r_name = "next_item")]
549 fn next(&self) -> Option<Self::Item>;
550
551 /// Get the estimated number of remaining elements.
552 ///
553 /// Returns `(lower_bound, upper_bound)` where upper_bound is None if unknown.
554 /// In R, this becomes `c(lower, upper)` where upper is NA if unknown.
555 ///
556 /// Skipped from trait ABI because tuples don't have R conversions.
557 /// Expose via manual forwarding or custom wrapper methods.
558 #[miniextendr(skip)]
559 fn size_hint(&self) -> (i64, Option<i64>);
560
561 /// Consume the iterator and count remaining elements.
562 ///
563 /// **Warning:** This exhausts the iterator.
564 fn count(&self) -> i64 {
565 let mut count = 0i64;
566 while self.next().is_some() {
567 count += 1;
568 }
569 count
570 }
571
572 /// Collect up to `n` elements into a vector.
573 ///
574 /// Returns fewer than `n` elements if the iterator is exhausted first.
575 fn collect_n(&self, n: i32) -> Vec<Self::Item> {
576 let mut result = Vec::with_capacity(n.max(0) as usize);
577 for _ in 0..n {
578 match self.next() {
579 Some(item) => result.push(item),
580 None => break,
581 }
582 }
583 result
584 }
585
586 /// Skip `n` elements from the iterator.
587 ///
588 /// Returns the number of elements actually skipped (may be less than `n`
589 /// if the iterator is exhausted).
590 fn skip(&self, n: i32) -> i32 {
591 let mut skipped = 0i32;
592 for _ in 0..n {
593 if self.next().is_none() {
594 break;
595 }
596 skipped += 1;
597 }
598 skipped
599 }
600
601 /// Get the `n`th element (0-indexed), consuming elements up to and including it.
602 ///
603 /// Returns None if the iterator has fewer than `n + 1` elements.
604 fn nth(&self, n: i32) -> Option<Self::Item> {
605 if n < 0 {
606 return None;
607 }
608 for _ in 0..n {
609 self.next()?;
610 }
611 self.next()
612 }
613}
614
615// Note: No blanket impl because Iterator::next() requires &mut self,
616// but ExternalPtr methods receive &self. Users must use interior mutability.
617
618/// Adapter trait for [`std::iter::Extend`].
619///
620/// Provides collection extension operations for R, allowing Rust collections
621/// to be extended with R vectors. Since extension requires mutation, the
622/// wrapper type should use interior mutability (e.g., `RefCell`).
623///
624/// # Methods
625///
626/// - `extend_from_vec(items)` - Extend the collection with items from a vector
627/// - `extend_from_slice(items)` - Extend from a slice (for Clone items)
628///
629/// # Example
630///
631/// ```rust,ignore
632/// use std::cell::RefCell;
633///
634/// #[derive(ExternalPtr)]
635/// struct MyVec(RefCell<Vec<i32>>);
636///
637/// impl MyVec {
638/// fn new() -> Self {
639/// Self(RefCell::new(Vec::new()))
640/// }
641/// }
642///
643/// impl RExtend<i32> for MyVec {
644/// fn extend_from_vec(&self, items: Vec<i32>) {
645/// self.0.borrow_mut().extend(items);
646/// }
647/// }
648///
649/// #[miniextendr]
650/// impl RExtend<i32> for MyVec {}
651/// ```
652///
653/// In R:
654/// ```r
655/// v <- MyVec$new()
656/// v$extend_from_vec(c(1L, 2L, 3L)) # Add items
657/// v$extend_from_vec(c(4L, 5L)) # Add more items
658/// ```
659///
660/// # Design Note
661///
662/// Like `RIterator`, `RExtend` does NOT have a blanket impl because `Extend::extend()`
663/// requires `&mut self`, but R's ExternalPtr pattern provides `&self`. Users must
664/// implement this trait manually using interior mutability (RefCell, Mutex, etc.).
665#[miniextendr]
666pub trait RExtend<T> {
667 /// Extend the collection with items from a vector.
668 ///
669 /// The items are moved into the collection.
670 fn extend_from_vec(&self, items: Vec<T>);
671
672 /// Extend the collection with cloned items from a slice.
673 ///
674 /// Default implementation clones items into a Vec and calls `extend_from_vec`.
675 ///
676 /// Skipped from trait ABI because `&[T]` doesn't have TryFromSexp.
677 #[miniextendr(skip)]
678 fn extend_from_slice(&self, items: &[T])
679 where
680 T: Clone,
681 {
682 self.extend_from_vec(items.to_vec());
683 }
684
685 /// Get the current length of the collection.
686 ///
687 /// Optional - returns -1 if not implemented.
688 fn len(&self) -> i64 {
689 -1 // Indicates "unknown" - implementers can override
690 }
691
692 /// Check if the collection is empty.
693 ///
694 /// Returns false when length is unknown.
695 fn is_empty(&self) -> bool {
696 self.len() == 0
697 }
698}
699
700// Note: No blanket impl because Extend::extend() requires &mut self,
701// but ExternalPtr methods receive &self. Users must use interior mutability.
702
703/// Adapter trait for [`std::iter::FromIterator`].
704///
705/// Provides collection construction from iterators/vectors for R.
706/// Unlike `RExtend`, this creates a new collection from items.
707///
708/// # Methods
709///
710/// - `from_vec(items)` - Create a new collection from a vector
711///
712/// # Example
713///
714/// ```rust,ignore
715/// #[derive(ExternalPtr)]
716/// struct MySet(std::collections::HashSet<i32>);
717///
718/// impl RFromIter<i32> for MySet {
719/// fn from_vec(items: Vec<i32>) -> Self {
720/// Self(items.into_iter().collect())
721/// }
722/// }
723///
724/// #[miniextendr]
725/// impl RFromIter<i32> for MySet {}
726/// ```
727///
728/// In R:
729/// ```r
730/// set <- MySet$from_vec(c(1L, 2L, 2L, 3L)) # Creates {1, 2, 3}
731/// ```
732#[miniextendr]
733pub trait RFromIter<T>: Sized {
734 /// Create a new collection from a vector of items.
735 fn from_vec(items: Vec<T>) -> Self;
736}
737
738impl<C, T> RFromIter<T> for C
739where
740 C: FromIterator<T>,
741{
742 fn from_vec(items: Vec<T>) -> Self {
743 items.into_iter().collect()
744 }
745}
746
747/// Adapter trait for collections that can be converted to vectors.
748///
749/// This is the complement to [`RFromIter`]: while `RFromIter` creates collections
750/// from vectors, `RToVec` extracts vectors from collections.
751///
752/// # Methods
753///
754/// - `to_vec()` - Collect all elements into a vector (cloning elements)
755/// - `len()` - Get the number of elements
756/// - `is_empty()` - Check if the collection is empty
757///
758/// # Design Note
759///
760/// Unlike Rust's `IntoIterator::into_iter()` which consumes the collection,
761/// this trait borrows the collection and clones elements. This is necessary
762/// because R's `ExternalPtr` pattern provides `&self`, not owned `self`.
763///
764/// For consuming iteration, use [`RIterator`] with interior mutability.
765///
766/// # Example
767///
768/// ```rust,ignore
769/// use std::collections::HashSet;
770///
771/// #[derive(ExternalPtr)]
772/// struct MySet(HashSet<i32>);
773///
774/// // RToVec is automatically available via blanket impl
775/// #[miniextendr]
776/// impl RToVec<i32> for MySet {}
777/// ```
778///
779/// In R:
780/// ```r
781/// set <- MySet$new(...)
782/// vec <- set$to_vec() # Get all elements as vector
783/// set$len() # Number of elements
784/// set$is_empty() # Check if empty
785/// ```
786#[miniextendr]
787pub trait RToVec<T> {
788 /// Collect all elements into a vector.
789 ///
790 /// Elements are cloned from the collection.
791 fn to_vec(&self) -> Vec<T>;
792
793 /// Get the number of elements in the collection.
794 fn len(&self) -> i64;
795
796 /// Check if the collection is empty.
797 fn is_empty(&self) -> bool {
798 self.len() == 0
799 }
800}
801
802// Blanket impl for any collection where:
803// - &C can be iterated over (yielding &T references)
804// - T: Clone (so we can clone elements into the Vec)
805// - The iterator knows its exact size
806//
807// Note: Using HRTB (higher-ranked trait bounds) to express that &C
808// can be iterated for any lifetime.
809impl<C, T> RToVec<T> for C
810where
811 T: Clone,
812 for<'a> &'a C: IntoIterator<Item = &'a T>,
813 for<'a> <&'a C as IntoIterator>::IntoIter: ExactSizeIterator,
814{
815 fn to_vec(&self) -> Vec<T> {
816 self.into_iter().cloned().collect()
817 }
818
819 fn len(&self) -> i64 {
820 self.into_iter().len() as i64
821 }
822}
823
824/// Adapter trait for creating iterator wrappers from collections.
825///
826/// This trait provides a way to create an [`RIterator`] wrapper from a collection.
827/// Since `ExternalPtr` methods receive `&self`, this trait clones the underlying
828/// data to create an independent iterator.
829///
830/// # Type Parameters
831///
832/// - `T`: The element type yielded by the iterator
833/// - `I`: The iterator type returned (must implement [`RIterator`])
834///
835/// # Design Note
836///
837/// The returned iterator is independent from the source collection. Modifications
838/// to the original collection after calling `make_iter()` won't affect the
839/// iterator's output.
840///
841/// # Example
842///
843/// ```rust,ignore
844/// use std::cell::RefCell;
845///
846/// #[derive(ExternalPtr)]
847/// struct MyVec(Vec<i32>);
848///
849/// #[derive(ExternalPtr)]
850/// struct MyVecIter(RefCell<std::vec::IntoIter<i32>>);
851///
852/// impl RIterator for MyVecIter {
853/// type Item = i32;
854/// fn next(&self) -> Option<i32> {
855/// self.0.borrow_mut().next()
856/// }
857/// fn size_hint(&self) -> (i64, Option<i64>) {
858/// let (lo, hi) = self.0.borrow().size_hint();
859/// (lo as i64, hi.map(|h| h as i64))
860/// }
861/// }
862///
863/// impl RMakeIter<i32, MyVecIter> for MyVec {
864/// fn make_iter(&self) -> MyVecIter {
865/// MyVecIter(RefCell::new(self.0.clone().into_iter()))
866/// }
867/// }
868///
869/// #[miniextendr]
870/// impl RMakeIter<i32, MyVecIter> for MyVec {}
871/// ```
872///
873/// In R (note: expose `next` as `next_item` since `next` is reserved):
874/// ```r
875/// v <- MyVec$new(c(1L, 2L, 3L))
876/// it <- v$make_iter() # Create iterator
877/// it$next_item() # 1L
878/// it$next_item() # 2L
879/// v$to_vec() # c(1L, 2L, 3L) - original unchanged
880/// ```
881#[miniextendr]
882pub trait RMakeIter<T, I>
883where
884 I: RIterator<Item = T>,
885{
886 /// Create a new iterator wrapper.
887 ///
888 /// The iterator is independent from this collection (typically by cloning
889 /// the underlying data).
890 fn make_iter(&self) -> I;
891}
892
893// Note: No blanket impl because:
894// 1. The iterator type I must be a concrete type that implements RIterator
895// 2. RIterator requires interior mutability (RefCell/Mutex)
896// 3. Users must define their own iterator wrapper type
897
898#[cfg(test)]
899mod tests {
900 use super::*;
901
902 #[test]
903 fn test_rdebug() {
904 let v = vec![1, 2, 3];
905 assert_eq!(v.debug_str(), "[1, 2, 3]");
906 assert!(v.debug_str_pretty().contains('\n') || v.debug_str_pretty() == "[1, 2, 3]");
907 }
908
909 #[test]
910 fn test_rdisplay() {
911 let s = "hello";
912 assert_eq!(s.as_r_string(), "hello");
913
914 let n = 42i32;
915 assert_eq!(n.as_r_string(), "42");
916 }
917
918 #[test]
919 fn test_rhash() {
920 let a = "test";
921 let b = "test";
922 let c = "other";
923
924 assert_eq!(RHash::hash(&a), RHash::hash(&b));
925 assert_ne!(RHash::hash(&a), RHash::hash(&c));
926 }
927
928 #[test]
929 fn test_rord() {
930 assert_eq!(ROrd::cmp(&1i32, &2), -1);
931 assert_eq!(ROrd::cmp(&2i32, &2), 0);
932 assert_eq!(ROrd::cmp(&3i32, &2), 1);
933 }
934
935 #[test]
936 fn test_rpartialord() {
937 assert_eq!(RPartialOrd::partial_cmp(&1.0f64, &2.0), Some(-1));
938 assert_eq!(RPartialOrd::partial_cmp(&2.0f64, &2.0), Some(0));
939 assert_eq!(RPartialOrd::partial_cmp(&3.0f64, &2.0), Some(1));
940 assert_eq!(RPartialOrd::partial_cmp(&f64::NAN, &1.0), None);
941 }
942
943 #[test]
944 fn test_rerror_simple() {
945 use std::io;
946 let err = io::Error::new(io::ErrorKind::NotFound, "file not found");
947 assert_eq!(err.error_message(), "file not found");
948 assert_eq!(err.error_chain().len(), 1);
949 assert_eq!(err.error_chain_length(), 1);
950 }
951
952 #[test]
953 fn test_rerror_chain() {
954 use std::fmt;
955
956 #[derive(Debug)]
957 struct OuterError {
958 msg: &'static str,
959 source: InnerError,
960 }
961
962 #[derive(Debug)]
963 struct InnerError {
964 msg: &'static str,
965 }
966
967 impl fmt::Display for OuterError {
968 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
969 write!(f, "{}", self.msg)
970 }
971 }
972
973 impl fmt::Display for InnerError {
974 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
975 write!(f, "{}", self.msg)
976 }
977 }
978
979 impl std::error::Error for InnerError {}
980
981 impl std::error::Error for OuterError {
982 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
983 Some(&self.source)
984 }
985 }
986
987 let err = OuterError {
988 msg: "outer error",
989 source: InnerError { msg: "inner error" },
990 };
991
992 assert_eq!(err.error_message(), "outer error");
993 let chain = err.error_chain();
994 assert_eq!(chain.len(), 2);
995 assert_eq!(chain[0], "outer error");
996 assert_eq!(chain[1], "inner error");
997 assert_eq!(err.error_chain_length(), 2);
998 }
999
1000 #[test]
1001 fn test_rfromstr_success() {
1002 let result: Option<i32> = RFromStr::from_str("42");
1003 assert_eq!(result, Some(42));
1004
1005 let result: Option<f64> = RFromStr::from_str("3.141592653589793");
1006 assert_eq!(result, Some(f64::consts::PI));
1007
1008 let result: Option<bool> = RFromStr::from_str("true");
1009 assert_eq!(result, Some(true));
1010 }
1011
1012 #[test]
1013 fn test_rfromstr_failure() {
1014 let result: Option<i32> = RFromStr::from_str("not a number");
1015 assert_eq!(result, None);
1016
1017 let result: Option<f64> = RFromStr::from_str("abc");
1018 assert_eq!(result, None);
1019 }
1020
1021 #[test]
1022 fn test_rclone() {
1023 let v = vec![1, 2, 3];
1024 let cloned = RClone::clone(&v);
1025 assert_eq!(v, cloned);
1026
1027 // Verify it's a deep copy
1028 let s = String::from("hello");
1029 let cloned_s = RClone::clone(&s);
1030 assert_eq!(s, cloned_s);
1031 }
1032
1033 #[test]
1034 fn test_rdefault() {
1035 let default_i32: i32 = RDefault::default();
1036 assert_eq!(default_i32, 0);
1037
1038 let default_vec: Vec<i32> = RDefault::default();
1039 assert!(default_vec.is_empty());
1040
1041 let default_string: String = RDefault::default();
1042 assert_eq!(default_string, "");
1043
1044 let default_bool: bool = RDefault::default();
1045 assert!(!default_bool);
1046 }
1047
1048 #[test]
1049 fn test_rcopy() {
1050 // Primitives are Copy
1051 let x = 42i32;
1052 let y = RCopy::copy(&x);
1053 assert_eq!(x, y);
1054 assert!(x.is_copy());
1055
1056 // Tuples of Copy types are Copy
1057 let point = (1.0f64, 2.0f64);
1058 let point2 = RCopy::copy(&point);
1059 assert_eq!(point, point2);
1060 assert!(point.is_copy());
1061
1062 // Arrays of Copy types are Copy
1063 let arr = [1, 2, 3];
1064 let arr2 = RCopy::copy(&arr);
1065 assert_eq!(arr, arr2);
1066 }
1067
1068 use core::f64;
1069 // Tests for RIterator
1070 use std::cell::RefCell;
1071
1072 /// Test iterator wrapper using RefCell for interior mutability.
1073 struct TestIter(RefCell<std::vec::IntoIter<i32>>);
1074
1075 impl TestIter {
1076 fn new(data: Vec<i32>) -> Self {
1077 Self(RefCell::new(data.into_iter()))
1078 }
1079 }
1080
1081 impl RIterator for TestIter {
1082 type Item = i32;
1083
1084 fn next(&self) -> Option<Self::Item> {
1085 self.0.borrow_mut().next()
1086 }
1087
1088 fn size_hint(&self) -> (i64, Option<i64>) {
1089 let (lo, hi) = self.0.borrow().size_hint();
1090 (lo as i64, hi.map(|h| h as i64))
1091 }
1092 }
1093
1094 #[test]
1095 fn test_riterator_next() {
1096 let it = TestIter::new(vec![1, 2, 3]);
1097 assert_eq!(it.next(), Some(1));
1098 assert_eq!(it.next(), Some(2));
1099 assert_eq!(it.next(), Some(3));
1100 assert_eq!(it.next(), None);
1101 assert_eq!(it.next(), None); // Stays exhausted
1102 }
1103
1104 #[test]
1105 fn test_riterator_size_hint() {
1106 let it = TestIter::new(vec![1, 2, 3, 4, 5]);
1107 assert_eq!(it.size_hint(), (5, Some(5)));
1108 it.next();
1109 assert_eq!(it.size_hint(), (4, Some(4)));
1110 it.next();
1111 it.next();
1112 assert_eq!(it.size_hint(), (2, Some(2)));
1113 }
1114
1115 #[test]
1116 fn test_riterator_count() {
1117 let it = TestIter::new(vec![1, 2, 3, 4, 5]);
1118 assert_eq!(it.count(), 5);
1119 // Iterator is now exhausted
1120 assert_eq!(it.next(), None);
1121 }
1122
1123 #[test]
1124 fn test_riterator_collect_n() {
1125 let it = TestIter::new(vec![1, 2, 3, 4, 5]);
1126 let first_three = it.collect_n(3);
1127 assert_eq!(first_three, vec![1, 2, 3]);
1128 let remaining = it.collect_n(10); // Ask for more than available
1129 assert_eq!(remaining, vec![4, 5]);
1130 }
1131
1132 #[test]
1133 fn test_riterator_skip() {
1134 let it = TestIter::new(vec![1, 2, 3, 4, 5]);
1135 let skipped = it.skip(2);
1136 assert_eq!(skipped, 2);
1137 assert_eq!(it.next(), Some(3));
1138
1139 // Skip more than remaining
1140 let skipped = it.skip(10);
1141 assert_eq!(skipped, 2); // Only 2 elements were left
1142 }
1143
1144 #[test]
1145 fn test_riterator_nth() {
1146 let it = TestIter::new(vec![10, 20, 30, 40, 50]);
1147 // Get element at index 2 (third element)
1148 assert_eq!(it.nth(2), Some(30));
1149 // Iterator has consumed 0, 1, 2 - next is index 3
1150 assert_eq!(it.next(), Some(40));
1151
1152 // Negative index returns None
1153 let it2 = TestIter::new(vec![1, 2, 3]);
1154 assert_eq!(it2.nth(-1), None);
1155 }
1156
1157 #[test]
1158 fn test_riterator_empty() {
1159 let it = TestIter::new(vec![]);
1160 assert_eq!(it.next(), None);
1161 assert_eq!(it.size_hint(), (0, Some(0)));
1162 assert_eq!(it.count(), 0);
1163 assert_eq!(it.collect_n(5), Vec::<i32>::new());
1164 assert_eq!(it.skip(5), 0);
1165 assert_eq!(it.nth(0), None);
1166 }
1167
1168 // Tests for RExtend
1169 struct TestExtendVec(RefCell<Vec<i32>>);
1170
1171 impl TestExtendVec {
1172 fn new() -> Self {
1173 Self(RefCell::new(Vec::new()))
1174 }
1175
1176 fn get(&self) -> Vec<i32> {
1177 Clone::clone(&*self.0.borrow())
1178 }
1179 }
1180
1181 impl RExtend<i32> for TestExtendVec {
1182 fn extend_from_vec(&self, items: Vec<i32>) {
1183 self.0.borrow_mut().extend(items);
1184 }
1185
1186 fn len(&self) -> i64 {
1187 self.0.borrow().len() as i64
1188 }
1189 }
1190
1191 #[test]
1192 fn test_rextend_basic() {
1193 let v = TestExtendVec::new();
1194 assert_eq!(v.get(), Vec::<i32>::new());
1195 assert_eq!(v.len(), 0);
1196
1197 v.extend_from_vec(vec![1, 2, 3]);
1198 assert_eq!(v.get(), vec![1, 2, 3]);
1199 assert_eq!(v.len(), 3);
1200
1201 v.extend_from_vec(vec![4, 5]);
1202 assert_eq!(v.get(), vec![1, 2, 3, 4, 5]);
1203 assert_eq!(v.len(), 5);
1204 }
1205
1206 #[test]
1207 fn test_rextend_empty() {
1208 let v = TestExtendVec::new();
1209 v.extend_from_vec(vec![]);
1210 assert_eq!(v.get(), Vec::<i32>::new());
1211 assert_eq!(v.len(), 0);
1212 }
1213
1214 #[test]
1215 fn test_rextend_from_slice() {
1216 let v = TestExtendVec::new();
1217 let data = [1, 2, 3];
1218 v.extend_from_slice(&data);
1219 assert_eq!(v.get(), vec![1, 2, 3]);
1220 }
1221
1222 // Tests for RFromIter
1223 #[test]
1224 fn test_rfromiter_vec() {
1225 let v: Vec<i32> = RFromIter::from_vec(vec![1, 2, 3]);
1226 assert_eq!(v, vec![1, 2, 3]);
1227 }
1228
1229 #[test]
1230 fn test_rfromiter_hashset() {
1231 use std::collections::HashSet;
1232 let set: HashSet<i32> = RFromIter::from_vec(vec![1, 2, 2, 3, 3, 3]);
1233 assert_eq!(set.len(), 3);
1234 assert!(set.contains(&1));
1235 assert!(set.contains(&2));
1236 assert!(set.contains(&3));
1237 }
1238
1239 #[test]
1240 fn test_rfromiter_string() {
1241 let s: String = RFromIter::from_vec(vec!['h', 'e', 'l', 'l', 'o']);
1242 assert_eq!(s, "hello");
1243 }
1244
1245 #[test]
1246 fn test_rfromiter_empty() {
1247 let v: Vec<i32> = RFromIter::from_vec(vec![]);
1248 assert!(v.is_empty());
1249 }
1250
1251 // Tests for RToVec
1252 #[test]
1253 fn test_rtovec_vec() {
1254 let v = vec![1, 2, 3];
1255 let collected: Vec<i32> = RToVec::to_vec(&v);
1256 assert_eq!(collected, vec![1, 2, 3]);
1257 assert_eq!(RToVec::<i32>::len(&v), 3);
1258 assert!(!RToVec::<i32>::is_empty(&v));
1259 }
1260
1261 #[test]
1262 fn test_rtovec_empty() {
1263 let v: Vec<i32> = vec![];
1264 let collected: Vec<i32> = RToVec::to_vec(&v);
1265 assert!(collected.is_empty());
1266 assert_eq!(RToVec::<i32>::len(&v), 0);
1267 assert!(RToVec::<i32>::is_empty(&v));
1268 }
1269
1270 #[test]
1271 fn test_rtovec_hashset() {
1272 use std::collections::HashSet;
1273 let mut set = HashSet::new();
1274 set.insert(1);
1275 set.insert(2);
1276 set.insert(3);
1277
1278 let mut collected: Vec<i32> = RToVec::to_vec(&set);
1279 collected.sort();
1280 assert_eq!(collected, vec![1, 2, 3]);
1281 assert_eq!(RToVec::<i32>::len(&set), 3);
1282 }
1283
1284 #[test]
1285 fn test_rtovec_slice() {
1286 let arr = [10, 20, 30];
1287 let collected: Vec<i32> = RToVec::to_vec(&arr);
1288 assert_eq!(collected, vec![10, 20, 30]);
1289 assert_eq!(RToVec::<i32>::len(&arr), 3);
1290 }
1291
1292 // Tests for RMakeIter
1293 struct TestCollection(Vec<i32>);
1294
1295 struct TestCollectionIter(RefCell<std::vec::IntoIter<i32>>);
1296
1297 impl RIterator for TestCollectionIter {
1298 type Item = i32;
1299
1300 fn next(&self) -> Option<i32> {
1301 self.0.borrow_mut().next()
1302 }
1303
1304 fn size_hint(&self) -> (i64, Option<i64>) {
1305 let (lo, hi) = self.0.borrow().size_hint();
1306 (lo as i64, hi.map(|h| h as i64))
1307 }
1308 }
1309
1310 impl RMakeIter<i32, TestCollectionIter> for TestCollection {
1311 fn make_iter(&self) -> TestCollectionIter {
1312 TestCollectionIter(RefCell::new(Clone::clone(&self.0).into_iter()))
1313 }
1314 }
1315
1316 #[test]
1317 fn test_rmakeiter_basic() {
1318 let coll = TestCollection(vec![1, 2, 3]);
1319 let iter = coll.make_iter();
1320
1321 assert_eq!(iter.next(), Some(1));
1322 assert_eq!(iter.next(), Some(2));
1323 assert_eq!(iter.next(), Some(3));
1324 assert_eq!(iter.next(), None);
1325 }
1326
1327 #[test]
1328 fn test_rmakeiter_independent() {
1329 let coll = TestCollection(vec![1, 2, 3]);
1330
1331 // Create two independent iterators
1332 let iter1 = coll.make_iter();
1333 let iter2 = coll.make_iter();
1334
1335 // Consuming one doesn't affect the other
1336 assert_eq!(iter1.next(), Some(1));
1337 assert_eq!(iter1.next(), Some(2));
1338
1339 assert_eq!(iter2.next(), Some(1)); // iter2 starts fresh
1340 assert_eq!(iter2.size_hint(), (2, Some(2))); // 2 remaining in iter2
1341 }
1342}