I'm implementing a method that has a nested structure call.
I read about Rust lifetimes and I think my problem is about lifetimes, but I cannot understand how can I use this in the code.
#[derive(Debug)]
pub struct Request {
Header: String
}
#[derive(Debug)]
pub enum Proto {
HTTP,
HTTPS
}
#[derive(Debug)]
pub struct HTTP {
ssss: Request,
names: Proto,
}
impl HTTP {
pub fn new(name: Proto) -> HTTP {
HTTP{
ssss.Header: "Herman".to_string(),
names: name,
}
}
}
It's not possible assign a value to ssss.Header:
error: expected one of `,` or `}`, found `.`
--> src/main.rs:20:17
|
20 | ssss.Header: "Herman".to_string(),
| ^ expected one of `,` or `}` here
error[E0425]: cannot find value `ssss` in this scope
--> src/main.rs:20:13
|
20 | ssss.Header: "Herman".to_string(),
| ^^^^
| |
| `self` value is only available in methods with `self` parameter
| help: try: `self.ssss`
error[E0063]: missing field `names` in initializer of `HTTP`
--> src/main.rs:19:9
|
19 | HTTP{
| ^^^^ missing `names`
There is nothing magical about nested structures. You use the exact same syntax as a non-nested structure:
pub fn new(name: Proto) -> HTTP {
HTTP {
ssss: Request {
header: "Herman".to_string(),
},
names: name,
}
}
If you find the nesting too complicated, you can always introduce an intermediate variable:
pub fn new(names: Proto) -> HTTP {
let ssss = Request {
header: "Herman".to_string(),
};
HTTP { ssss, names }
}
Note: idiomatic Rust uses snake_case for identifiers like variables, methods, and struct properties. I've renamed your Header to header to avoid warnings.
Related
I trying to implement a proxy in Rust, allowing me to read a model, but also to perform mutable operations. To avoid having two different implementations of the proxy (one mutable, one immutable), I made the proxy implementation generic.
I would like the proxy to create other instances of self, in different situations, and this is where I got a type mismatch.
The code below reproduces the problem I have:
use std::borrow::{Borrow, BorrowMut};
struct Model {
data: Vec<u32>,
}
impl Model {
fn get_proxy(&self) -> Proxy<&Model> {
Proxy::new(self)
}
fn get_proxy_mut(&mut self) -> Proxy<&mut Model> {
Proxy::new(self)
}
}
struct Proxy<M: Borrow<Model>> {
model: M
}
impl<M: Borrow<Model>> Proxy<M> {
fn new(model: M) -> Self {
Self {model}
}
fn get_another(&self) -> Proxy<M> {
// FIRST ERROR here
self.model.borrow().get_proxy()
}
}
impl<M: BorrowMut<Model>> Proxy<M> {
fn get_another_mut(&mut self) -> Proxy<M> {
// SECOND ERROR here
self.model.borrow_mut().get_proxy_mut()
}
}
The first compiler error looks like
error[E0308]: mismatched types
--> src\sandbox.rs:28:9
|
21 | impl<'m, M: Borrow<Model>> Proxy<M> {
| - this type parameter
...
26 | fn get_another(&self) -> Proxy<M> {
| -------- expected `Proxy<M>` because of return type
27 | // FIRST ERROR here
28 | self.model.borrow().get_proxy()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `M`, found `&Model`
|
= note: expected struct `Proxy<M>`
found struct `Proxy<&Model>`
Any idea how to fix the first error? (I assume the second one will be fixed in a similar way).
I unfortunately must use sql_query(). However, I'm wondering if there is a way to serialize the database results into a nested struct. I'd like to avoid creating a flattened data type to receive the results from the data and instead use the data struct with nested struct definitions, similar to deserializing json with #[serde(flatten)]
I've attempted this with the following code:
use diesel::*;
use serde::Deserialize;
use diesel::r2d2::{ConnectionManager, PooledConnection};
type DB = diesel::pg::Pg;
type DbConn = PooledConnection<ConnectionManager<PgConnection>>;
diesel::table! {
foo (id) {
id -> Int4,
}
}
diesel::table! {
bar (id) {
id -> Int4,
foo_id -> Int4,
}
}
#[derive(Deserialize, Queryable)]
#[diesel(table_name=foo)]
pub struct Foo {
pub id: i32,
}
#[derive(Deserialize, Queryable, QueryableByName)]
pub struct Nested {
#[sql_type = "Integer"]
pub bar_id: i32,
pub foo: Foo
}
pub fn get_nested(conn: & mut DbConn) {
sql_query("select * from bar join foo on foo.id = bar.foo_id")
.get_results::<Nested>(conn);
}
But it complains
error: Cannot determine the SQL type of foo
--> src/main.rs:30:9
|
30 | pub foo: Foo
| ^^^
|
= help: Your struct must either be annotated with `#[diesel(table_name = foo)]` or have this field annotated with `#[diesel(sql_type = ...)]`
error[E0277]: the trait bound `Untyped: load_dsl::private::CompatibleType<Nested, Pg>` is not satisfied
--> src/main.rs:35:32
|
35 | .get_results::<Nested>(conn);
| ----------- ^^^^ the trait `load_dsl::private::CompatibleType<Nested, Pg>` is not implemented for `Untyped`
| |
| required by a bound introduced by this call
|
= help: the trait `load_dsl::private::CompatibleType<U, DB>` is implemented for `Untyped`
= note: required for `SqlQuery` to implement `LoadQuery<'_, _, Nested>`
note: required by a bound in `get_results`
--> /home/rogers/.cargo/registry/src/github.com-1ecc6299db9ec823/diesel-2.0.3/src/query_dsl/mod.rs:1695:15
|
1695 | Self: LoadQuery<'query, Conn, U>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::get_results`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `rust_test` due to 2 previous errors
[Finished running. Exit status: 101]
Is there a way to serialize the database values into a nested structs when doing raw sql queries in diesel?
To cite from the relevant documentation:
If a field is another struct which implements QueryableByName, instead of a column, you can annotate that struct with #[diesel(embed)]. Then all fields contained by that inner struct are loaded into the embedded struct.
That means that:
Your struct Foo needs to derive QueryableByName as well
The field foo of the Nested struct needs to be annotated with #[diesel(embed)]
I have a newtype struct:
pub struct Branch<'repo>(Git2Branch<'repo>);
And I am trying to wrap a method call:
impl <'repo> Branch<'_> {
pub fn into_reference(self) -> Git2Reference<'repo> {
self.0.into_reference()
}
}
(Git2Branch and Git2Reference here are aliases for types of the same name from the git2 crate.)
This fails to compile with
error: lifetime may not live long enough
--> git_wrapper/src/branch.rs:38:9
|
6 | impl <'repo> Branch<'_> {
| ----- lifetime `'repo` defined here
...
37 | pub fn into_reference(self) -> Git2Reference<'repo> {
| ---- has type `branch::Branch<'1>`
38 | self.0.into_reference()
| ^^^^^^^^^^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'repo` but it is returning data with lifetime `'1`
Lifetimes '1 and 'repo should be the same, but I can't figure out how (or if it's even possible) to specify the lifetime of self in this case.
impl <'repo> Branch<'_> {
Is the same as:
impl <'repo, 'anonymous> Branch<'anonymous> {
So the lifetimes 'repo and the anonymous lifetime of the field are unrelated - which causes an issue when you try to return the Git2Reference<'anonymous>.
You only need to talk about one lifetime here, so say that:
impl <'repo> Branch<'repo> {
struct DummyRtspClient<'a> {
on_produce: &'a dyn Fn(EncodedPacket)
}
impl ... for DummyRtspClient {
fn set_on_produce(&self, f: &'a dyn Fn(EncodedPacket)){
self.on_produce = f;
}
}
Then how can I use on_produce?
I tried
let encoded_packet = EncodedPacket{
data: Vec::new(),
};
self.on_produce(encoded_packet);
but it says that on_produce is not a member function, but a field.
I tried self.on_produce.call(encoded_packet) but I also get errors.
Your error message should say something like this:
error[E0599]: no method named `on_produce` found for reference `&DummyRtspClient<'a>` in the current scope
--> src/lib.rs:14:18
|
14 | self.on_produce(encoded_packet);
| ^^^^^^^^^^ field, not a method
|
help: to call the function stored in `on_produce`, surround the field access with parentheses
|
14 | (self.on_produce)(encoded_packet);
| ^ ^
In particular, the second part tells exactly you how to solve this: wrap self.on_produce in a set of parentheses to disambiguate it from attempting to call a member function.
I'm building a wrapper around a DLL. This DLL gives me access to a database engine which implements an OOP design pattern. This requires me to create multiple overlapping traits that cover all the functionality:
pub trait CursorStatement { /* ... */ }
pub trait CursorTable { /* ... */ }
pub trait CursorStatementTable { /* ... */ }
...
I want to be able to bring these traits in scope so that I can call the functions without having to list every trait. Right now I'm doing:
mod traittest;
use traittest::*;
fn test() -> Result<(), AceError> {
let t = traittest::Table::new(3, "ORDERS")?;
let c = traittest::Cursor { handle: 42 };
println!("t.fields={}", t.fields());
println!("c.fields={}", c.fields());
Ok(())
}
fn main() {
test().expect("success");
}
The problem with use foo::* is that it puts everything from the module into my namespace, which I don't want.
In the example above, I don't have to type traittest::Table or traittest::Cursor, I just have to type Table or Cursor. However, I want to have to prefix those objects with the module name so when I'm reading the code I know where the objects came from. I might want to create a Table object in my local file that is distinguished from the one coming from the module.
I also don't want to have to do the following because if I later have to add a new trait I will have to update a bunch of other source files that depend on this module:
mod traittest;
use traittest::{CursorStatement, CursorStatementTable, CursorTable, /* ... */};
I tried creating a Traits supertrait that would inherit all other traits as shown in Is there any way to create a type alias for multiple traits?, but it doesn't work because I can't implement the trait for anything because there's nothing that would be an implementation of every trait in the file:
pub trait Traits: CursorStatement, CursorTable, CursorStatementHandle, /* ... */ {}
If I could create a named scope for all the traits, that would work, but I can't figure out how to make Rust happy with this idea:
let traits = {
pub trait CursorTable { /* ... */ }
}
It looks like this trait_group macro might do the trick but it's not obvious to me how I could use it to solve my problem.
Here's my entire program
mod traittest {
#[derive(Debug)]
pub struct AceError {
code: u32,
description: String,
}
pub trait CursorTable {
fn get_handle(&self) -> u32; // impl's must write this function
fn fields(&self) -> String {
return format!("(get_handle() -> {})", self.get_handle());
}
}
pub struct Table {
pub handle: u32,
pub table_name: String,
}
pub struct Cursor {
pub handle: u32,
}
impl Table {
pub fn new(handle: u32, table_name: &str) -> Result<Table, AceError> {
let table = Table {
handle: handle,
table_name: table_name.to_string(),
};
return Ok(table);
}
}
impl CursorTable for Table {
fn get_handle(&self) -> u32 {
return self.handle;
}
}
impl CursorTable for Cursor {
fn get_handle(&self) -> u32 {
return self.handle;
}
}
pub trait Traits: CursorTable {} /* super trait to bring all other traits in scope */
}
use traittest::Traits;
fn test() -> Result<(), traittest::AceError> {
let t = traittest::Table::new(3, "ORDERS")?;
let c = traittest::Cursor { handle: 42 };
println!("t.fields={}", t.fields());
println!("c.fields={}", c.fields());
Ok(())
}
fn main() {
test().expect("success");
}
and here's the error I get:
warning: unused import: `traittest::Traits`
--> src/main.rs:49:5
|
49 | use traittest::Traits;
| ^^^^^^^^^^^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
error[E0599]: no method named `fields` found for struct `traittest::Table` in the current scope
--> src/main.rs:54:31
|
10 | fn fields(&self) -> String {
| ------
| |
| the method is available for `std::boxed::Box<traittest::Table>` here
| the method is available for `std::sync::Arc<traittest::Table>` here
| the method is available for `std::rc::Rc<traittest::Table>` here
...
15 | pub struct Table {
| ---------------- method `fields` not found for this
...
54 | println!("t.fields={}", t.fields());
| ^^^^^^ method not found in `traittest::Table`
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
49 | use crate::traittest::CursorTable;
|
error[E0599]: no method named `fields` found for struct `traittest::Cursor` in the current scope
--> src/main.rs:55:31
|
10 | fn fields(&self) -> String {
| ------
| |
| the method is available for `std::boxed::Box<traittest::Cursor>` here
| the method is available for `std::sync::Arc<traittest::Cursor>` here
| the method is available for `std::rc::Rc<traittest::Cursor>` here
...
20 | pub struct Cursor {
| ----------------- method `fields` not found for this
...
55 | println!("c.fields={}", c.fields());
| ^^^^^^ method not found in `traittest::Cursor`
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
49 | use crate::traittest::CursorTable;
|
I finally figured out a solution I can live with, in case anybody else is looking for a solution to this problem.
In your module where you define your traits, create a sub-module with all the traits, like so:
pub mod Traits
{
pub trait CursorTrait
{
fn get_handle ( &self ) -> u32; // impl's must write this function
fn fields ( &self ) -> String
{
return format! ( "(get_handle() -> {})", self.get_handle() );
}
}
}
Now in your other modules, if you want to bring the traits in scope without bringing in the entire module, you can just bring in the submodule, like so:
mod foo; use foo::Traits::*;