I define a pagination function in rust 1.57.0 like this:
impl<T> QueryFragment<Pg> for Paginated<T>
where
T: QueryFragment<Pg>,
{
fn walk_ast(&self, mut out: AstPass<Pg>) -> QueryResult<()> {
if self.is_big_table {
}else{
}
Ok(())
}
}
now I want to pass the &self into another function, when I define the function like this:
fn handle_big_table_query(&self, mut out: AstPass<Pg>){
out.push_sql("SELECT *, COUNT(*) OVER () FROM ");
if self.is_sub_query {
out.push_sql("(");
}
self.query.walk_ast(out.reborrow())?;
if self.is_sub_query {
out.push_sql(")");
}
out.push_sql(" t LIMIT ");
out.push_bind_param::<BigInt, _>(&self.per_page)?;
out.push_sql(" OFFSET ");
let offset = (self.page - 1) * self.per_page;
out.push_bind_param::<BigInt, _>(&offset)?;
}
the visual studio code shows error that:
Function `handle_big_table_query` cannot have `self` parameter
why did this happen? is it possible to pass &self into the function? what should I to do pass the parameter like this in rust?
Only methods can have self parameter. For free functions, either pass it as a normal parameter, or make them a method.
fn handle_big_table_query<T: QueryFragment<Pg>>(this: &Paginated<T>, mut out: AstPass<Pg>) {
out.push_sql("SELECT *, COUNT(*) OVER () FROM ");
if this.is_sub_query {
out.push_sql("(");
}
this.query.walk_ast(out.reborrow())?;
if this.is_sub_query {
out.push_sql(")");
}
out.push_sql(" t LIMIT ");
out.push_bind_param::<BigInt, _>(&this.per_page)?;
out.push_sql(" OFFSET ");
let offset = (this.page - 1) * this.per_page;
out.push_bind_param::<BigInt, _>(&offset)?;
}
Related
I receive a long string (several gigabytes) as chunks of [u8]s in a Crossbeam channel. I want to break it down to lines. How do I turn these chunks into a BufRead?
fn foo(recv: crossbeam_channel::Receiver<Vec<u8>>) {
let mut buf_read: dyn std::io::BufRead = WHAT_COMES_HERE(recv); // <----
for line in buf_read.lines() {
// ...
}
}
I make these chunks on another thread since they are CPU-intensive to make. I could use something else than Vec<u8> if it makes more sense.
I don't think there is anything builtin, but it shouldn't be too difficult to write yourself. For example something like this:
use crossbeam_channel; // 0.5.4
use std::cmp::min;
use std::io::BufRead;
struct CrossbeamReader {
recv: crossbeam_channel::Receiver<Vec<u8>>,
offset: usize,
buffer: Vec<u8>,
}
impl CrossbeamReader {
fn new (recv: crossbeam_channel::Receiver<Vec<u8>>) -> Self
{
CrossbeamReader { recv, offset: 0, buffer: vec![], }
}
}
impl std::io::Read for CrossbeamReader {
fn read (&mut self, buf: &mut [u8]) -> std::io::Result<usize>
{
while self.offset >= self.buffer.len() {
self.buffer = match self.recv.recv() {
Ok (v) => v,
Err (_) => return Ok (0), // TODO: error handling
};
self.offset = 0;
}
let size = min (buf.len(), self.buffer.len() - self.offset);
buf[..size].copy_from_slice (&self.buffer[self.offset .. self.offset + size]);
self.offset += size;
Ok (size)
}
}
pub fn foo(recv: crossbeam_channel::Receiver<Vec<u8>>) {
let buf_read = std::io::BufReader::new (CrossbeamReader::new (recv));
for _line in buf_read.lines() {
// ...
}
}
Playground
This is my dummy code that doesn't actually work, I would like to know how, or is there a way to achieve this functionality.
Currently if I want to do this, I need to define an enum and match, which is inefficient and difficult to maintain.
pub fn mainrun() {
let aimpl = MyStruct {
Name: "bar".to_string(),
};
// dummy method collector
let some_dummy = impl_method_collector(&aimpl);
for k in some_dummy {
k();
}
/*expected to get
bar say one
bar say two
bar say three
*/
}
struct MyStruct {
Name: String,
}
impl MyStruct {
fn one_fn(&self) {
println!("{:?} say one", self.Name)
}
fn two_fn(&self) {
println!("{:?} say two", self.Name)
}
fn three_fn(&self) {
println!("{:?} say three", self.Name)
}
}
Here is how I achieve the same in Go. I want to achieve something like this with Rust.
package main
import "reflect"
func main() {
println("start")
astr := &MyStruct{"bar"}
v := reflect.ValueOf(astr)
vNums := v.NumMethod()
for i := 0; i < vNums; i++ {
v.Method(i).Call([]reflect.Value{})
}
/*expected to get
start
bar say one
bar say three
bar say tow
*/
}
type MyStruct struct {
Name string
}
func (m *MyStruct) FnOne() {
println(m.Name, "say one")
}
func (m *MyStruct) FnTow() {
println(m.Name, "say tow")
}
func (m *MyStruct) FnThree() {
println(m.Name, "say three")
}
You can do something similar using a macro that defines all the "route" methods along with any "global" methods that want to use the list of "routes":
macro_rules! make_routes {
($name:ident $(fn $method:ident (&$self:ident) { $($code:tt)* })*) => {
impl $name {
$(fn $method (&$self) { $($code)* })*
// Here you define the method (or methods) that operate on the list
// of "routes".
fn call_all (&self) {
$(self.$method();)*
}
}
}
}
Then you call it like this:
struct MyStruct {
a: i32,
}
make_routes!{
MyStruct
fn route1 (&self) {
println!("Route 1");
}
fn route2 (&self) {
println!("Route 2 (a = {})", self.a);
}
}
Playground
Note that if the methods you want to call take extra parameters, then you will need to list the parameter names for each method (but you don't need to list the types since they must be the same anyway):
macro_rules! make_routes {
($name:ident $(fn $method:ident (&$self:ident, $param:pat) { $($code:tt)* })*) => {
impl $name {
$(fn $method (&$self, $param: i32) { $($code)* })*
fn call_all (&self, param: i32) {
$(self.$method (param);)*
}
}
}
}
make_routes!{
MyStruct
fn route1 (&self, param) {
println!("Route 1 (param = {})", param);
}
fn route2 (&self, param) {
println!("Route 2 (a = {}, param = {})", self.a, param);
}
}
Playground
For more details on macros, you can read The Little Book of Rust Macros.
I want to use a function in the main function in a rust program that I am building to help me learn rust and come up with an error: self value is a keyword only available in methods with a self parameterrustc(E0424). What can I fix in my code so that this error does not happen?
pub use crate::user_account::user_account;
use rand::Rng;
#[allow(dead_code)]
pub trait UserInfo {
fn user_info(&mut self);
fn acc_no(&mut self);
fn yes(self);
fn bank_new_user(self);
}
pub struct NewUser {
age: String,
new_user: String,
account: String,
account_number: i32,
routing_number: i32,
select: String,
}
impl UserInfo for NewUser {
fn user_info(&mut self) {
self.age = String::new();
self.new_user = String::new();
println!("What is your name?");
print!("Name: ");
std::io::stdin().read_line(&mut self.new_user);
println!(" ");
println!("Hello {}, What is your age? ", self.new_user);
std::io::stdin().read_line(&mut self.age);
let age2: String = self.age.trim().into();
}
fn acc_no(&mut self) {
println!(
"We will generate a new account number \
and routing number for you."
);
self.account_number = rand::thread_rng().gen_range(10000000..99999999);
println!("Your account number is {}", self.account_number);
self.routing_number = rand::thread_rng().gen_range(10000000..99999999);
println!("Your account routing number is {}", self.routing_number);
}
fn yes(self) {
NewUser::user_info(&mut self);
NewUser::acc_no(&mut self);
}
//function I want to use in main.
fn bank_new_user(self) {
self.account = String::new();
println!("Would you like to make a new account with us today?");
loop {
println!(
" yes: continue to application, no: continue browsing , \
or exit: to exit"
);
self.account.clear();
std::io::stdin()
.read_line(&mut self.account)
.expect("please type yes, no or exit.");
let account = self.account.trim();
match account {
"yes" => {
self.yes();
break;
}
"no" => {
println!("You do not need an account to continue browsing.");
println!("Have a wonderful day and thank you for considering Mars Banking!");
break;
}
"exit" => {
println!(
"Thank you for choosing Mars Banking for your banking needs!\
Have a wonderful day!"
);
break;
}
_ => {
println!("Error! Enter yes, no, or exit.")
}
}
}
}
}
pub mod new_user;
mod settings;
mod user_account;
pub use crate::settings::settings;
pub use crate::user_account::user_account;
use new_user::NewUser;
use new_user::UserInfo;
fn main() {
loop{
let mut select = String::new();
println!("Welcome to Mars Banking!");
println!("What would you like to do today?");
println!("Create a new account: 1\nLogin: 2\nSettings: 3\nExit: 4");
select.clear();
std::io::stdin().read_line(&mut select);
let select = select.trim();
match select {
//Here is where the error happens.
"1" => NewUser::bank_new_user(self),
"2" => user_account(),
"3" => settings(),
"4" => break,
_ => {}
}
}
}
The conventional pattern for this sort of constructor is a static method that doesn't take a self argument, like this:
impl NewUser {
fn bank_new_user() {
let mut new_user = NewUser { /* initialize the fields */ };
// Edit or use new_user as necessary
}
}
you can see an example of this here, in the methods defined for Point:
struct Point {
x: f64,
y: f64,
}
// Implementation block, all `Point` associated functions & methods go in here
impl Point {
// This is an "associated function" because this function is associated with
// a particular type, that is, Point.
//
// Associated functions don't need to be called with an instance.
// These functions are generally used like constructors.
fn origin() -> Point {
Point { x: 0.0, y: 0.0 }
}
// Another associated function, taking two arguments:
fn new(x: f64, y: f64) -> Point {
Point { x: x, y: y }
}
}
notice how niether origin nor new take self as an argument.
We all know that using global variables can lead to subtle bugs. I need to migrate Python programs to Rust, keeping the algorithm intact as far as possible. Once I have demonstrated Python-Rust equivalence there will be opportunities to debug and change the logic to fit Rust better. Here is a simple Python program using global variables, followed by my unsuccessful Rust version.
# global variable
a = 15
# function to perform addition
def add():
global a
a += 100
# function to perform subtraction
def subtract():
global a
a -= 100
# Using a global through functions
print("Initial value of a = ", a)
add()
print("a after addition = ", a)
subtract()
print("a after subtraction = ", a)
Here is a Rust program that runs, but I cannot get the closures to update the so-called global variable.
fn fmain() {
// global variable
let mut a = 15;
// perform addition
let add = || {
let mut _name = a;
// name += 100; // the program won't compile if this is uncommented
};
call_once(add);
// perform subtraction
let subtract = || {
let mut _name = a;
// name -= 100; // the program won't compile if this is uncommented
};
call_once(subtract);
// Using a global through functions
println!("Initial value of a = {}", a);
add();
println!("a after addition = {}", a);
subtract();
println!("a after subtraction = {}", a);
}
fn main() {
fmain();
}
fn call_once<F>(f: F)
where
F: FnOnce(),
{
f();
}
My request: Re-create the Python logic in Rust.
Your Rust code is not using global variables, the a variable is stack-allocated. While Rust doesn't particularly endorse global variables, you can certainly use them. Translated to Rust that uses actual globals, your program would look like this:
use lazy_static::lazy_static;
use parking_lot::Mutex; // or std::sync::Mutex
// global variable
lazy_static! {
static ref A: Mutex<u32> = Mutex::new(15);
}
// function to perform addition
fn add() {
*A.lock() += 100;
}
// function to perform subtraction
fn subtract() {
*A.lock() -= 100;
}
fn main() {
// Using a global through functions
println!("Initial value of a = {}", A.lock());
add();
println!("a after addition = {}", A.lock());
subtract();
println!("a after subtraction = {}", A.lock());
}
Playground
If you prefer to use closures, you can do that too, but you'll need to use interior mutability to allow multiple closures to capture the same environment. For example, you could use a Cell:
use std::cell::Cell;
fn main() {
let a = Cell::new(15);
let add = || {
a.set(a.get() + 100);
};
let subtract = || {
a.set(a.get() - 100);
};
// Using a global through functions
println!("Initial value of a = {}", a.get());
add();
println!("a after addition = {}", a.get());
subtract();
println!("a after subtraction = {}", a.get());
}
Playground
Dependency-less examples as enum and function. EDIT : Code improved, as suggested in comment and corrected match arm.
use std::sync::{Arc, Mutex, Once};
static START: Once = Once::new();
static mut ARCMUT: Vec<Arc<Mutex<i32>>> = Vec::new();
// as enum
enum Operation {
Add,
Subtract,
}
impl Operation {
// static change
fn result(self) -> i32 {
let mut arc_clone = unsafe { ARCMUT[0].clone() };
let mut unlock = arc_clone.lock().unwrap();
match self {
Operation::Add => *unlock += 100,
Operation::Subtract => *unlock -= 100,
}
*unlock
}
// dynamic change
fn amount(self, amount: i32) -> i32 {
let mut arc_clone = unsafe { ARCMUT[0].clone() };
let mut unlock = arc_clone.lock().unwrap();
match self {
Operation::Add => *unlock += amount,
Operation::Subtract => *unlock -= amount,
}
*unlock
}
}
// as a function
fn add() -> i32 {
let mut arc_clone = unsafe { ARCMUT[0].clone() };
let mut unlcok = arc_clone.lock().unwrap();
*unlcok += 100;
*unlcok
}
// as trait
trait OperationTrait {
fn add(self) -> Self;
fn subtract(self) -> Self;
fn return_value(self) ->i32;
}
impl OperationTrait for i32 {
fn add(mut self) -> Self {
let arc_clone = unsafe{ARCMUT[0].clone()};
let mut unlock = arc_clone.lock().unwrap();
*unlock += self;
self
}
fn subtract(mut self) -> Self {
let arc_clone = unsafe{ARCMUT[0].clone()};
let mut unlock = arc_clone.lock().unwrap();
*unlock -= self;
self
}
fn return_value(self)->Self{
let arc_clone = unsafe{ARCMUT[0].clone()};
let mut unlock = arc_clone.lock().unwrap();
*unlock
}
}
// fn main
fn main() {
START.call_once(|| unsafe {
ARCMUT = vec![Arc::new(Mutex::new(15))];
});
let test = Operation::Add.result();
println!("{:?}", test);
let test = Operation::Subtract.amount(100);
println!("{:?}", test);
let test = add();
println!("{:?}", test);
let test = 4000.add();
println!("{:?}", test);
}
I have some pseudocode that checks if a variable is null:
Test test;
if (test == null) {
test = new Test();
}
return test;
How would I do something like this in Rust? This is my attempt so far:
struct Test {
time: f64,
test: Test,
}
impl Test {
fn get(&self) -> Test {
if self.test == null {
// <--
self.test = Test { time: 1f64 };
} else {
self.test
}
}
}
Uninitialized variables cannot be detected at runtime since the compiler won't let you get that far.
If you wish to store an optional value, however, the Option<...> type is handy for that. You can then use match or if let statements to check:
let mut x: Option<f32> = None;
// ...
x = Some(3.5);
// ...
if let Some(value) = x {
println!("x has value: {}", value);
}
else {
println!("x is not set");
}