Skip to main content

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}