parsely_impl/error.rs
1use crate::parsely_write::ParselyWrite;
2
3pub type ParselyResult<T> = anyhow::Result<T>;
4
5/// Helper trait to coerce values of both `T: ParselyWrite` and `Result<T, E>: E:
6/// Into<anyhow::Error>` into `ParselyResult<T>`. We need a trait specifically for writing because
7/// if we don't bound the impl for `T` in some way there's ambiguity: the compiler doesn't know if
8pub trait IntoWritableParselyResult<T, B> {
9 fn into_writable_parsely_result(self) -> ParselyResult<T>;
10}
11
12impl<T, B> IntoWritableParselyResult<T, B> for T
13where
14 T: ParselyWrite<B>,
15{
16 fn into_writable_parsely_result(self) -> ParselyResult<T> {
17 Ok(self)
18 }
19}
20
21impl<T, E, B> IntoWritableParselyResult<T, B> for Result<T, E>
22where
23 E: Into<anyhow::Error>,
24{
25 fn into_writable_parsely_result(self) -> ParselyResult<T> {
26 self.map_err(Into::into)
27 }
28}
29
30/// When we need to convert an expression that may or may not be wrapped in a Result on the _read_
31/// path, we can rely on the fact that we'll eventually be assigning the value to a field with a
32/// concrete type and we can rely on type inference in order to figure out what that should be.
33/// Because of that we don't want/need the `ParselyWrite` trait bounds on the impl like we have
34/// above for the writable side, so we need a different trait here.
35// TODO: remove the 'read' from these method calls, as they get used in places like context
36// expression evaluation where the writable limitations also don't exist, but aren't exactly on the
37// 'read path' (for example when syncing state)
38pub trait IntoParselyResult<T> {
39 fn into_parsely_result(self) -> ParselyResult<T>;
40}
41
42impl<T> IntoParselyResult<T> for T {
43 fn into_parsely_result(self) -> ParselyResult<T> {
44 Ok(self)
45 }
46}
47
48impl<T, E> IntoParselyResult<T> for Result<T, E>
49where
50 E: Into<anyhow::Error>,
51{
52 fn into_parsely_result(self) -> ParselyResult<T> {
53 self.map_err(Into::into)
54 }
55}