Monday, March 9, 2020

Self learn to write a File read program in Rust

cargo-test_debugging

Write a program to read a File in Rust

When I got this question first time, I don’t know where to start with this in Rust.
If this question was to write the same prgoram in C :

C is a school taught language and we know that C 's stdio has fopen, fclose ,fgets etc … because of that I wouldn’t have worried what/how fgets read or type conversion challenges are handled.

Here in Rust , I don’t which libraries/modules needs to imported
libraries are called crates in rust.
Some of the questions came to mind where

  1. what are all the standard libraries needed for this ?
  2. is there any method called ‘read’ in Rust ?
  3. how to get the file descriptor , is there any File Open ?

Looks like all these details are well documented in
std lib in rust

Finally I just started writing the program with whatever read method that I found somewhat relevant

  1 use std::fs::File;
  2 
  3 fn main() {
  4 
  5     let f = File::open("a.txt");
  6 
  7     match f.read() {
  8           Ok(x) => { println!("file contents = {}",x) },
  9           Err(e) => { println!("Error") },
 10     }
 11 }

Oops Error…
compiler complaints …

 error[E0599]: no method named `read` found for enum `std::result::Result<std::fs::File, std::io::Error>` in the current scope
 --> src/main.rs:7:13
  |
7 |     match f.read() {
  |             ^^^^ method not found in `std::result::Result<std::fs::File, std::io::Error>`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0599`.
error: could not compile `std_learning1`.

Ok. read method is not there in fs inmodule.
We will goahead search where is the read in rust lang documentation.

I used std::fs::read , but if we read through the documentation carefully , we will understand that this is for small files and that can be parsed to a string format type like SocketAddr.

enter image description here

9   |     match std::fs::read(f) {
    |                         ^ the trait `std::convert::AsRef<std::path::Path>` is not implemented for `std::result::Result<std::fs::File, std::io::Error>

This error actually gives a clue that our “f” file object is “std::result::Result<std::fs::File, std::io::Error>”

I know that I can handles the error types with just adding “?” to file open.

But still we haven’t got which read method to use . Again going to back to documentation and search - I found a read that reasonable choice which is std::io:: Read::read

enter image description here

(Note:wrongly highlighted above)

just brought std::io::Read trait alone to the program for now.

as the function signature says -
fn read(&mut self, buf: &mut [u8]) -> Result<usize >

 1 use std::fs::File;
 2 use std::io::Read;
 4 
 5 fn main()  {
 6 
 7     let mut f = File::open("a.txt")?;
 8     let mut buf = [0;30];
 9     let n =  f.read(&mut buf[..]);
 
14 
15     println!("{:?}",&buf[0..n]);
16 
18 }


mainly two errors

  | |
7  | |     let mut f = File::open("a.txt")?;
   | |                 ^^^^^^^^^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
8  | |     let mut buf = [0;30];
error[E0308]: mismatched types
  --> src/main.rs:15:29
   |
15 |     println!("{:?}",&buf[0..n]);
   |                             ^ expected integer, found enum `std::result::Result`
   |
   = note: expected type `{integer}`
              found enum `std::result::Result<usize, std::io::Error>`

error: aborting due to 2 previous errors

we need to give return type in the main() function as we used “?” in line 7 and also we need to return Ok(()) in the main

We need to add io::Result<()> as return type in the main function, so for that we would need to include std::io;

So code would looks something like below:

  1 use std::fs::File;
  2 use std::io::Read;
  3 
  4 use std::io;
  5 //use std::io::prelude::*;
  6 
  7 fn main() -> io::Result<()>  {
  8 
  9     let mut f = File::open("a.txt")?;
 10     let mut buf = [0;30];
 11     let n =  f.read(&mut buf[..])?;
  17     println!("{:?}",&buf[0..n]);
 18 
 19    Ok(())
 20 }



But the output is still bytes.

   Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `/home/naveen/rustprojects/mar2020/std_learning1/target/debug/std_learning1`
[84, 104, 105, 115, 32, 105, 115, 32, 102, 105, 114, 115, 116, 32, 82, 117, 115, 116, 32, 115, 116, 100, 32, 108, 105, 98, 114, 97, 114, 121]

We can convert the bytes to string type using below statements.


 println!("{:?}",String::from_utf8((&buf[0..n]).to_vec()).unwrap());

One you might have noticed is that we need to handle the buffer explicitly.

So let us look again for some other read method available.

The one I found interesting is BufRead Trait which is a type reader that handle internal buffer.

Let us search for what are all the methods implementing this.

enter image description here

But how it can be used or related to File struct.

We know that File implements Read trait.

enter image description here

BufReader implements Read
BufReader implements BufRead as well.
So we can go-ahead are use/create an instance of BufReader on a File object.

Once we convert File object to an instance of BufReader , we can use methods like
lines
read_lines
read_until
split

  1 use std::fs::File;
  2 //use std::io::Read;
  3 
  4 use std::io::{self,BufReader};
  5 
  6 //include io  prelude which import all important structs and implementation
  7 //in this case it import all supporting BufReader implementation ( eg :  //BufRead)  for File struct.
  9 
 10 
 11 use std::io::prelude::*;
 12 
 13 fn main() -> io::Result<()>  {
 14 
 15     let mut f = File::open("a.txt")?;
 16 //    let mut buf = [0;30];
 17 
 18     let buf = BufReader::new(f);
 19 
 20  //   let n =  f.read(&mut buf[..])?;
 21 
 22    for line in buf.lines(){
 23         println!("{:?}",line);
 24    }
 25 
 26 
 27    Ok(())
 28 }



Diagram might be not fully correct. But I am trying to picturize the File read program modules and important internals.

Some notes in the above snippet:

  1. include io::prelude which import all important structs and implementation. in this case it import all supporting BufReader implementation ( eg : BufRead) for File struct.

  2. commented some of the lines(not deleted) which we used prior version of the program to understand the difference.

Output :

Ok("This is first Rust std library learning program.")

if we do an unwrap(), we will get the line string itself.

Conclusion:
Hope this helps you to understand how different traits are connected together at least for Rust File read program and which std modules needs to be imported for it. This same module/trait analysis required when you are working with external crates. It is important reading through the crate documentation and understand which traits are matching your requirement and which are needs to be imported and ready to use for their methods.

Saturday, March 7, 2020

regex programs should be a must tool for a programmer

Rust Regex:

I haven't given much attention to pattern matching. but I think it should be must taught topic for every programming student. having said that,  we can get into the my example



we can get into the Rust regex crate https://crates.io/crates/regex
and https://docs.rs/regex/1.3.4/src/regex/lib.rs.html#1-785





Since Rust handles string pretty nicely, regex expression matching is quite easy even if for my native language - Malayalam

you can either create an Rust regex object with Regex::new(r"(മല)") or RegexSetBuilder::new(&[r"ജാവ"]).case_insensitive(true) .build()?;


if you really want to check each malayalam character , then you can use Regex::new(r"(p\{Malayalam}).unwrap()

For more detail how to use regex : 

https://www.regular-expressions.info/brackets.html

https://medium.com/factory-mind/regex-tutorial-a-simple-cheatsheet-by-examples-649dc1c3f285


Code details: regex malayalam search .

Thursday, February 20, 2020

gdb tips - PART1

gdb

Some gdb ( GNU debugger) tips

It is very important to understand the debugging tools and their different functionalities to hack the system level programs easily.

How to compile a program to debug in gdb.

  1. compile your C program with -g option

    $cc -g helloworld.c

  2. Open the executable in gdb
    $gdb a.out

  3. Run the program using below commands in gdb prompt using simply ‘r’.
    (gdb)run or (gdb)r

  4. Continue run from breakpoint using ‘c’
    (gdb)c

Setting Breakpoint in gdb.

1.Setting up breakpoint in a line number
$b 10
2. breakpoint setting up in an address
$b *0x7c00

(gdb) b *0x7c00
Breakpoint 1 at 0x7c00
(gdb) c
Continuing.
Thread 1 hit Breakpoint 1, 0x00007c00 in ?? ()

3.Setting up breakpoint in a function
$b main

Switch to tui mode using ctrl+x 2

you can switch to tui ( text gui mode) mode using ctrl+x 2
to view the source file in the same screen.
tui mode

you can ctrl+x 1 to see registers values

ctrl+x n to come back to gdb prompt.

stepping through line and instruction

$si \ steps through instruction
$s \ source level step through next line

Next step over through line

$n
$next

gdb_steps_through_source

Printing variables

$p foo//print the value of foo
$p car // print the value of car variable

$p/x addr //printing hexa decimal values

information about frames and registers

Current function stack frame details can be displayed using the command ‘f’ or ‘frame’
$f
$frame

enter image description here

The registers details or values can be seen using the command ’ info r’

info r
enter image description here

backtrace of call stacks

How can we backtrace all call stacks in gdb?!. This would be very useful command especially when you are debugging big projects source codes.

$bt
shows the backtrace of all call stacks so far.

enter image description here

You can switch to different frames using below command

$f 1
to switch to the first frame
f 5 switch to 5th frame etc

Some of the helpful commands when you are in a function

$info locals
shows the local variable in a function

$info args
shows arguments of the function

getting help on gdb

(gdb) help

List of classes of commands:

aliases – Aliases of other commands
breakpoints – Making program stop at certain points
data – Examining data
files – Specifying and examining files
internals – Maintenance commands
obscure – Obscure features
running – Running the program

(gdb)h breakpoints //provide help on breakpoints

PART 2 -
https://naveendavisv.blogspot.com/2020/04/gdb-debugging-part-2.html