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