Don't know how to use nom's dbg_dmp - rust

I have a parser setup where I've injected dbg_dmp to the best of my ability:
permutation((
check_eye_color,
check_passport_id,
check_birth_year,
check_issue_year,
check_expiry_year,
check_hair_color,
check_height,
dbg_dmp(check_cid, "cid"),
))(input)
This gives me:
error[E0277]: expected a `FnMut<(&str,)>` closure, found `impl Fn<(&[u8],)>`
No clue why or how to resolve this.

Related

Error handling for applications: how to return a public message error instead of all the chain of errors and tracing it at the same time?

PROLOGUE
I'm using async-graphql and I have hundreds of resolvers and for each resolver I would like to trace all the possible errors.
In each method of my app I'm using anyhow::{Error}.
Right now I have code similar to this for each resolver:
#[Object]
impl MutationRoot {
async fn player_create(&self, ctx: &Context<'_>, input: PlayerInput) -> Result<Player> {
let services = ctx.data_unchecked::<Services>();
let player = services
.player_create(input)
.await?;
Ok(player)
}
}
So I thought about using the below code (note the added line with .map_err()):
#[Object]
impl MutationRoot {
async fn player_create(&self, ctx: &Context<'_>, input: PlayerInput) -> Result<Player> {
let services = ctx.data_unchecked::<Services>();
let player = services
.player_create(input)
.await
.map_err(errorify)?;
Ok(player)
}
}
fn errorify(err: anyhow::Error) -> async_graphql::Error {
tracing::error!("{:?}", err);
err.into()
}
Now the error is traced along with all the error chain:
ERROR example::main:10: I'm the error number 4
Caused by:
0: I'm the error number 3
1: I'm the error number 2
2: I'm the error number 1
in example::async_graphql
QUESTION 1
Is there a way to avoid the .map_err() on each resolver?
I would like to use the ? alone.
Should I use a custom error?
Can we have a global "hook"/callback/fn to call on each error?
QUESTION 2
As you can see above the chain of the error is the inverse.
In my graphql response I'm getting as message the "I'm the error number 4" but I need to get the "I'm the error number 2" instead.
The error chain is created using anyhow like this:
main.rs: returns error with .with_context(|| "I'm the error number 4")?
call fn player_create() in graphql.rs: returns with .with_context(|| "I'm the error number 3")?
call fn new_player() in domain.rs: returns with .with_context(|| "I'm the error number 2")?
call fn save_player() in database.rs: returns with .with_context(|| "I'm the error number 1")?
How can I accomplish this?
I'm really new to Rust. I come from Golang where I was using a struct like:
type Error struct {
error error
public_message string
}
chaining it easily with:
return fmt.Errorf("this function is called but the error was: %w", previousError)
How to do it in Rust?
Do I necessarily have to use anyhow?
Can you point me to a good handling error tutorial/book for applications?
Thank you very much.
I would suggest you define your own error for your library and handle them properly by using thiserror crate.
It's like Go defining var ErrNotFound = errors.New(...) and use fmt.Errorf(..., err) to add context.
With the powerful tool enum in Rust, so you can handle every error properly by match arms. It also provides really convenient derive macro like #[from] or #[error(transparent)] to make error conversion/forwarding easy.
Edit 1:
If you want to separate public message and tracing log, you may consider defining you custom error struct like this:
#[derive(Error, Debug)]
pub struct MyError {
msg: String,
#[source] // optional if field name is `source`
source: anyhow::Error,
}
and implement Display trait for formatting its inner msg field.
Finally, you could use macro in tracing-attributes crate:
#[instrument(err(Debug))]
fn my_function(arg: usize) -> Result<(), std::io::Error> {
Ok(())
}
Is there a way to avoid the .map_err() on each resolver?
Yes, you should be able to remove it unless you really need to convert to async_graphql::Error.
Do I necessarily have to use anyhow?
No, but it makes this easier when using ? on different error types.
I'm really new to Rust. I come from Golang where I was using a struct like:
Take a look at thiserror which lets you build you own enum of error variants.

Why can't I import `std::assert` via `use` while it works for other macros from std?

With Rust 2018, this code works (Playground):
use std::panic;
use std::format;
use std::assert_eq;
But this:
use std::assert;
Results in this error:
error[E0432]: unresolved import `std::assert`
--> src/lib.rs:4:5
|
4 | use std::assert;
| ^^^^^^^^^^^ no `assert` in the root
I read the edition guide about this topic and it says that use should work with macro_rules! macros and procedural macros. Thus, I'm confused.
use should work with macro_rules! macros and procedural macros
Except assert is neither of those:
/// Built-in macros to the compiler itself.
///
/// These macros do not have any corresponding definition with a `macro_rules!`
/// macro, but are documented here. Their implementations can be found hardcoded
/// into libsyntax itself.
It is a compiler built-in:
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_doc_only_macro]
macro_rules! assert {
($cond:expr) => ({ /* compiler built-in */ });
($cond:expr,) => ({ /* compiler built-in */ });
($cond:expr, $($arg:tt)+) => ({ /* compiler built-in */ });
}
Other faux-macros include:
compile_error
format_args
env
option_env
concat_idents
concat
line
column
file
stringify
include_str
include_bytes
module_path
cfg
include
The actual definition of assert is buried much lower in libsyntax_ext/assert.rs
Stabilize uniform paths on Rust 2018 (#56417) does mention these in passing:
Built-in macros, for example use env.
Currently an error due to some (fixable) implementation details of built-in macros.
No known issues to resolve before stabilization (after the error is removed).

Rust conflict with error-chain and websocket crates

I'm trying to use error-chain with the websocket crate, but running into an issue that I'm not sure how to resolve. WsUpgrade::accept has the following signature:
fn accept(self) -> Result<Client<S>, (S, IoError)>
Note that the Err variant is a tuple. I want to configure error-chain to handle calls to this method, so I tried to do so as follows in the relevant consuming module:
mod errors {
error_chain! {
foreign_links {
WebSock((::std::net::TcpStream, ::std::io::Error));
}
}
}
This results in the following error, seemingly related to the presence of the tuple.
error: expected identifier, found `(`
--> src/lib/websock.rs:23:21
|
23 | WebSock((::std::net::TcpStream, ::std::io::Error));
| ^
How can I resolve this? Hopefully I've missed something simple.
A simple solution would be to introduce a type alias:
mod errors {
type WebSocketError = (::std::net::TcpStream, ::std::io::Error);
error_chain! {
foreign_links {
WebSock(WebSocketError);
}
}
}
However, this type does not implement traits required by error-chain (such as Error and Display), so it can't be used there.
I think the simplest solution is to convert the error manually using Result::map_err before passing the value to error-chain. For example, the following construction will produce Result<Client<S>, IoError>:
x.accept().map_err(|e| e.1)

Typescript class can only be found if there isn't a reference to its properties?

I am using TypeScript 2.0 in VSCode, however, the errors highlighted are all confirmed by the TypeScript compiler. So I am importing a module:
import * as els from 'elasticsearch';
where elasticsearch has definitions installed, e.g. npm i #types/elasticsearch -S
Now if in my class I have a property with an els type like this:
private _client: els.Client;
There isn't an issue, however, if I have a property with a type like this:
search(term: string): Promise<els.Client.search> {}
then I get the error:
Module 'Elasticsearch' has no exported member 'Client'
How can the class not be found if I'm looking for one of its properties, but not if I just look for it?
You are right, the error message is confusing. It originates from your attempt to use els.Client.search as a type. You get similar messages if you try this:
import * as els from 'elasticsearch';
class Foo {
private _client: els.Client;
y: els.Client.search;
bar() {}
x: Foo.bar;
}
error TS2305: Module 'Elasticsearch' has no exported member 'Client'.
error TS2503: Cannot find namespace 'Foo'.
Note how in the second message it complains that it can't find Foo right within the Foo class. You might consider posting an issue for typescript about this.
How can the class not be found if I'm looking for one of its
properties, but not if I just look for it?
The real problem is that you probably want the return type of your search to be the same as the return type of els.Client.search. I don't think there is a better way to do that other than essentially copy els.Client.search declaration:
search<T>(term: string): Promise<els.SearchResponse<T>> {}

"associated types may not be referenced here"

Can someone explain why this code fails to compile?
#![feature(associated_types)]
trait Wub {
type Zoop;
}
trait Flim: Wub {
}
I get the error:
qqq.rs:7:13: 7:16 error: associated types may not be referenced here
qqq.rs:7 trait Flim: Wub {
Looks like a bug, I filed #18996. Associated items are very raw at the moment, issue #17307 summarises how much there is to go.

Resources