Return type errors making a POST request using reqwest in Rust - api

I'm new to Rust and Typed languages and am having trouble making a post request using reqwest in Rust. I'm not sure which arguments I should pass in to the Result return type enum.
I'm also not sure if my approach so far is the right on because I get errors when I call .await; after send. Does this function need to be async?
error[E0308]: mismatched types
--> rust/src/lib.rs:41:13
|
41 | Ok(res) => res,
| ^^^^^^^ expected opaque type, found enum `std::result::Result`
|
::: home/.cargo/registry/src/reqwest-0.11.3/src/async_impl/request.rs:416:26
|
416 | pub fn send(self) -> impl Future<Output = Result<Response, crate::Error>> {
| ---------------------------------------------------- the expected opaque type
|
= note: expected opaque type `impl std::future::Future`
found enum `std::result::Result<_, _>`
error[E0308]: mismatched types
--> rust/src/lib.rs:42:13
|
42 | Err(err) => err,
| ^^^^^^^^ expected opaque type, found enum `std::result::Result`
|
::: /home/.cargo/registry/src/reqwest-0.11.3/src/async_impl/request.rs:416:26
|
416 | pub fn send(self) -> impl Future<Output = Result<Response, crate::Error>> {
| ---------------------------------------------------- the expected opaque type
|
= note: expected opaque type `impl std::future::Future`
found enum `std::result::Result<_, _>`
error: aborting due to 2 previous errors
Ultimately, I'm not sure if I'm on the right track with making a POST request using reqwest, but this is what I have:
enum Result<T, E> {
Ok(T),
Err(E),
}
pub async fn make_request(path: &str) -> Result<(), ()>{
let client = reqwest::Client::new();
let request = client.post(format!("http://localhost:8000/{}", path))
.body("tbd")
.send();
match request {
Ok(res) => res,
Err(err) => err,
}
}
Any advice on moving forward would be greatly appreciated.

Related

How to pass a stm32f3discovery API into a function?

I am trying to create a separate file/module that has functions that can deal with the LEDs or gyro for the stm32f3discovery. I am trying to pass the stm32f3 API that holds all of the registers into a function to then use inside.
When I run this code, I get an error saying "there is no field '###' on type '##'". How can I do this?
main.rs
#![no_std]
#![no_main]
use stm32f3::stm32f303;
mod my_api;
#[entry]
fn main() -> ! {
let periph = stm32f303::Peripherals::take().unwrap();
let gpioe = periph.GPIOE;
let rcc = periph.RCC;
my_api::led::setup_led(&gpioe, &rcc);
loop {
my_api::led::all_led_on(&gpioe);
}
}
my_api.rs
pub mod led {
pub fn setup_led<G, R>(gpio: &G, rcc: &R) {
*rcc.ahbenr.modify(|_, w| w.iopeen().set_bit()); //enables clock
*gpio.moder.modify(|_, w| {
w.moder8().bits(0b01);
w.moder9().bits(0b01);
w.moder10().bits(0b01);
w.moder11().bits(0b01);
w.moder12().bits(0b01);
w.moder13().bits(0b01);
w.moder14().bits(0b01);
w.moder15().bits(0b01)
});
}
pub fn all_led_on<G>(gpio: &G) {
*gpio.odr.modify(|_, w| {
w.odr8().set_bit();
w.odr9().set_bit();
w.odr10().set_bit();
w.odr11().set_bit();
w.odr12().set_bit();
w.odr13().set_bit();
w.odr14().set_bit();
w.odr15().set_bit()
});
}
pub fn all_led_off<G>(gpio: &G) {
*gpio.odr.modify(|_, w| {
w.odr8().clear_bit();
w.odr9().clear_bit();
w.odr10().clear_bit();
w.odr11().clear_bit();
w.odr12().clear_bit();
w.odr13().clear_bit();
w.odr14().clear_bit();
w.odr15().clear_bit()
});
}
}
Error
error[E0609]: no field `odr` on type `&G`
--> src/my_api.rs:30:15
|
29 | pub fn all_led_off <G> (gpio: &G) {
| - type parameter 'G' declared here
30 | *gpio.odr.modify(|_,w| {
| ^^^
It has this error for all of the calls onto any of the registers
Instead of using a generic to try and force our way into passing in a type that you don't know use something like:
let my_name: () = 39.2;
It will give an error that will tell you what the value on the right is and you can use that to work out what data type you can pass into the function. As shown printing variable type in rust

How do I define a from method to convert the error in a foreign result type? [duplicate]

This question already has answers here:
Is it possible to implement methods on type aliases?
(1 answer)
Rust proper error handling (auto convert from one error type to another with question mark)
(5 answers)
How to do error handling in Rust and what are the common pitfalls?
(2 answers)
Closed 2 years ago.
I have a pair of Result type aliases, AResult and BResult. AResult is from another crate, and embeds its own error type AError. I have my result (BResult) and I want to convert errors from AError to BError so I can embed them in the BResults that I return.
TIO demo
struct AError(u32);
struct BError(i64);
type AResult = Result<(), AError>;
type BResult = Result<(), BError>;
impl From<AError> for BError {
fn from(item: AError) -> Self {
(item as i64)
}
}
impl From<AResult> for BResult {
fn from(item: AResult) -> Self {
item.map_err(BError::from)
}
}
fn main() {
let result_as_a: AResult = Err(5u32);
let result_as_b = result_as_a;
if let Err(value) = result_as_b {
print!("{}", value);
}
}
I have defined a conversion for the errors from AError to BError (impl From<AError> for BError { ... }) and I'm trying to define a conversion for the Result which uses it, thinking I could do:
impl From<AResult> for BResult {
fn from(item: AResult) -> Self {
item.map_err(BError::from)
}
}
But Rust complains that I can't define things from another crate:
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
--> src/main.rs:12:1
|
12 | impl From<AResult> for BResult {
| ^^^^^-------------^^^^^-------
| | | |
| | | `std::result::Result` is not defined in the current crate
| | `std::result::Result` is not defined in the current crate
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead
I'm trying to define an implementation on BResult, not AResult?!
Am I doing something very stupid? Is there a better way to do this?

Why isn't an error type implicitly converted when I return it?

The following code fails to compile
// winservice.rs
#[macro_use] extern crate err_derive;
extern crate windows_service;
use windows_service::service_manager::{ServiceManager, ServiceManagerAccess};
#[derive(Debug, Error)]
pub enum WinServiceError {
#[error(display = "could not query windows services api")]
WinApiError(windows_service::Error),
}
impl From<windows_service::Error> for WinServiceError {
fn from(error: windows_service::Error) -> Self {
WinServiceError::WinApiError(error)
}
}
fn get_manager(request_access: ServiceManagerAccess) -> Result<ServiceManager, WinServiceError> {
ServiceManager::local_computer(None::<&str>, request_access)
}
pub fn main() {
// get_manager();
}
I am getting the error
error[E0308]: mismatched types
--> src/winservice.rs:186:5
|
185 | fn get_manager(request_access: ServiceManagerAccess) -> Result<ServiceManager, Error> {
| ----------------------------- expected `std::result::Result<windows_service::service_manager::ServiceManager, winservice::Error>` because of return type
186 | ServiceManager::local_computer(None::<&str>, request_access)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `winservice::Error`, found enum `windows_service::Error`
|
= note: expected type `std::result::Result<_, winservice::Error>`
found type `std::result::Result<_, windows_service::Error>`
Why isn't the Rust compiler auto converting the return type from windows_service::Error to winservice::Error?
Thanks to #Shepmaster's help, I was able resolve the error.
I did not realize that I was returning the result object directly. I had to unwrap the result object for the conversion to work.
The following code attempts to return a value of type Result<_, windows_services::Error> as Result<_, WinServiceError>.
fn get_manager(request_access: ServiceManagerAccess) -> Result<ServiceManager, WinServiceError> {
ServiceManager::local_computer(None::<&str>, request_access)
}
But the following code works, because we are now creating a new Result object of the correct signature, and rust compiler performs the conversion between the error types while creating the new object.
fn get_manager(request_access: ServiceManagerAccess) -> Result<ServiceManager, WinServiceError> {
Ok(ServiceManager::local_computer(None::<&str>, request_access)?)
}

Why do I get "the method exists but the following trait bounds were not satisfied" when extending Result for failure types?

I'm trying to add a more concise version of the failure crate's .with_context(|e| format!("foo: {}", e)) to my code. Like this playground:
use failure::{Context, Fail, ResultExt}; // 0.1.5
/// Extension methods for failure `Result`.
pub trait ResultContext<T, E> {
/// Wraps the error type in a context type generated by looking at the
/// error value. This is very similar to `with_context` but much more
/// concise.
fn ctx(self, s: &str) -> Result<T, Context<String>>;
}
impl<T, E> ResultContext<T, E> for Result<T, E>
where
E: Fail,
{
fn ctx(self, s: &str) -> Result<T, Context<String>> {
self.map_err(|failure| {
let context = format!("{}: {}", s, failure);
failure.context(context)
})
}
}
pub fn foo() -> Result<i32, failure::Error> {
Ok(5i32)
}
pub fn main() -> Result<(), failure::Error> {
// This works.
let _ = foo().with_context(|_| "foo".to_string())?;
// This doesn't.
foo().ctx("foo")?
}
I get the following error:
error[E0599]: no method named `ctx` found for type `std::result::Result<i32, failure::error::Error>` in the current scope
--> src/main.rs:31:11
|
31 | foo().ctx("foo")?
| ^^^
|
= note: the method `ctx` exists but the following trait bounds were not satisfied:
`std::result::Result<i32, failure::error::Error> : ResultContext<_, _>`
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `ctx`, perhaps you need to implement it:
candidate #1: `ResultContext`
I can't work out why. I more or less copied the existing with_context code.
As the compiler tells you, Result<i32, failure::error::Error> doesn't implement ResultContext<_, _>. You have added a bound to your implementation:
where
E: Fail,
But failure::Error doesn't implement failure::Fail:
use failure; // 0.1.5
fn is_fail<F: failure::Fail>() {}
pub fn main() {
is_fail::<failure::Error>();
}
error[E0277]: the trait bound `failure::error::Error: std::error::Error` is not satisfied
--> src/main.rs:6:5
|
6 | is_fail::<failure::Error>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `failure::error::Error`
|
= note: required because of the requirements on the impl of `failure::Fail` for `failure::error::Error`
note: required by `is_fail`
--> src/main.rs:3:1
|
3 | fn is_fail<F: failure::Fail>() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You will need to alter your bounds or your type.

fn foo() -> Result<()> throws "expected 2 type arguments"

Why isn't Result<()> allowed when compiling this bit of Rust code? Is it a breaking change between Rust editions?
fn run() -> Result<()> {
let (tx, rx) = channel();
thread::spawn(move || {
do_things_with_tx(&exit_tx);
});
match exit_rx.recv() {
Ok(result) => if let Err(reason) = result {
return Err(reason);
},
Err(e) => {
return Err(e.into());
},
}
Ok(())
}
The compiler says:
error[E0107]: wrong number of type arguments: expected 2, found 1
--> src/main.rs:1000:18
|
1000 | fn run_wifi() -> Result<()> {
| ^^^^^^^^^^ expected 2 type arguments
When I tweak the return type to Result<(), Err>, it says:
error[E0107]: wrong number of type arguments: expected 2, found 0
--> src/main.rs:1000:29
|
1000 | fn run() -> Result<(), Err> {
| ^^^ expected 2 type arguments
This is from the wifi-connect project.
The definition of Result is, and has always been, the following:
pub enum Result<T, E> {
Ok(T),
Err(E),
}
This definition is even presented in the Rust Programming language, to show how simple it is. As a generic sum type of an OK outcome and an error outcome, it always expects two type parameters, and the compiler will complain if it cannot infer them, or the list of type arguments does not have the expected length.
On the other hand, one may find many libraries and respective docs showing a Result with a single type argument, as in Result<()>. What gives?
It's still no magic. By convention, libraries create type aliases for result types at the level of a crate or module. This works pretty well because it is common for those to produce errors of the same, locally created type.
pub type Result<T> = std::result::Result<T, Error>;
Or alternatively, a definition which can still purport as the original result type.
pub type Result<T, E = Error> = std::result::Result<T, E>;
This pattern is so common that some error helper crates such as error-chain, will automatically create a result alias type for each error declared.
As such, if you are using a library that may or may not use error-chain, you are expected to assume that mentions of Result<T> are local type aliases to a domain-specific Result<T, Error>. In case of doubt, clicking on that type in the generated documentation pages will direct you to the concrete definition (in this case, the alias).
From The Rust Programming Language section The ? Operator Can Only Be Used in Functions That Return Result
use std::error::Error;
use std::fs::File;
fn main() -> Result<(), Box<dyn Error>> {
let f = File::open("hello.txt")?;
Ok(())
}
TL;DR
use std::io::Result;
Link to the type description
Long answer
I believe that the top-voted answer given by E_net4 the comment flagger is correct. But it doesn't work if applied blindly. In both cases
this
pub type Result<T> = Result<T, Error>;
and this
pub type Result<T, E = Error> = Result<T, E>;
will give the cycle dependency error
error[E0391]: cycle detected when expanding type alias `Result`
--> src\main.rs:149:33
|
149 | pub type Result<T, E = Error> = Result<T, E>;
| ^^^^^^^^^^^^
|
= note: ...which immediately requires expanding type alias `Result` again
= note: type aliases cannot be recursive
= help: consider using a struct, enum, or union instead to break the cycle
= help: see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information
So as much as users of SO don't want to admit it, but Gabriel soft is very close to elegant solution, because that type alias
pub type Result<T> = result::Result<T, Error>;
is straight from the standard library.
Here it is, our desired Result with 1 generic argument is defined in std::io (docs). To fix the problem I added
use std::io::Result;
fn some_func() -> Result<()> {
...
}
or
use std::io;
fn some_func() -> io::Result<()> {
...
}
rustc 1.62.1
i solved my own error by making a generic Result type to handle the error
As its says it require a generic of T and E, so to simplify things, i had to follow this way
pub type Result = result::Result<T, Error>;