jsonptr/
resolve.rs

1//! # Resolve values based on JSON [`Pointer`]s
2//!
3//! This module provides the [`Resolve`] and [`ResolveMut`] traits which are
4//! implemented by types that can internally resolve a value based on a JSON
5//! Pointer.
6//!
7//! This module is enabled by default with the `"resolve"` feature flag.
8//!
9//! ## Usage
10//! [`Resolve`] and [`ResolveMut`] can be used directly or through the
11//! [`resolve`](Pointer::resolve) and [`resolve_mut`](Pointer::resolve_mut)
12//! methods on [`Pointer`] and [`PointerBuf`](crate::PointerBuf).
13//!
14//! ```rust
15//! use jsonptr::{Pointer, Resolve, ResolveMut};
16//! use serde_json::json;
17//!
18//! let ptr = Pointer::from_static("/foo/1");
19//! let mut data = json!({"foo": ["bar", "baz"]});
20//!
21//! let value = ptr.resolve(&data).unwrap();
22//! assert_eq!(value, &json!("baz"));
23//!
24//! let value = data.resolve_mut(ptr).unwrap();
25//! assert_eq!(value, &json!("baz"));
26//! ```
27//!
28//! ## Provided implementations
29//!
30//! | Lang  |     value type      | feature flag | Default |
31//! | ----- |: ----------------- :|: ---------- :| ------- |
32//! | JSON  | `serde_json::Value` |   `"json"`   |   ✓     |
33//! | TOML  |    `toml::Value`    |   `"toml"`   |         |
34//!
35//!
36use crate::{
37    diagnostic::{diagnostic_url, Diagnostic, Label},
38    index::{OutOfBoundsError, ParseIndexError},
39    Pointer, PointerBuf, Token,
40};
41use alloc::{boxed::Box, string::ToString};
42use core::iter::once;
43
44/// A trait implemented by types which can resolve a reference to a value type
45/// from a path represented by a JSON [`Pointer`].
46pub trait Resolve {
47    /// The type of value that this implementation can operate on.
48    type Value;
49
50    /// Error associated with `Resolve`
51    type Error;
52
53    /// Resolve a reference to `Self::Value` based on the path in a [Pointer].
54    ///
55    /// ## Errors
56    /// Returns a [`Self::Error`](Resolve::Error) if the [`Pointer`] can not
57    /// be resolved.
58    fn resolve(&self, ptr: &Pointer) -> Result<&Self::Value, Self::Error>;
59}
60
61/// A trait implemented by types which can resolve a mutable reference to a
62/// value type from a path represented by a JSON [`Pointer`].
63pub trait ResolveMut {
64    /// The type of value that is being resolved.
65    type Value;
66
67    /// Error associated with `ResolveMut`
68    type Error;
69
70    /// Resolve a mutable reference to a `serde_json::Value` based on the path
71    /// in a JSON Pointer.
72    ///
73    /// ## Errors
74    /// Returns a [`Self::Error`](ResolveMut::Error) if the [`Pointer`] can not
75    /// be resolved.
76    fn resolve_mut(&mut self, ptr: &Pointer) -> Result<&mut Self::Value, Self::Error>;
77}
78
79// TODO: should ResolveError be deprecated?
80/// Alias for [`Error`].
81pub type ResolveError = Error;
82
83/// Indicates that the `Pointer` could not be resolved.
84#[derive(Debug, PartialEq, Eq)]
85pub enum Error {
86    /// `Pointer` could not be resolved because a `Token` for an array index is
87    /// not a valid integer or dash (`"-"`).
88    ///
89    /// ## Example
90    /// ```rust
91    /// # use serde_json::json;
92    /// # use jsonptr::Pointer;
93    /// let data = json!({ "foo": ["bar"] });
94    /// let ptr = Pointer::from_static("/foo/invalid");
95    /// assert!(ptr.resolve(&data).unwrap_err().is_failed_to_parse_index());
96    /// ```
97    FailedToParseIndex {
98        /// Position (index) of the token which failed to parse as an [`Index`](crate::index::Index)
99        position: usize,
100        /// Offset of the partial pointer starting with the invalid index.
101        offset: usize,
102        /// The source `ParseIndexError`
103        source: ParseIndexError,
104    },
105
106    /// A [`Token`] within the [`Pointer`] contains an [`Index`] which is out of
107    /// bounds.
108    ///
109    /// ## Example
110    /// ```rust
111    /// # use serde_json::json;
112    /// # use jsonptr::Pointer;
113    /// let data = json!({ "foo": ["bar"] });
114    /// let ptr = Pointer::from_static("/foo/1");
115    /// assert!(ptr.resolve(&data).unwrap_err().is_out_of_bounds());
116    OutOfBounds {
117        /// Position (index) of the token which failed to parse as an [`Index`](crate::index::Index)
118        position: usize,
119        /// Offset of the partial pointer starting with the invalid index.
120        offset: usize,
121        /// The source `OutOfBoundsError`
122        source: OutOfBoundsError,
123    },
124
125    /// `Pointer` could not be resolved as a segment of the path was not found.
126    ///
127    /// ## Example
128    /// ```rust
129    /// # use serde_json::json;
130    /// # use jsonptr::{Pointer};
131    /// let mut data = json!({ "foo": "bar" });
132    /// let ptr = Pointer::from_static("/bar");
133    /// assert!(ptr.resolve(&data).unwrap_err().is_not_found());
134    /// ```
135    NotFound {
136        /// Position (index) of the token which was not found.
137        position: usize,
138        /// Offset of the pointer starting with the `Token` which was not found.
139        offset: usize,
140    },
141
142    /// `Pointer` could not be resolved as the path contains a scalar value
143    /// before fully exhausting the path.
144    ///
145    /// ## Example
146    /// ```rust
147    /// # use serde_json::json;
148    /// # use jsonptr::Pointer;
149    /// let mut data = json!({ "foo": "bar" });
150    /// let ptr = Pointer::from_static("/foo/unreachable");
151    /// let err = ptr.resolve(&data).unwrap_err();
152    /// assert!(err.is_unreachable());
153    /// ```
154    Unreachable {
155        /// Position (index) of the token which was unreachable.
156        position: usize,
157        /// Offset of the pointer which was unreachable.
158        offset: usize,
159    },
160}
161
162impl Error {
163    /// Offset of the partial pointer starting with the token which caused the
164    /// error.
165    pub fn offset(&self) -> usize {
166        match self {
167            Self::FailedToParseIndex { offset, .. }
168            | Self::OutOfBounds { offset, .. }
169            | Self::NotFound { offset, .. }
170            | Self::Unreachable { offset, .. } => *offset,
171        }
172    }
173
174    /// Position (index) of the token which caused the error.
175    pub fn position(&self) -> usize {
176        match self {
177            Self::FailedToParseIndex { position, .. }
178            | Self::OutOfBounds { position, .. }
179            | Self::NotFound { position, .. }
180            | Self::Unreachable { position, .. } => *position,
181        }
182    }
183
184    /// Returns `true` if this error is `FailedToParseIndex`; otherwise returns
185    /// `false`.
186    pub fn is_unreachable(&self) -> bool {
187        matches!(self, Self::Unreachable { .. })
188    }
189
190    /// Returns `true` if this error is `FailedToParseIndex`; otherwise returns
191    /// `false`.
192    pub fn is_not_found(&self) -> bool {
193        matches!(self, Self::NotFound { .. })
194    }
195
196    /// Returns `true` if this error is `FailedToParseIndex`; otherwise returns
197    /// `false`.
198    pub fn is_out_of_bounds(&self) -> bool {
199        matches!(self, Self::OutOfBounds { .. })
200    }
201
202    /// Returns `true` if this error is `FailedToParseIndex`; otherwise returns
203    /// `false`.
204    pub fn is_failed_to_parse_index(&self) -> bool {
205        matches!(self, Self::FailedToParseIndex { .. })
206    }
207}
208
209impl Diagnostic for Error {
210    type Subject = PointerBuf;
211
212    fn url() -> &'static str {
213        diagnostic_url!(enum assign::Error)
214    }
215
216    fn labels(&self, origin: &Self::Subject) -> Option<Box<dyn Iterator<Item = Label>>> {
217        let position = self.position();
218        let token = origin.get(position)?;
219        let offset = if self.offset() + 1 < origin.as_str().len() {
220            self.offset() + 1
221        } else {
222            self.offset()
223        };
224        let len = token.encoded().len();
225        let text = match self {
226            Error::FailedToParseIndex { .. } => "not an array index".to_string(),
227            Error::OutOfBounds { source, .. } => source.to_string(),
228            Error::NotFound { .. } => "not found in value".to_string(),
229            Error::Unreachable { .. } => "unreachable".to_string(),
230        };
231        Some(Box::new(once(Label::new(text, offset, len))))
232    }
233}
234
235impl core::fmt::Display for Error {
236    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
237        match self {
238            Self::FailedToParseIndex { offset, .. } => {
239                write!(f, "resolve failed: json pointer token at offset {offset} failed to parse as an index")
240            }
241            Self::OutOfBounds { offset, .. } => {
242                write!(
243                    f,
244                    "resolve failed: json pointer token at offset {offset} is out of bounds"
245                )
246            }
247            Self::NotFound { offset, .. } => {
248                write!(
249                    f,
250                    "resolve failed: json pointer token at {offset} was not found in value"
251                )
252            }
253            Self::Unreachable { offset, .. } => {
254                write!(f, "resolve failed: json pointer token at {offset} is unreachable (previous token resolved to a scalar or null value)")
255            }
256        }
257    }
258}
259
260#[cfg(feature = "std")]
261impl std::error::Error for Error {
262    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
263        match self {
264            Self::FailedToParseIndex { source, .. } => Some(source),
265            Self::OutOfBounds { source, .. } => Some(source),
266            _ => None,
267        }
268    }
269}
270
271#[cfg(feature = "json")]
272mod json {
273    use super::{parse_index, Error, Pointer, Resolve, ResolveMut};
274    use serde_json::Value;
275
276    impl Resolve for Value {
277        type Value = Value;
278        type Error = Error;
279
280        fn resolve(&self, mut ptr: &Pointer) -> Result<&Value, Self::Error> {
281            let mut offset = 0;
282            let mut position = 0;
283            let mut value = self;
284            while let Some((token, rem)) = ptr.split_front() {
285                let tok_len = token.encoded().len();
286                ptr = rem;
287                value = match value {
288                    Value::Array(v) => {
289                        let idx = token
290                            .to_index()
291                            .map_err(|source| Error::FailedToParseIndex {
292                                position,
293                                offset,
294                                source,
295                            })?
296                            .for_len(v.len())
297                            .map_err(|source| Error::OutOfBounds {
298                                position,
299                                offset,
300                                source,
301                            })?;
302                        Ok(&v[idx])
303                    }
304
305                    Value::Object(v) => v
306                        .get(token.decoded().as_ref())
307                        .ok_or(Error::NotFound { position, offset }),
308                    // found a leaf node but the pointer hasn't been exhausted
309                    _ => Err(Error::Unreachable { position, offset }),
310                }?;
311                offset += 1 + tok_len;
312                position += 1;
313            }
314            Ok(value)
315        }
316    }
317
318    impl ResolveMut for Value {
319        type Value = Value;
320        type Error = Error;
321
322        fn resolve_mut(&mut self, mut ptr: &Pointer) -> Result<&mut Value, Error> {
323            let mut offset = 0;
324            let mut position = 0;
325            let mut value = self;
326            while let Some((token, rem)) = ptr.split_front() {
327                let tok_len = token.encoded().len();
328                ptr = rem;
329                value = match value {
330                    Value::Array(array) => {
331                        let idx = parse_index(token, array.len(), position, offset)?;
332                        Ok(&mut array[idx])
333                    }
334                    Value::Object(v) => v
335                        .get_mut(token.decoded().as_ref())
336                        .ok_or(Error::NotFound { position, offset }),
337                    // found a leaf node but the pointer hasn't been exhausted
338                    _ => Err(Error::Unreachable { position, offset }),
339                }?;
340                offset += 1 + tok_len;
341                position += 1;
342            }
343            Ok(value)
344        }
345    }
346}
347fn parse_index(
348    token: Token,
349    array_len: usize,
350    position: usize,
351    offset: usize,
352) -> Result<usize, Error> {
353    token
354        .to_index()
355        .map_err(|source| Error::FailedToParseIndex {
356            position,
357            offset,
358            source,
359        })?
360        .for_len(array_len)
361        .map_err(|source| Error::OutOfBounds {
362            position,
363            offset,
364            source,
365        })
366}
367
368#[cfg(feature = "toml")]
369mod toml {
370    use super::{Error, Resolve, ResolveMut};
371    use crate::Pointer;
372    use toml::Value;
373
374    impl Resolve for Value {
375        type Value = Value;
376        type Error = Error;
377
378        fn resolve(&self, mut ptr: &Pointer) -> Result<&Value, Self::Error> {
379            let mut offset = 0;
380            let mut position = 0;
381            let mut value = self;
382            while let Some((token, rem)) = ptr.split_front() {
383                let tok_len = token.encoded().len();
384                ptr = rem;
385                value = match value {
386                    Value::Array(v) => {
387                        let idx = token
388                            .to_index()
389                            .map_err(|source| Error::FailedToParseIndex {
390                                position,
391                                offset,
392                                source,
393                            })?
394                            .for_len(v.len())
395                            .map_err(|source| Error::OutOfBounds {
396                                position,
397                                offset,
398                                source,
399                            })?;
400                        Ok(&v[idx])
401                    }
402
403                    Value::Table(v) => v
404                        .get(token.decoded().as_ref())
405                        .ok_or(Error::NotFound { position, offset }),
406                    // found a leaf node but the pointer hasn't been exhausted
407                    _ => Err(Error::Unreachable { position, offset }),
408                }?;
409                offset += 1 + tok_len;
410                position += 1;
411            }
412            Ok(value)
413        }
414    }
415
416    impl ResolveMut for Value {
417        type Value = Value;
418        type Error = Error;
419
420        fn resolve_mut(&mut self, mut ptr: &Pointer) -> Result<&mut Value, Error> {
421            let mut offset = 0;
422            let mut position = 0;
423
424            let mut value = self;
425            while let Some((token, rem)) = ptr.split_front() {
426                let tok_len = token.encoded().len();
427                ptr = rem;
428                value = match value {
429                    Value::Array(array) => {
430                        let idx = token
431                            .to_index()
432                            .map_err(|source| Error::FailedToParseIndex {
433                                position,
434                                offset,
435                                source,
436                            })?
437                            .for_len(array.len())
438                            .map_err(|source| Error::OutOfBounds {
439                                position,
440                                offset,
441                                source,
442                            })?;
443                        Ok(&mut array[idx])
444                    }
445                    Value::Table(v) => v
446                        .get_mut(token.decoded().as_ref())
447                        .ok_or(Error::NotFound { position, offset }),
448                    // found a leaf node but the pointer hasn't been exhausted
449                    _ => Err(Error::Unreachable { position, offset }),
450                }?;
451                offset += 1 + tok_len;
452                position += 1;
453            }
454            Ok(value)
455        }
456    }
457}
458
459#[cfg(test)]
460mod tests {
461    use super::{Error, Resolve, ResolveMut};
462    use crate::{
463        index::{OutOfBoundsError, ParseIndexError},
464        Pointer,
465    };
466    use core::fmt;
467
468    #[test]
469    fn resolve_error_is_unreachable() {
470        let err = Error::FailedToParseIndex {
471            position: 0,
472            offset: 0,
473            source: ParseIndexError::InvalidInteger("invalid".parse::<usize>().unwrap_err()),
474        };
475        assert!(!err.is_unreachable());
476
477        let err = Error::OutOfBounds {
478            position: 0,
479            offset: 0,
480            source: OutOfBoundsError {
481                index: 1,
482                length: 0,
483            },
484        };
485        assert!(!err.is_unreachable());
486
487        let err = Error::NotFound {
488            position: 0,
489            offset: 0,
490        };
491        assert!(!err.is_unreachable());
492
493        let err = Error::Unreachable {
494            position: 0,
495            offset: 0,
496        };
497        assert!(err.is_unreachable());
498    }
499
500    #[test]
501    fn resolve_error_is_not_found() {
502        let err = Error::FailedToParseIndex {
503            position: 0,
504            offset: 0,
505            source: ParseIndexError::InvalidInteger("invalid".parse::<usize>().unwrap_err()),
506        };
507        assert!(!err.is_not_found());
508
509        let err = Error::OutOfBounds {
510            position: 0,
511            offset: 0,
512            source: OutOfBoundsError {
513                index: 1,
514                length: 0,
515            },
516        };
517        assert!(!err.is_not_found());
518
519        let err = Error::NotFound {
520            position: 0,
521            offset: 0,
522        };
523        assert!(err.is_not_found());
524
525        let err = Error::Unreachable {
526            position: 0,
527            offset: 0,
528        };
529        assert!(!err.is_not_found());
530    }
531
532    #[test]
533    fn resolve_error_is_out_of_bounds() {
534        let err = Error::FailedToParseIndex {
535            position: 0,
536            offset: 0,
537            source: ParseIndexError::InvalidInteger("invalid".parse::<usize>().unwrap_err()),
538        };
539        assert!(!err.is_out_of_bounds());
540
541        let err = Error::OutOfBounds {
542            position: 0,
543            offset: 0,
544            source: OutOfBoundsError {
545                index: 1,
546                length: 0,
547            },
548        };
549        assert!(err.is_out_of_bounds());
550
551        let err = Error::NotFound {
552            position: 0,
553            offset: 0,
554        };
555        assert!(!err.is_out_of_bounds());
556
557        let err = Error::Unreachable {
558            position: 0,
559            offset: 0,
560        };
561        assert!(!err.is_out_of_bounds());
562    }
563
564    #[test]
565    fn resolve_error_is_failed_to_parse_index() {
566        let err = Error::FailedToParseIndex {
567            position: 0,
568            offset: 0,
569            source: ParseIndexError::InvalidInteger("invalid".parse::<usize>().unwrap_err()),
570        };
571        assert!(err.is_failed_to_parse_index());
572
573        let err = Error::OutOfBounds {
574            position: 0,
575            offset: 0,
576            source: OutOfBoundsError {
577                index: 1,
578                length: 0,
579            },
580        };
581        assert!(!err.is_failed_to_parse_index());
582
583        let err = Error::NotFound {
584            position: 0,
585            offset: 0,
586        };
587        assert!(!err.is_failed_to_parse_index());
588
589        let err = Error::Unreachable {
590            position: 0,
591            offset: 0,
592        };
593        assert!(!err.is_failed_to_parse_index());
594    }
595
596    /*
597    ╔═══════════════════════════════════════════════════╗
598    ║                        json                       ║
599    ╚═══════════════════════════════════════════════════╝
600    */
601
602    #[test]
603    #[cfg(feature = "json")]
604    fn resolve_json() {
605        use serde_json::json;
606
607        let data = &json!({
608            "array": ["bar", "baz"],
609            "object": {
610                "object": {"baz": {"qux": "quux"}},
611                "strings": ["zero", "one", "two"],
612                "nothing": null,
613                "bool": true,
614                "objects": [{"field": "zero"}, {"field": "one"}, {"field": "two"}]
615            },
616            "": 0,
617            "a/b": 1,
618            "c%d": 2,
619            "e^f": 3,
620            "g|h": 4,
621            "i\\j": 5,
622            "k\"l": 6,
623            " ": 7,
624            "m~n": 8
625        });
626        // let data = &data;
627
628        Test::all([
629            // 0
630            Test {
631                ptr: "",
632                data,
633                expected: Ok(data),
634            },
635            // 1
636            Test {
637                ptr: "/array",
638                data,
639                expected: Ok(data.get("array").unwrap()), // ["bar", "baz"]
640            },
641            // 2
642            Test {
643                ptr: "/array/0",
644                data,
645                expected: Ok(data.get("array").unwrap().get(0).unwrap()), // "bar"
646            },
647            // 3
648            Test {
649                ptr: "/a~1b",
650                data,
651                expected: Ok(data.get("a/b").unwrap()), // 1
652            },
653            // 4
654            Test {
655                ptr: "/c%d",
656                data,
657                expected: Ok(data.get("c%d").unwrap()), // 2
658            },
659            // 5
660            Test {
661                ptr: "/e^f",
662                data,
663                expected: Ok(data.get("e^f").unwrap()), // 3
664            },
665            // 6
666            Test {
667                ptr: "/g|h",
668                data,
669                expected: Ok(data.get("g|h").unwrap()), // 4
670            },
671            // 7
672            Test {
673                ptr: "/i\\j",
674                data,
675                expected: Ok(data.get("i\\j").unwrap()), // 5
676            },
677            // 8
678            Test {
679                ptr: "/k\"l",
680                data,
681                expected: Ok(data.get("k\"l").unwrap()), // 6
682            },
683            // 9
684            Test {
685                ptr: "/ ",
686                data,
687                expected: Ok(data.get(" ").unwrap()), // 7
688            },
689            // 10
690            Test {
691                ptr: "/m~0n",
692                data,
693                expected: Ok(data.get("m~n").unwrap()), // 8
694            },
695            // 11
696            Test {
697                ptr: "/object/bool/unresolvable",
698                data,
699                expected: Err(Error::Unreachable {
700                    position: 2,
701                    offset: 12,
702                }),
703            },
704            // 12
705            Test {
706                ptr: "/object/not_found",
707                data,
708                expected: Err(Error::NotFound {
709                    position: 1,
710                    offset: 7,
711                }),
712            },
713        ]);
714    }
715
716    /*
717    ╔═══════════════════════════════════════════════════╗
718    ║                        toml                       ║
719    ╚═══════════════════════════════════════════════════╝
720    */
721    #[test]
722    #[cfg(feature = "toml")]
723    fn resolve_toml() {
724        use toml::{toml, Value};
725
726        let data = &Value::Table(toml! {
727            "array" = ["bar", "baz"]
728            "object" = {
729                "object" = {"baz" = {"qux" = "quux"}},
730                "strings" = ["zero", "one", "two"],
731                "bool" = true,
732                "objects" = [{"field" = "zero"}, {"field" = "one"}, {"field" = "two"}]
733            }
734            "" = 0
735            "a/b" = 1
736            "c%d" = 2
737            "e^f" = 3
738            "g|h" = 4
739            "i\\j" = 5
740            "k\"l" = 6
741            " " = 7
742            "m~n" = 8
743        });
744        // let data = &data;
745
746        Test::all([
747            Test {
748                ptr: "",
749                data,
750                expected: Ok(data),
751            },
752            Test {
753                ptr: "/array",
754                data,
755                expected: Ok(data.get("array").unwrap()), // ["bar", "baz"]
756            },
757            Test {
758                ptr: "/array/0",
759                data,
760                expected: Ok(data.get("array").unwrap().get(0).unwrap()), // "bar"
761            },
762            Test {
763                ptr: "/a~1b",
764                data,
765                expected: Ok(data.get("a/b").unwrap()), // 1
766            },
767            Test {
768                ptr: "/c%d",
769                data,
770                expected: Ok(data.get("c%d").unwrap()), // 2
771            },
772            Test {
773                ptr: "/e^f",
774                data,
775                expected: Ok(data.get("e^f").unwrap()), // 3
776            },
777            Test {
778                ptr: "/g|h",
779                data,
780                expected: Ok(data.get("g|h").unwrap()), // 4
781            },
782            Test {
783                ptr: "/i\\j",
784                data,
785                expected: Ok(data.get("i\\j").unwrap()), // 5
786            },
787            Test {
788                ptr: "/k\"l",
789                data,
790                expected: Ok(data.get("k\"l").unwrap()), // 6
791            },
792            Test {
793                ptr: "/ ",
794                data,
795                expected: Ok(data.get(" ").unwrap()), // 7
796            },
797            Test {
798                ptr: "/m~0n",
799                data,
800                expected: Ok(data.get("m~n").unwrap()), // 8
801            },
802            Test {
803                ptr: "/object/bool/unresolvable",
804                data,
805                expected: Err(Error::Unreachable {
806                    position: 2,
807                    offset: 12,
808                }),
809            },
810            Test {
811                ptr: "/object/not_found",
812                data,
813                expected: Err(Error::NotFound {
814                    position: 1,
815                    offset: 7,
816                }),
817            },
818        ]);
819    }
820    struct Test<'v, V> {
821        ptr: &'static str,
822        expected: Result<&'v V, Error>,
823        data: &'v V,
824    }
825
826    impl<'v, V> Test<'v, V>
827    where
828        V: Resolve<Value = V, Error = Error>
829            + ResolveMut<Value = V, Error = Error>
830            + Clone
831            + PartialEq
832            + fmt::Display
833            + fmt::Debug,
834    {
835        fn all(tests: impl IntoIterator<Item = Test<'v, V>>) {
836            tests.into_iter().enumerate().for_each(|(i, t)| t.run(i));
837        }
838
839        fn run(self, _i: usize) {
840            _ = self;
841            let Test {
842                ptr,
843                data,
844                expected,
845            } = self;
846            let ptr = Pointer::from_static(ptr);
847
848            // cloning the data & expected to make comparison easier
849            let mut data = data.clone();
850            let expected = expected.cloned();
851
852            // testing Resolve
853            let res = data.resolve(ptr).cloned();
854            assert_eq!(&res, &expected);
855
856            // testing ResolveMut
857            let res = data.resolve_mut(ptr).cloned();
858            assert_eq!(&res, &expected);
859        }
860    }
861}