Skip to main content

server_rpc/
error.rs

1
2use std::borrow::Borrow;
3
4use bitcoin::hex::FromHex;
5use log::debug;
6
7
8/// Extension trait for [tonic::Status]
9pub trait StatusExt: Borrow<tonic::Status> {
10	/// Whether the server rejected the request and no state has changed
11	fn is_rejection(&self) -> bool;
12
13	/// Get any not-found identifiers
14	fn not_found<T: FromHex>(&self) -> Option<Vec<T>>;
15}
16
17impl StatusExt for tonic::Status {
18	fn is_rejection(&self) -> bool {
19	    match self.code() {
20			tonic::Code::InvalidArgument | tonic::Code::NotFound => true,
21			_ => false,
22		}
23	}
24
25	fn not_found<T: FromHex>(&self) -> Option<Vec<T>> {
26		if self.code() != tonic::Code::NotFound {
27			return None;
28		}
29
30		let ids = match self.metadata().get("identifiers") {
31			Some(v) => v,
32			None => {
33				debug!("Server sent NOT_FOUND error without identifiers");
34				return Some(vec![]);
35			},
36		};
37		let mut ret = Vec::new();
38		let ids_str = match ids.to_str() {
39			Ok(v) => v,
40			Err(e) => {
41				debug!("Invalid (non-ASCII) value in NOT_FOUND identifiers metadata: {:#}", e);
42				return Some(vec![]);
43			},
44		};
45		for value in ids_str.split(',') {
46			match T::from_hex(value) {
47				Ok(v) => ret.push(v),
48				Err(e) => {
49					debug!("Server NOT_FOUND identifier could not be parsed: {:#}", e);
50				},
51			}
52		}
53		Some(ret)
54	}
55}