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());
}