Rust all write to file methods give 'method not found in std::io::BufReader<std::fs::File>' - file

I've been following tutorials, accepted answers, and the docs. They never worked for me since the beginning of learning, and now I'm stuck at it again.
Imports:
use std::io::prelude::*;
use std::fs::{File, OpenOptions};
use std::io::Read;
use std::io::BufReader;
use std::io::BufRead;
use std::io::Write;
Code:
let mut file_help = OpenOptions::new().append(true).create_new(true).open("n.txt").expect(".");
let mut file_help = BufReader::new(file_help);
Loop for vec:
for i in d_call {file_help.write(format!("{}\n",i))};
In-loop variants that are giving out same errormethod not found in `std::io::BufReader<std::fs::File>:
file_help.write_all(format!("{}\n",i))
write!(file_help, "{}\n",i)
file_help.write(format!("{}\n",i.to_string()))
writeln!(file_help, "{}", i.to_string())
error[E0599]: no method named `write` found for struct `BufReader` in the current scope
--> src/main.rs:21:19
|
21 | file_help.write(format!("{}\n", i.to_string()))
| ^^^^^ method not found in `BufReader<File>`
Playground.

The issue is actually quite simple. You are trying to write data to a BufReader. It can buffer file reads, but does not implement any write functionality. You likely want to use a std::io::BufWriter instead.

Related

How to execute a collection of statements in Tiberius?

I could not figure out how to iterate over a collection and execute statements one by one with Tiberius.
My current code looks like this (simplified):
use futures::Future;
use futures_state_stream::StateStream;
use tokio::executor::current_thread;
use tiberius::SqlConnection;
fn find_files(files: &mut Vec<String>) {
files.push(String::from("file1.txt"));
files.push(String::from("file2.txt"));
files.push(String::from("file3.txt"));
}
fn main() {
let mut files: Vec<String> = Vec::new();
find_files(&mut files);
let future = SqlConnection::connect(CONN_STR)
.and_then(|conn| {
conn.simple_exec("CREATE TABLE db.dbo.[Filenames] ( [Spalte 0] varchar(80) );")
})
.and_then(|(_, conn)| {
for k in files.iter() {
let sql = format!("INSERT INTO db.dbo.Filenames ([Spalte 0]) VALUES ('{}')", k);
&conn.simple_exec(sql);
}
Ok(())
});
current_thread::block_on_all(future).unwrap();
}
I got the following error message
error[E0382]: use of moved value: `conn`
--> src/main.rs:23:18
|
20 | .and_then(|(_, conn)| {
| ---- move occurs because `conn` has type `tiberius::SqlConnection<std::boxed::Box<dyn tiberius::BoxableIo>>`, which does not implement the `Copy` trait
...
23 | &conn.simple_exec(sql);
| ^^^^ value moved here, in previous iteration of loop
I'm new to Rust but I know there is something wrong with the use of the conn variable but nothing works.
There are actual two questions here:
The header question: how to perform multiple sequential statements using tiberius?
The specific question concerning why an error message comes from a specific bit of code.
I will answer them separately.
Multiple statements
There are many ways to skin a cat. In TDS (the underlying protocol Tiberius is implementing) there is the possibility to execute several statements in a single command. They just need to be delimited by using semicolon. The response from such an execution is in Tiberius represented a stream of futures, one for each statement.
So if your chain of statements is not too big to fit into one command, just build one string and send it over:
fn main() {
let mut files: Vec<String> = Vec::new();
find_files(&mut files);
let stmts = vec![
String::from(
"CREATE TABLE db.dbo.[Filenames] ( [Spalte 0] varchar(80) )")]
.into_iter()
.chain(files.iter().map(|k|
format!("INSERT INTO db.dbo.Filenames ([Spalte 0]) VALUES ('{}')", k)))
.collect::<Vec<_>>()
.join(";");
let future
= SqlConnection::connect(std::env::var("CONN_STR").unwrap().as_str())
.and_then(|conn|
conn.simple_exec(stmts)
.into_stream()
.and_then(|future| future)
.for_each(|_| Ok(())));
current_thread::block_on_all(future).unwrap();
}
There is some simple boilerplate in that example.
simple_exec returns an ExecResult, a wrapper around the individual statement's future results. Calling `into_stream() on that provides a stream of those futures.
That stream of results need to be forced to be carried out, one way of doing that is to call and_then, which awaits each future and does something with it.
We don't actually care about the results here, so we just do a noop for_each.
But, say that there is a lot of statements, more than can fit in a single TDS command, then there is a need to issue them separately (another case is when the statements themselves depend on earlier ones). A version of that problem is solved in How do I iterate over a Vec of functions returning Futures in Rust? .
Then finally, what is your specific error? Well conn is consumed by simple_exec, so it cannot be used afterwards, that is what the error tells you. If you want to use the connection after that execution is done you have to use the Future it returns, which is wrapping the mutated connection. I defer to the link above, on one way to do that.

Is it possible to write a function that calls BufRead::fill_buf until an interrupted error no longer occurs without using unsafe?

Is it possible to write a function that calls BufRead::fill_buf until io::ErrorKind::Interrupted no longer occurs without using unsafe?
With unsafe code, it is:
use std::{
io::{self, BufRead},
slice,
};
fn fill_buf_and_ignore_interrupts(reader: &mut impl BufRead) -> io::Result<&[u8]> {
let (buf_ptr, buf_len) = loop {
match reader.fill_buf() {
Ok(buf) => (buf.as_ptr(), buf.len()),
Err(e) => {
if e.kind() != io::ErrorKind::Interrupted {
return Err(e);
}
}
}
};
Ok(unsafe { slice::from_raw_parts(buf_ptr, buf_len) })
}
If I try to return or break Ok(buf), I get an error from the borrow checker:
error[E0499]: cannot borrow `*reader` as mutable more than once at a time
--> src/lib.rs:8:15
|
6 | fn fill_buf_and_ignore_interrupts(reader: &mut impl BufRead) -> io::Result<&[u8]> {
| - let's call the lifetime of this reference `'1`
7 | let (buf_ptr, buf_len) = loop {
8 | match reader.fill_buf() {
| ^^^^^^ mutable borrow starts here in previous iteration of loop
9 | Ok(buf) => return Ok(buf),
| ------- returning this value requires that `*reader` is borrowed for `'1`
I have tried to replace the loop with recursion, but the error stays. I have also tried to use #![feature(nll)], but it does not work either.
You cannot, and neither should you want to for reasons highlighted below (they have nothing to do with the reference return or unsafe). fill_buf does not work the way you think it does, due to one important caveat from the doc:
Returns the contents of the internal buffer, filling it with more data
from the inner reader if it is empty.
In other words, a subsequent call to fill_buf without consume will be a no-op if the trait is implemented properly and follows the contract stated in the doc. As such, doing one without the other is fraught with risk if you forget that requirement anywhere in anything that calls fill_buf.
Two solutions:
If you're reading to the end of a stream (which is what a BufReader does in quite a few other languages), just BufRead::read_to_end(), BufRead::read_line() or BufRead::read_until(). If you can identify a delimiter, read_until can be easily be worked into an iterable structure
If you are trying to peek at the data and possibly wait for more, you'll need to implement your own trait. This is not a frequent need as most people trying to peek into a stream are looking for a Pattern or a single byte, which BufRead covers.
As a quick summary, fill_buf does not do what you think it does, and you should not need to call it more than once without consuming the internal state of the buffer. If you are not trying to do this, then the lower-level methods of BufRead are not the tool for the job.
I don't think it's possible in safe Rust today for the loop to return a reference to fill_buf's return. (At least I hit my head against this for a while before giving up.)
But...you could just call fill_buf an extra time. If the buffer is already filled, the call should return Ok, and I'd expect the cost to be minimal. (Maybe inlining and optimization will eliminate it entirely.) If that's not true, the underlying BufRead implementation is bad.
I just did something similar in a BufRead adapter that skips escape bytes (looping over the underlying stream's fill_buf when the current chunk has no more non-escape bytes to pass along).
use std::io::{self, BufRead};
pub fn fill_buf_and_ignore_interrupts(reader: &mut impl BufRead) -> io::Result<&[u8]> {
while let Err(e) = reader.fill_buf() {
if e.kind() != io::ErrorKind::Interrupted {
return Err(e);
}
}
reader.fill_buf()
}
Pay no attention to the other answer that says you must never call fill_buf without consume. It's wrong. You should simply expect that if you call fill_buf again without calling consume first, the stream will be at the same position. You only need to call consume when you want the stream to advance. (And I don't know how you could end up with the nonsense idea that you should call consume after fill_buf returns error...)
I have found the answer here: Rust lifetime issue in loop
Rustc can't "deal" with conditional borrowing returns
So, for now, unsafe in such case is the only answer.

Package-qualified names. Differences (if any) between Package::<&var> vs &Package::var?

Reading through https://docs.perl6.org/language/packages#Package-qualified_names it outlines qualifying package variables with this syntax:
Foo::Bar::<$quux>; #..as an alternative to Foo::Bar::quux;
For reference the package structure used as the example in the document is:
class Foo {
sub zape () { say "zipi" }
class Bar {
method baz () { return 'Þor is mighty' }
our &zape = { "zipi" }; #this is the variable I want to resolve
our $quux = 42;
}
}
The same page states this style of qualification doesn't work to access &zape in the Foo::Bar package listed above:
(This does not work with the &zape variable)
Yet, if I try:
Foo::Bar::<&zape>; # instead of &Foo::Bar::zape;
it is resolves just fine.
Have I misinterpreted the document or completely missed the point being made? What would be the logic behind it 'not working' with code reference variables vs a scalar for example?
I'm not aware of differences, but Foo::Bar::<&zape> can also be modified to use {} instead of <>, which then can be used with something other than literals, like this:
my $name = '&zape';
Foo::Bar::{$name}()
or
my $name = 'zape';
&Foo::Bar::{$name}()
JJ and Moritz have provided useful answers.
This nanswer is a whole nother ball of wax. I've written and discarded several nanswers to your question over the last few days. None have been very useful. I'm not sure this is either but I've decided I've finally got a first version of something worth publishing, regardless of its current usefulness.
In this first installment my nanswer is just a series of observations and questions. I also hope to add an explanation of my observations based on what I glean from spelunking the compiler's code to understand what we see. (For now I've just written up the start of that process as the second half of this nanswer.)
Differences (if any) between Package::<&var> vs &Package::var?
They're fundamentally different syntax. They're not fully interchangeable in where you can write them. They result in different evaluations. Their result can be different things.
Let's step thru lots of variations drawing out the differences.
say Package::<&var>; # compile-time error: Undeclared name: Package
So, forget the ::<...> bit for a moment. P6 is looking at that Package bit and demanding that it be an already declared name. That seems simple enough.
say &Package::var; # (Any)
Quite a difference! For some reason, for this second syntax, P6 has no problem with those two arbitrary names (Package and var) not having been declared. Who knows what it's doing with the &. And why is it (Any) and not (Callable) or Nil?
Let's try declaring these things. First:
my Package::<&var> = { 42 } # compile-time error: Type 'Package' is not declared
OK. But if we declare Package things don't really improve:
package Package {}
my Package::<&var> = { 42 } # compile-time error: Malformed my
OK, start with a clean slate again, without the package declaration. What about the other syntax?:
my &Package::var = { 42 }
Yay. P6 accepts this code. Now, for the next few lines we'll assume the declaration above. What about:
say &Package::var(); # 42
\o/ So can we use the other syntax?:
say Package::<&var>(); # compile-time error: Undeclared name: Package
Nope. It seems like the my didn't declare a Package with a &var in it. Maybe it declared a &Package::var, where the :: just happens to be part of the name but isn't about packages? P6 supports a bunch of "pseudo" packages. One of them is LEXICAL:
say LEXICAL::; # PseudoStash.new(... &Package::var => (Callable) ...
Bingo. Or is it?
say LEXICAL::<&Package::var>(); # Cannot invoke this object
# (REPR: Uninstantiable; Callable)
What happened to our { 42 }?
Hmm. Let's start from a clean slate and create &Package::var in a completely different way:
package Package { our sub var { 99 } }
say &Package::var(); # 99
say Package::<&var>(); # 99
Wow. Now, assuming those lines above and trying to add more:
my Package::<&var> = { 42 } # Compile-time error: Malformed my
That was to be expected given our previous attempt above. What about:
my &Package::var = { 42 } # Cannot modify an immutable Sub (&var)
Is it all making sense now? ;)
Spelunking the compiler code, checking the grammar
1 I spent a long time trying to work out what the deal really is before looking at the source code of the Rakudo compiler. This is a footnote covering my initial compiler spelunking. I hope to continue it tomorrow and turn this nanswer into an answer this weekend.
The good news is it's just P6 code -- most of Rakudo is written in P6.
The bad news is knowing where to look. You might see the doc directory and then the compiler overview. But then you'll notice the overview doc has barely been touched since 2010! Don't bother. Perhaps Andrew Shitov's "internals" posts will help orient you? Moving on...
In this case what I am interested in is understanding the precise nature of the Package::<&var> and &Package::var forms of syntax. When I type "syntax" into GH's repo search field the second file listed is the Perl 6 Grammar. Bingo.
Now comes the ugly news. The Perl 6 Grammar file is 6K LOC and looks super intimidating. But I find it all makes sense when I keep my cool.
Next, I'm wondering what to search for on the page. :: nets 600+ matches. Hmm. ::< is just 1, but it is in an error message. But in what? In token morename. Looking at that I can see it's likely not relevant. But the '::' near the start of the token is just the ticket. Searching the page for '::' yields 10 matches. The first 4 (from the start of the file) are more error messages. The next two are in the above morename token. 4 matches left.
The next one appears a quarter way thru token term:sym<name>. A "name". .oO ( Undeclared name: Package So maybe this is relevant? )
Next, token typename. A "typename". .oO ( Type 'Package' is not declared So maybe this is relevant too? )
token methodop. Definitely not relevant.
Finally token infix:sym<?? !!>. Nope.
There are no differences between Package::<&var> and &Package::var.
package Foo { our $var = "Bar" };
say $Foo::var === Foo::<$var>; # OUTPUT: «True␤»
Ditto for subs (of course):
package Foo { our &zape = { "Bar" } };
say &Foo::zape === Foo::<&zape>;# OUTPUT: «True␤»
What the documentation (somewhat confusingly) is trying to say is that package-scope variables can only be accessed if declared using our. There are two zapes, one of them has got lexical scope (subs get lexical scope by default), so you can't access that one. I have raised this issue in the doc repo and will try to fix it as soon as possible.

How can I pass a Swift array as an argument to a thread?

I'm trying to spawn a new thread to do some background processing, based on a String that I've broken down into an array of characters. Here's what my code looks like:
var testString : String = NSString(data:data!, encoding:NSUTF8StringEncoding)
var testStringArray : Array<Character> = []
for character in testString
{
if(!(self.isCharacterStrippable(character)))
{
testStringArray.append(character)
}
}
NSThread.detachNewThreadSelector("fillKeysFromArray:", toTarget: self, withObject: testStringArray)
I get a compiler error telling me that "Array does not conform to protocol AnyObject".
Short of writing an object wrapper for my array, or setting it as an instance variable (both of which seem like overkill), is there any way I can get this array passed through to the new thread?
Using Grand Central Dispatch is going to be much easier in the long run. You can run your function on a background thread with something like:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) {
[weak self] in // This is so that we don't create a reference cycle
self?.fillKeysFromArray(testStringArray);
return
}
You can read up on Grand Central Dispatch and all the nice things it provides when it comes to threading and concurrency in Apple's Concurrency Programming Guide.
The root cause is that detachNewThreadSelector can only accept a NSMutableArray for the withObject parameter. If you make testStringArray a variable of type NSMutableArray you can get rid of the compiler error message.
Having said that, you should seriously consider the advices from Bryan Chen and Mike S to switch to GCD.

How do I convert a Zip into an array in rust 0.8?

The docs seem to indicate that after zipping two iterators together, you can turn them into an array with .from_iterator(), but when I try to do this, rust reports:
std::iter::Zip<std::vec::VecIterator<,int>,std::vec::VecIterator<,int>>` does not implement any method in scope named `from_iterator`
Could someone please give working sample code for rust 0.8 that turns a Zip into an array?
That would be FromIterator::from_iterator(iterator).
The more commonly used interface for that is Iterator.collect (link is to master docs, but it's the same in 0.8 and 0.9), whereby you will call iterator.collect().
Rust 0.8 is dated, you should upgrade to 0.9. The following works in 0.9:
let a = ~[1,12,3,67];
let b = ~[56,74,13,2];
let c: ~[(&int,&int)] = a.iter().zip(b.iter()).collect();
println!("{:?}", c);
Result:
~[(&1, &56), (&12, &74), (&3, &13), (&67, &2)]

Resources