How to impl From<AStruct> for a tokio_postgres::Row - postgresql

I've successfully impl From<tokio_postgres::Row> for AStruct, but is it possible to (1) impl From<AStruct> to tokio_postgres::Row and (2) subsequently insert the created tokio_postgres::Row into a table? I've looked at tokio_postgres::Row (see bellow), and also tried to impl tokio_postgres::types::ToSql as well as
tokio_postgres::types::FromSql.
I'd really like to exclusively use Tokio-Postgres for this project, if it's possible.
I have written up a minimal code example bellow to show what I am trying to do.
Let me know if I can clarify my question in any way.
#[derive(ToSql, FromSql, Debug)]
enum E {
A,
B,
}
#[derive(ToSql, FromSql, Debug)]
struct AStruct {
i: i32,
e: E,
d: DateTime<Utc>
}
impl From<Row> for AStruct {
fn from(row: Row) -> Self {
Self {
i: row.get(0),
e: row.get(1),
d: row.get(2),
}
}
}
// TODO
impl From<AStruct> for Row {
fn from(s: S) -> Self {
Self {
statement: ...?,
body: ...?,
ranges: ...?,
}
}
}
#[tokio::main]
async fn main() -> Result<(), Error> {
let (client, _) = tokio_postgres::connect(database_url, NoTls).await?;
let s = AStruct {
i: 1,
e: E::A,
d: Utc::now(),
};
// This works!
let s: AStruct = client
.query("SELECT * FROM structs WHERE id = $1", &[&id])
.await?
.into_iter()
.next()
.unwrap()
.into();
// This does not work :(
let row: Row = s.into();
Ok(())
}

Related

Swift lazy array with throwing

I need to make a lazy array of my objects and process them later. For instance:
struct A {
init(i: Int) {
print(i)
}
}
let arrayA = (0..<3).lazy.map { A(i: $0) }
print(arrayA)
Outputs:
LazyMapSequence<Range<Int>, A>(_base: Range(0..<3), _transform: (Function))
The code from above works OK - neither init are called. But it changes when I try to use throwing initializer:
struct B {
init(i: Int) throws {
print(i)
}
}
let arrayB = try (0..<3).lazy.map { try B(i: $0) }
print(arrayB)
Outputs:
0
1
2
[__lldb_expr_92.B(), __lldb_expr_92.B(), __lldb_expr_92.B()]
As you can see all inits are called and the array is regular.
I haven't found any info about so my questions are:
Why does try force to convert from a lazy to a regular one (No throwing enumerator for collection etc.)?
Is it possible to make a lazy array with throw?
Simple workaround is wrapping throwing creation of your objects with throwing closures to postpone initialization and then you can operate lazy array of closures:
struct B {
init(i: Int) throws {
print(i)
}
}
let arrayB = (0..<3).lazy.map { i in { try B(i: i) } }
print(arrayB)
print(try arrayB[0]()) // Request first object
Outputs:
LazyMapSequence<Range<Int>, () throws -> B>(_base: Range(0..<3), _transform: (Function))
0
B()

How to write generic function in Swift using a protocol associatedtype

I'm trying to write generic handler function which will receive ResourceModel instances and process them somehow:
func handleGeneric<R, M: ResourceModel>(resource: R, modelType: M.Type) {
I got stuck with Swift protocols usage though
This is the error I get:
Resource.playground:60:20: note: generic parameter 'R' of global function 'handleGeneric(resource:modelType:)' declared here
func handleGeneric<R, M: ResourceModel>(resource: R, modelType: M.Type) {
import UIKit
// Structs
struct ResourceA: Decodable {
let id: Int
let name: String
}
struct ResourceB: Decodable {
let id: Int
let number: Int
}
// Models
protocol ResourceModel {
associatedtype R
init(resource: R)
}
class ModelA: ResourceModel {
var id: Int = 0
var name: String = ""
convenience required init(resource: ResourceA) {
self.init()
id = resource.id
name = resource.name
}
}
class ModelB: ResourceModel {
var id: Int = 0
var number: Int = 0
convenience required init(resource: ResourceB) {
self.init()
id = resource.id
number = resource.number
}
}
// Save
func handleA(resource: ResourceA) {
let m = ModelA(resource: resource)
// save ... A ...
print("handle A completed")
}
func handleB(resource: ResourceB) {
let m = ModelB(resource: resource)
// ... save B ...
print("handle B completed")
}
// Generic handler
func handleGeneric<R, M: ResourceModel>(resource: R, modelType: M.Type) {
let m = M.init(resource: resource)
// ... save m ...
print("handle generic completed")
}
// Download
func downloadA() {
let r = ResourceA(id: 1, name: "A")
handleA(resource: r)
}
func downloadB() {
let r = ResourceB(id: 2, number: 10)
handleB(resource: r)
}
downloadA()
downloadB()
The question is how can I implement the generic function I need? I.e.
handleGeneric<ResourceA, ModelA>(ResourceA(id: 1, name: "A"))
handleGeneric<ResourceB, ModelB>(ResourceB(id: 2, number: 10))
handleGeneric<ResourceC, ModelC>(ResourceC(id: 3, "foo": "bar"))
handleGeneric<ResourceD, ModelD>(ResourceD(id: 4, "egg": "spam"))
Upd
I tried
handleGeneric(resource: ResourceA(id: 1, name: "A"), modelType: ModelA.Type)
handleGeneric(resource: ResourceB(id: 2, number: 10), modelType: ModelB.Type)
But I get
Cannot convert value of type 'ResourceA' to expected argument type '_.R'
Don't put R in the <> -- use M.R in your signature.
func handleGeneric<M: ResourceModel>(resource: M.R, modelType: M.Type) {

How to pass a method as callback

In Python or C++, a class say A can delegate some work to another instance of class Say B, and set a callback method of A in B.
I try to do this in Rust, but so far I got nowhere, beaten by Rust compiler.
Here is Code I have tried, remaining code is at the end of this post.
In A::test I tried using closure to get a Fn() trait object as callback.
// let b = B::new(self.finish)); // ideally but would not compile
// let test :Box<Fn(String)> = Box::new(move |msg| {self.finish(msg);}); // cannot infer an appropriate lifetime due to conflicting requirements
// let b = B::new(&test);
// let b = B::new(&Box::new( |msg| {A::finish(&self, msg);} )); // expected trait std::ops::Fn, found closure
// let b = B::new(&Box::new( |msg| {self.finish(msg);} )); // expected trait std::ops::Fn, found closure
Nothing work yet. Is there a way doing this?
Any help would be appreciated!
Or Am I fundamentally wrong? Do Rust request an other way to implement the idea here?
Here is my testing code
Play Ground Link
struct A {}
impl A {
fn finish(&self, msg: String) {
println!("{}", msg);
}
fn test(&self) {
//let b = B::new(self.finish)); // would not compile
// let test :Box<Fn(String)> = Box::new(move |msg| {self.finish(msg);}); // cannot infer an appropriate lifetime due to conflicting requirements
// let b = B::new(&test);
// let b = B::new(&Box::new( |msg| {A::finish(&self, msg);} )); // expected trait std::ops::Fn, found closure
let b = B::new(&Box::new( |msg| {self.finish(msg);} )); // expected trait std::ops::Fn, found closure
b.start("hi".to_string().clone());
}
}
struct B<'b> {
// cb:fn(msg:String),
cb: &'b Box<Fn(String)>,
}
impl<'b> B<'b> {
fn new(cb: &'b Box<Fn(String)>) -> B<'b> {
B { cb: cb }
}
fn start(&self, msg: String) {
(self.cb)(msg);
}
}
fn main() {
let a = A {};
a.test();
}
Yes you can pass a method as callback to your struct and call it from this struct's method. And you don't need to box the closure as you pass a reference:
struct A {}
impl A {
fn finish(&self, msg: String) {
println!("{}", msg);
}
fn test(&self) {
let fun = |msg: String| self.finish(msg);
let b = B::new(&fun);
b.start("hi".to_string().clone());
}
}
struct B<'b> {
cb: &'b Fn(String),
}
impl<'b> B<'b> {
fn new(cb: &'b Fn(String)) -> B<'b> {
B { cb }
}
fn start(&self, msg: String) {
(self.cb)(msg);
}
}
fn main() {
let a = A {};
a.test();
}
playground
The box is useful when you move your function to the new struct, which is not your case.
Note: As your function is called start, I suspect in your real use case you want to start a thread, in which case you should probably look at channels instead of callbacks.

How to pass data across down a promise chain?

Let's say that I want to generate a data set that requires multiple promises to resolve, how would I store each result down the promise chain so I can create my final data set in one shot?
struct CompleteData {
let a: String
let b: String
}
func getData() -> Promise<CompleteData> {
getA().then { a -> Promise<String> in
return a.getB()
}.then { b -> CompleteData in
return CompleteData(a: ???, b: b)
}
}
The solutions that I'm coming up with don't feel elegant enough:
Temporary IUOs
Use implicitly-unwrapped optionals to store temporary values. This can break if I forget to assign to a.
func getData() -> Promise<CompleteData> {
var a: String!
getA().then { _a -> Promise<String> in
_a = a
return _a.getB()
}.then { b -> CompleteData in
return CompleteData(a: a, b: b)
}
}
Nested promises
Nest promises and access values from the outer scopes. This defeats the purpose of promises by getting into a nesting hell.
func getData() -> Promise<CompleteData> {
getA().then { a -> Promise<CompleteData> in
return a.getB().then { b -> CompleteData in
return CompleteData(a: a, b: b)
}
}
}
Other solutions on top of my head: use optional fields in CompleteData, use var fields in CompleteData and assign as the chain resolves, none of those are good to me.
Can someone think of a more elegant way to do this?
You could use tuples to pass data down the promise chain. You just need to specify tuple and "a" return promise. Use .map to return tuple. Here is the code on your example:
struct CompleteData {
let a: String
let b: String
}
func getData() -> Promise<CompleteData> {
getA().then { a -> Promise<(String, a)> in
return a.getB().map{ ($0, a) }
}.then { (b, a) -> CompleteData in
return CompleteData(a: a, b: b)
}
}
PromiseKit documentation
Hope it will help you. Cheers :)

Function that return either of two generics

I'm trying to implement either function, which accepts two generic container and return either of them:
func either<A,B>(a: Container<A>, b: Container<B>) -> ?either Container<A> or Container<B>? {
// choose any of container
return chosen
}
Looks like I need a protocol, that Container must conforms to, so that my either's return type should be of this protocol.
Is this right solution?
protocol ContainerProtocol
struct Container<T>: ContainerProtocol
func either<A: ContainerProtocol, B:ContainerProtocol, C:ContainerProtocol>(a: A, b: B) -> C {
// choose any of container
return chosen
}
UPDATE
ok so I've implemented the EitherContainer enum and the final code is following:
struct Container<T>: Unique {
typealias UnderlyingObject = T
var object: UnderlyingObject
var uniqueId: String
}
enum EitherContainer<A,B> {
case a(container: Container<A>)
case b(container: Container<B>)
}
func wrappedInput<A,B>(wra: Container<A>, wrb: Container<B>, paramClosure: (Container<A>, Container<B>) -> EitherContainer<A,B>) -> EitherContainer<A,B> {
//do some work here
return paramClosure(wra, wrb)
}
func rawInput<A, B>(a: A, b: B) -> Any {
let wrappedA = Container(object: a, uniqueId: "a")
let wrappedB = Container(object: b, uniqueId: "b")
let wrappedRes = wrappedInput(wrappedA, wrb: wrappedB) {
(a1: Container, a2: Container) -> EitherContainer<A,B> in
// do some work here
return EitherContainer.a(container: a1)
}
var rawRes: Any
switch wrappedRes {
case .a(let container):
rawRes = container.object
case .b(let container):
rawRes = container.object
}
return rawRes
}
what bothers me now, is Any type, which shuts the compiler up, but for me looks like a weak crutch. Again same problem rawInput<A, B>(a: A, b: B) -> Any . rawInput should return either A or B, but I'm forced to use Any instead. Should I add another enum for raw options? Any thoughts?
The traditional Either type looks like this:
enum Either<A, B>
{
case Left(A)
case Right(B)
}
and is more useful, as it's not limited to your Container type.
(Either is the "canonical" sum type.)
It would be used like this:
func wrappedInput<A, B> (
a : Container<A>,
b: Container<B>,
paramClosure: (Container<A>, Container<B>) -> Either<Container<A>,Container<B>>
) -> Either<Container<A>, Container<B>>
{
return Either.Left(a) // Dummy
}
func rawInput<A, B>(a: A, b: B) -> Either<A,B> {
let wrappedA = Container(object: a, uniqueId: "a")
let wrappedB = Container(object: b, uniqueId: "b")
let wrappedRes = wrappedInput(wrappedA, b: wrappedB) {
(a1: Container, a2: Container) -> Either<Container<A>, Container<B>> in
// do some work here
return Either.Left(a1)
}
switch wrappedRes {
case .Left(let container):
return Either.Left(container.object)
case .Right(let container):
return Either.Right(container.object)
}
}