๐Ÿ“ฆ nrc / provide-any

๐Ÿ“„ tests.rs ยท 49 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49use crate::error::*;
use crate::provide_any::{tags, Requisition, TypeTag};

// A concrete error type implemented by an application or library author.
#[derive(Debug)]
pub struct ConcreteError {
    name: String,
    array: Vec<String>,
}

struct SuggestionTag;
impl<'a> TypeTag<'a> for SuggestionTag {
    type Type = &'a str;
}

impl Error for ConcreteError {
    fn provide_context<'a>(&'a self, req: &mut Requisition<'a, '_>) {
        // Provide a `String` value (a temporary value), a `&str` reference (references a field
        // of `self`), and a slice of `String`s.
        req.provide_value::<String, _>(|| "Hello!".to_owned())
            .provide::<SuggestionTag>(&*self.name)
            .provide_ref::<[String]>(&*self.array);
    }
}

#[test]
fn access_context() {
    let e: &dyn Error = &ConcreteError {
        name: "Bob".to_owned(),
        array: vec!["Alice".to_owned()],
    };

    // Get context by value.
    let s: String = e.get_context().unwrap();
    assert_eq!(&s, "Hello!");

    // Get context by reference.
    let s: &str = e.get_context_by_type_tag::<SuggestionTag>().unwrap();
    assert_eq!(s, "Bob");

    // Get context by reference.
    let s: &[String] = e.get_context_ref().unwrap();
    assert_eq!(s, &*vec!["Alice".to_owned()]);

    // Use the fully-general API to get an `i32`, this operation fails since `ConcreteError` does
    // not provide `i32` context.
    assert!(e.get_context_by_type_tag::<tags::Value<i32>>().is_none());
}