Showing posts with label rust lang. Show all posts
Showing posts with label rust lang. Show all posts

Wednesday, May 4, 2022

Rust bare metal programming

If you are a Rust enthusiast and looking for something to read and try. I would recommend https://os.phil-opp.com/minimal-rust-kernel 

The blogs explains how to build OS in rust.

You can have a start over and build OS if you missed to build it in your college days . Blog starts from OS bigbang with a compiler story telling way. A basic understanding of Rust would be a prerequisite , but the blog explains the builing steps in Rust compiler driven programming method. So it would be good learning experience in embedded Rust programming .

Friday, April 15, 2022

Type-Driven API Design in Rust by Will Crichton

I think that below video is one of the must seen video before reading any source code in Rust language. I was confused with this Trait futures::future::FutureExt when I read through some of the async programs. It is very common that people extending the traits and types in Rust. The "ext" traits were very hard to digest for me.

After seeing this video, these APIs makes more sense.



.

Saturday, March 19, 2022

Rust- Generic type T is super set of &T and &mut T

T includes both & T and &mut T

I had a misconception in Rustlang that the generic types &T and &mut T are  not subset of generic type  T. It turned out to be totally wrong.  Generic Type T includes both &T and &mut T. It is quite easy to get believed that  &T and &mut T are not part of T .

but actually it is as below






I think below is the proper definition of reference types in Rust - &mut T - is the exclusive reference to the value and &T is the shared reference to the value.

When you have exclusive reference(&mut T)  to a value, you can mutate it and guarantees no other references for it at that point of time.


Example:




In the example program the function 'print' has type with trait debug and it is a generic type T.
We are able to pass the &v, &mut v and v to the print function. Meaning the  type check  T  is able to accept the  exclusive reference and shared references.


Reference:






 

 

Saturday, February 5, 2022

May be Rust can speed Django projects ?

I was trying to plugin pyo3 build Rust '.so' files(dynamic libraries) to Django. Looks like its not that difficult, we can copy and paste the file to Django folder. Once the file avaliable in Django folder , it will allow us to import the Rust dynamic library functions to your Django views.

Step1: create the Rust program as library using pyo3 and build the file using cargo build. Remember to put the crate-type "cdylib". I used manual build and copy .so file . Remember to keep the python module name and .so file name as same. https://pyo3.rs/v0.15.1/
Step2 Create your normal Django helloworld App
Step3 Copy the .so file to your Django project folder and import it in your views.py file, then you should be able to run django server .

Tuesday, December 29, 2020

Rat-Maze problem - Yew app - PART2

Rust Yew app:


Last week I wrote about the  Rat-Maze problem - Yew app.

Writing code  in Rust programming language is always fun and a learning.So thought of making some enhancements to the yew app 

1. add colors to the cells

2. after solving the path, change the color of the cells in the path. ..etc


This gave an opportunity to work with CSS and Yew. I think still there is no full support for CSS from Yew as you might have seen in React. But I was managed to change the color with "class" property in CSS.

index.css


.game-celluley {
display: inline-block;
width: 20px;
height: 20px;
border: 1px solid #ccc;
background-color: yellow;
text-align: center;

}


.game-celluleg {
display: inline-block;
width: 20px;
height: 20px;
border: 1px solid #ccc;
background-color: green;
text-align: center;

}



lib.rs

html!{
<div key=x class=format!("game-cellule{}",cell_color)>{ cell.value } </div>
}


Source Code:

github- Yew app


How to compile and run:




output:




Saturday, July 25, 2020

Why tokio tasks are run-time dependent ?


Tokio and async-std 


I was going through two major crates for async programming in Rust. I believe Tokio and async-std are predominant crates now available for async programming. 

But when I tried to run tokio tasks with async-std run-time, but default it won't allow. I need to change run-time as tokio using #[tokio::main] that's not nice.

But when  I tried to run async-std tasks with tokio run-time, I am able to run.  Looks like async-std is more compatible with other Rust eco-systems.



error:
thread 'main' panicked at 'must be called from the context of Tokio runtime configured with either `basic_scheduler` or `threaded_scheduler


There would be libraries/crates to make it happen, but I think by default this should be available.


Friday, July 24, 2020

Where is the infinite loop in the below Rust Program ?

Have you ever wonder how the below  TcpListener Code run infinitely looking for new connections/clients.

Code:
When you run this below program with a Rust compiler or Cargo run, you will see that the program is not ending. How ?


As you noticed , the for loop doesn't have a explicit condition to exit. As far as the Iterator can return values, the "for loop" construct  execute the  statements inside the body. The Iterators can behave like  an infinite loop.But can return "None"(which can be used to exit from "for") , or can return Some values from next method .

Read more to understand how "for loop"  decompose in Rust - https://doc.rust-lang.org/reference/expressions/loop-expr.html

Ok..we understood that there is something called Iterator which can yield for values infinite.

But where is the Iterator here ?

When you look at the TcpListener , it is just a struct. But it has one particular method which implements Iterator trait. 
The connections can be accepted from TcpListener through a  struct called  std::net::Incoming  which is an Iterator.It is hidden(abstracted) behind the method incoming  in this case. As I said earlier  Iterators can yield and ask for values infinite times.





Iterator Trait is implemented on the struct "Incoming"



As you noticed the next method on the Iterator is not going to end. It just keep iterate as far as we are calling incoming method.




Incoming struct accepts connections of TcpListener:



Incoming implementing Iterator trait:




Saturday, July 18, 2020

compiled a Rust program for Wasm target without wasmbind-gen

It was not that hard to write a function and build for wasm target. I was using the #![no_std] without knowing much on it.The Rust compiler was just guiding through errors to fill the code.
I did not use the wasmbind-gen. But I did use wee_alloc

The program is below:

Note: just comment each line and see the error message compiler is giving to you.

Sunday, June 14, 2020

Pointers in Rust

pointers in Rust

Pointers

Pointers - what is the definition of pointer?
As per wikipedia - In computer science, a pointer is a programming language object that stores a memory address. This can be that of another value located in computer memory, or in some cases, that of memory-mapped computer hardware.

https://en.wikipedia.org/wiki/Pointer_(computer_programming)

Historically pointers become a tough topic for students, even though the definition looks simple. The loop holes behind the pointers make programmers life hard with them.
If I write a program in C with pointers, its end up in “Segmentation Fault”

Pointers in Rust

I have seen Computer languages started introducing smart pointers recently for safety . So since Rust is new language, Rust has really smart pointers .But it may looks a bit more syntax around them. Once you know the specification of them its quite safe to use them.

1.Raw pointers in Rust

Let starts with dirty one(it’s not dirty,just not smart). Raw, unsafe pointers, *const T, and *mut T.
As name suggests they are raw or unsafe pointers. You can assign a raw address to a raw pointer.

These pointers are very useful when you need to assign some port address to a variable in Rust.

fn main() {
    let p: *mut i32;
    p = 0x10 as *mut i32 ;
    
}

But if you try to deference and assign a value , it throws error in Rust. Rust error shows you why it is risky…

```rust_errors
|
5 |     *p= 10;
  |     ^^^^^^ dereference of raw pointer
  |
  = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior

But if you explicitly tell the compiler that I am sure this is safe to use and so am tagging this snippet under “unsafe” , the compiler compile the code successfully
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=792e09bd5485af4ceca96e59ba80848b

Read more: https://doc.rust-lang.org/std/primitive.pointer.html

2.references - &T

References are generally called as pointers. In Rust,&T type a ‘reference’. So rather than calling this as pointers ,Rust consider this as a separate Type.
&T means reference to a type value T. You can dereference it with * operator.

fn main() {
    let a = 10;
    let p = &a;
    println!("{}",*p);
    
}

3.References - &mut T

Since it is a Type , &T and &mut T are different. The first one is simple reference and we can access the value that points ,but can’t modify the value.
You can modify the value with &mut T reference
Rust treats different variation(mutable or immutable) of references as different types
eg:

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=776367d50a05cc1af60c90b31d8ac0d7

But mutable references have one big restriction: you can have only one mutable reference to a particular piece of data in a particular scope

The Rules of References

  • At any given time, you can have either one mutable reference or any number of immutable references.
  • References must always be valid.
fn main() {

    let mut a = 10;
    
    let p1 = &mut a;
    
    *p1 = 11;
   
    let p2 = &a;
    
    println!("{},{}",*p1,*p2)
    
}

Above code won’t compile with error message

rust_errors
error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable
  --> src/main.rs:9:14
   |
5  |     let p1 = &mut a;
   |              ------ mutable borrow occurs here
...
9  |     let p2 = &a;
   |              ^^ immutable borrow occurs here
10 |     
11 |     println!("{},{}",*p1,*p2)
   |                      --- mutable borrow later used here

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=1a975610b3d5d380e57dea9cc1c286b4

If you use 2 mutable reference, the program won’t compile successfully.

fn main() {

    let mut a = 10;
    
    let p1 = &mut a;
    
    *p1 = 11;
   
    let p2 = &mut a;
    
    println!("{},{}",*p1,*p2)
    
}

error message is below, hope that is self explanatory.

error[E0499]: cannot borrow `a` as mutable more than once at a time
  --> src/main.rs:9:14
   |
5  |     let p1 = &mut a;
   |              ------ first mutable borrow occurs here

9  |     let p2 = &mut a;
   |              ^^^^^^ second mutable borrow occurs here
10 |     
11 |     println!("{},{}",*p1,*p2)
   |                      --- first borrow later used here

4.Box - A pointer type for heap allocation.

A Box allows heap allocations similar to “malloc” in C programming.
You can mutate the heap value using the keyword ‘mut’ in front of the variables.

fn main() {

   let mut heap_pointer = Box::new(10);
    *heap_pointer += 1;
   println!("{}",*heap_pointer);
   
}

The above code gives you the output as 11.

 fn main() {

    let mut heap_pointer = Box::new(10);
    
    let heap_pointer2 = &mut heap_pointer ;

   // let heap_pointer3 = &mut heap_pointer;
   // heap_pointer2 = *heap_pointer2 + 1;
   
   match *heap_pointer {
       x => { println!("{}",x+34)},
   }
    
 //   let heap_pointer3 = &mut heap_pointer;
  //   *heap_pointer2 = *heap_pointer + 1;
    println!("{}",*heap_pointer);
 //   println!("{}",x);
 //   println!("{}",*heap_pointer2);
    
}

How to get the value from Box:
You can use * operator to dereference the address.

#![allow(unused)]
fn main() {
let x = Box::new(String::from("Hello"));
println!("{}",*x);
}

Using Raw pointer -

You have to use “unsafe” block for creating a raw pointer for a boxed value.

#![allow(unused)]
fn main() {
let x = Box::new(String::from("Hello"));

//taking a raw pointer
let ptr = Box::into_raw(x);

let x = unsafe { Box::from_raw(ptr) };

println!("{}",x);
}

5.Rc - Reference Counted

We are getting into the world of smart pointers. Reference counting is not a new concept, it is there in Python. If you see below program in python tutor.

a = [12,3,4]
b = a
c = b

a = 0
b= 1
c =2

The python visualizer shows you that the object (list object) remains in the memory until all the references to the object get removed.
Note: when we assign a =0 , the value assigned to ‘a’ become zero .

http://www.pythontutor.com/visualize.html#code=a %3D [12,3,4] b %3D a c %3D b a %3D 0 b%3D 1 c %3D2 &cumulative=false&curInstr=6&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=[]&textReferences=false

In Rust ‘Rc’ is a single-threaded reference-counting pointer. ‘Rc’ stands for ‘Reference Counted’.

Below program creates an Rc reference and get the value using * operator (dereferencing )



fn main() {
use std::rc::Rc;

let x = Rc::new("hello".to_owned());

let y = Rc::clone(&x);
let z = Rc::clone(&x);

println!("{}",*x);
println!("{}",*y);

println!("{}",Rc::strong_count(&y));

}

Below Rust program generates number of references from a heap allocated memory . You might have noticed that we drop ‘x’ in the middle. But still we have 2 Rc references. If you have multiple normal reference &T for a heap allocation, compiler won’t allow you to drop the owned reference.

fn main() {
use std::rc::Rc;
let x = Rc::new("hello".to_owned());

let y = Rc::clone(&x);
let z = Rc::clone(&x);

drop(x);

println!("{}",Rc::strong_count(&x));
}

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=12748f50761fb40ae36bead095f64a65

6.Recell

A mutable memory location with dynamically checked borrow rules.
Refcell gives you a mutable reference for an immutable instance.
if you do two or more ‘borrow_mut’ in the same scope, the program panic in the run time.

But below program , we are passing borrow_mut to the function, so it is not in the same scope.

#![allow(unused)]
use std::cell::RefCell;
use std::cell::*;

fn main() {

//c is not declared as mutable.
let  c = RefCell::new(5);

//but we are creating a mutable borrow and passing to the function.
fun (c.borrow_mut());
fun (c.borrow_mut());

println!("{}",c.into_inner());

}

//fun function receive a mutable cell
fn fun(mut x:RefMut<i32>){
    
// changing the value inside the cell, even though cell 'c' was not declared as mutable.
    *x = 3;
}

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=02b0ed5116b1abada7160c6ee0fbb436

You can wrap RefCell(not declared mutable) with Rc and mutate the object with Rc reference . If you are using immutable Rc for another objects other than RefCell, it won’t allow to mutate .

#![
allow(unused)]
use std::cell::RefCell;
use std::cell::*;
use std::rc::Rc;
fn main() {

//c is not declared as mutable.
let  c = RefCell::new(5);

//wrap Refcell with Rc

let r = Rc::new(&c);
//wrap Refcell with Rc, even though r1 is not mutable , we use it mutating cell value
let r1 = Rc::clone(&r);

let r2 = Rc::clone(&r);



//but we are creating a mutable borrow and passing to the function.
fun (r1.borrow_mut());

//let d = c.borrow();
fun( r2.borrow_mut());


println!("{}",c.into_inner());

}

//fun function receive a mutable cell
fn fun(mut x:RefMut<i32>){
    
   // changing the value inside the cell, even though cell 'c' was not declared as mutable.
    *x += 3;
} 

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=75d5ccbb4c6c9d62d5df4a92a8f7137e

Conclusion

You might need to try these pointers and write some small code snippets and see to understand how Rust compiler behaves on these pointers. The smart pointers really safe to use in Rust. You can avoid bugs that are hard to debug like race condition, double free,free after use etc…

This is just my notes and experiments with Rust pointers.There could be some missing or incorrect information. Happy to correct it !!

Monday, June 8, 2020

Rust - Test driven program development

Cargo supports test driven developmentin Rust programming. There are lot of options comes with cargo test command.


Writing test functions with #[test] in your program makes the code more readable as well as its makes easy to understand the functionalities of the program for others . I have seen that even I can start running the complex projects and see outputs of some of the modules or functions in those projects.
code repository - https://github.com/davnav/parser_try.git

Tuesday, April 7, 2020

Understanding hashing and applications of hashing - Rust

Rust hashing

Rust Hashing

I am seeing hashing everywhere like block chain, load balancing ,Cryptographic hash functions,Password Verification,key-value pair data structures in programming languages.

So thought of checking how to do hashing Rust and looks like its pretty easy to do in Rust as well.

#![allow(unused)]
fn main() {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};

#[derive(Hash)]
struct Person {
    id: u32,
    name: String,
    phone: u64,
}

let person1 = Person {
    id: 5,
    name: "Janet".to_string(),
    phone: 555_666_7777,
};
let person2 = Person {
    id: 5,
    name: "Bob".to_string(),
    phone: 555_666_7777,
};

assert!(calculate_hash(&person1) != calculate_hash(&person2));

fn calculate_hash<T: Hash>(t: &T) -> u64 {
    let mut s = DefaultHasher::new();
    t.hash(&mut s);
    println!("{:?}",s.finish());
    s.finish()
}
}

hashing code example in rust

Sunday, April 5, 2020

How do C and Rust programs differs in memory safety -Example 3

memory-safety 2

Memory safety example 3

Dangling Pointers in C

If you try to free a pointer and then try to access it, the C compiler won’t complains it. But you will be come to know that bug in the run time.

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 
  4 int main(){
  5 
  6   int* ptr = (int*) malloc(2*sizeof(int));
  7 
  8   *ptr= 10;
  9    ptr++;
 10   *ptr = 20;
 11 
 12   free(ptr);
 13 
 14   printf("pointer values are %d",*ptr);
 15 
 16 }

This is the runtime error: I know that you hate runt ime errors . But that is what happens when we try to access pointers that are already freed. We won’t any clue until we encounter this error in C.

======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f97ccd4e7e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x8037a)[0x7f97ccd5737a]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7f97ccd5b53c]
./a.out[0x4005f1]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f97cccf7830]
./a.out[0x4004e9]
======= Memory map: ========
00400000-00401000 r-xp 00000000 08:06 6554103                            /home/naveen/rustprojects/mar2020/C_Rust_$omp/a.out
00600000-00601000 r--p 00000000 08:06 6554103                            /home/naveen/rustprojects/mar2020/C_Rust_$omp/a.out
00601000-00602000 rw-p 00001000 08:06 6554103                            /home/naveen/rustprojects/mar2020/C_Rust_$omp/a.out
020fa000-0211b000 rw-p 00000000 00:00 0                                  [heap]
7f97c8000000-7f97c8021000 rw-p 00000000 00:00 0 

But Rust save us here.

Rust:

 1 fn main() {
  2 
  3     let a = vec!(10,11,14); //  vector 'a' is initialized.
  4     let p = &a ; // reference to the value in 'a'.
  5 
  6     drop(a);   //free the memory allocated for 'a'
  7     
  8     //we can try to access  values in 'a' through reference 'p'
  9     println!(" values in a = {:?}",*p);
 10 }
                


The famous error comes in compile time itself

Rust complains “borrow later used here” means we dropped the value and but still trying to access it.

borrow means: when we create a reference to the value, we are just borrowing the value.In this case the ownership of the value still remains with ‘a’.

So when we dropped the value ‘a’. The borrowed reference is also become invalid and we can’t use it later point in the program.

error[E0505]: cannot move out of `a` because it is borrowed
  --> src/main.rs:9:10
   |
7  |     let p = &a ; // reference to the value in 'a'.
   |             -- borrow of `a` occurs here
8  |     
9  |     drop(a);   //free the memory allocated for 'a'
   |          ^ move out of `a` occurs here
...
12 |     println!(" values in a = {:?}",*p);
   |                                    -- borrow later used here

error: aborting due to previous error

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

To learn more, run the command again with --verbose.

Wednesday, April 1, 2020

How do C and Rust programs differs in memory safety - Example 2

memory-safety 2

Memory safety example 2

This is one of the well known problem in C programming language - Array Overflow.
C compiler really won’t care the boundary of arrays , you can even point to the value beyond array length using a pointer as if you are traversing through it.

C Program

  1 
  2 int main(){
  3 
  4     int a[3] =  {1,2,3 };
  5     char c = 'a';
  6     char d = 'b';
  //pointer to the array, 
  //usually array itself is a pointer
  // to the first address of the array 
  7     printf("array = %d " , *a );
  8     printf("array = %d " , *(a+1) );
  9     printf("array = %d " , *(a+2) );
 10     
 11     
 12     //memory overflow , we are trying to access beyond array's length
 13     //but compiling is not complaining
 14 
 15     printf("array = %d " , *(a+3) );
 16     printf("array = %d " , a[5] );
 17 
 18 }

Output is

array = 1 array = 2 array = 3 array = 0 array = 32764 

We will see how Rust program restricts this vulnerability .

Rust Program

trying to create pointer and dereferencing it below, but compiler catches it

 1 
  2 fn main() {
  3 
  4     let a = [1,2,4];
  5 
  6     let p = &a;
  7     
  8     println!("array ={:?}",*p+1);
  9 
 10 }

error is

--> src/main.rs:8:31
  |
8 |     println!("array ={:?}",*(p+1)); 
  |                              -^- {integer}
  |                              |
  |                              &[{integer}; 3]


if you try to access it through index, as a[3] , below is the error


error: this operation will panic at runtime
 --> src/main.rs:8:26
  |
8 |    println!("array = {}",a[3]);
  |                          ^^^^ index out of bounds: the len is 3 but the index is 3
  |
  = note: `#[deny(unconditional_panic)]` on by default

Tuesday, March 31, 2020

How do C and Rust programs differs in memory-safety - example 1

ownership

How do C and Rust differs in memory safety ? example 1

Looks at the below program, how crazy the ‘main’ function snatches the password from the function ‘assign’. We only return the pointer to the ‘user’, but ‘main’ gets ‘password’ from it.

It took some trials for me to find number nine(9) as the offset (byte) ( difference between the “user” and " password" address ) .

C code

 l 1 
  2 #include<stdlib.h>
  3 
  4 char* assign(){
  5 
  6     char password = 'a'; //password stored here
  7     char b[3] = "ab";
  8 
  9     int* username = &b;
 10 
 11     return username;
 12 }
 13 
 14 
 15 
 16 int main(){
 17 
 18   char* user = NULL;
 19 
 20   user  = assign();
 
 21   // you can just do some address offseting with "-" or "+" to get the "password" field
 
 22   printf("%c\n",*(user - 9));
 23 
 24 }

Output is ‘a’ which is the password here.

a

Rust code:

In rust it is very difficult or not even possible ( I don’t know a method) without unsafe code to offset the address and get another variables or string slices(literals).

Interestingly “password” and “username” variables are referring to the program memory itself ( not stack or heap ) as &str ( string slice) hard coding in program binary.

We can try with "unsafe " code to do some manipulation on the username address to snatch the “password”.

But if you are making sure that no ‘unsafe’ code in your program , you can avoid this scenario in rust or you will catch those scenario on compile time itself ( that is AWESOME! )

 2 fn assign() -> &'static str{
  3 
  4     let password = "q";
  5     let username = "asdasd";
  6 
  7     let q = username;
  8 
  9 
 10     println!("pointer = {:p}, {:p}",password,q);
 11 
 12     q
 13 
 14 }
 15 
 16 
 17 fn main() {
 18 
 19   let p:&str = assign();
 20 
 21   let ptr: *const u8 = p.as_ptr();
 22 
   /// you really need to write unsafe code and
   /// do some trick to get offset address of the 
   /// "password" here. The + , - operators won't work with address in rust.
   
 23   unsafe {
 24           println!("Hello, world! : {}",*ptr.sub(1) as char);
 25   }
 26 
 27 }

          

Output is

pointer = 0x5638e3aa3d70, 0x5638e3aa3d71
Hello, world! : q

Sunday, March 29, 2020

Rust Traits Must know points

Reading and understanding Traits is a pre-requisite before starting to read any code base in Rust.

Most of the scenarios and examples are mentioned here,

https://doc.rust-lang.org/1.8.0/book/traits.html

Tuesday, March 24, 2020

Rust iterator types

I was  reading this .. honestly I lost in between.. https://blog.jcoglan.com/2019/04/22/generic-returns-in-rust/

Understanding traits and type bounds  are hard in rust , amazing fact is that  Rust is doing this with zero cost.

Wednesday, March 18, 2020

Passing function as parameter in Rust

Passing function as argument in Rust

Passing function type check in Rust

Passing a function to another function is not a new thing in programming. We usually pass the address of the function( in C like languages &function name ).
but do we ensure that passed function performing the intended functionality or at least the parameter and return types are matching with what we intended to pass.

Rust asks passed function signature

Rust explicitly ask for the type of the pass function signature . If it’s not matching the rust program won’t compile.
that means - no one can inject anonymous functions to our function for some extend.

Rust passed function

In the below example , you would notice an extra type in the function signature. Anything in ‘’<>" are generic type in Rust. But what is that generic type means ?
If you don't know the type of the function parameter, you can specify it as generic.
It represent the passed function or closure type, that will be declared in the “where” clause.
P is a function type with signature Fn(i32) -> bool means it a closure or function which can accept an integer parameter and return a bool type value.
fn foo(x:i32,mult:P) -> i32
where P: Fn(i32) -> bool
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=b1a66f49cc31c9176d894ddd42c4422b
from the main function we call foo as below
foo(220,mult1); which is a valid call because the ‘‘mult1’’ function signature matches with generic type
///foo function definition - it has 2 parameter 
/// an integer value and a passed function
///return type of the function is integer
fn foo(x:i32,mult:P) -> i32
    /// passed function type  
    where P: Fn(i32) -> bool {
  
    ///calling the passed function and getting the return value
    let y = mult(x);
    
    ///some calculation around based on the value 'y'
    if y {
        x
    }else{
        x - 1
    }
}
///the signature of this function matches with foo's passed function signature 'P'
fn mult1(x:i32) -> bool {
    x> 32
}
///the signature of this function not matches with foo's passed function signature 'P'
///as it return integer
fn mult2(x:i32) -> i32{
  x
}

fn main() {
    ///call to foo with passed function 'mult1'
    let q = foo(220,mult1);
    println!("Hello, world! = {}",q);   
}
When I change the same program to call foo with passed function as mult2,
foo(220,mult2);
got the below error message while compiling
error[E0271]: type mismatch resolving ` i32 {mult2} as std::ops::FnOnce<(i32,)>>::Output == bool`
  --> src/main.rs:30:13
   |
2  | fn foo(x:i32,mult:P) -> i32
   |    ---
3  |  
4  |   where P: Fn(i32) -> bool {
   |                       ---- required by this bound in `foo`
...
30 |     let q = foo(220,mult2);
   |             ^^^ expected `bool`, found `i32`

error: aborting due to previous error

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

To learn more, run the command again with --verbose.
the error clearly states below, which is awesome!!
where P: Fn(i32) -> bool {
   |                       ---- required by this bound in `foo`

Saturday, March 14, 2020

How do we make a C program call Rust program

C to Rust.md

Internals of C program call to rust program call

One of the main strength of Rust programming language is that it can easily inter-operate with other programming languages.

But as we know Rust is very very strongly typed language. When you are planning Rust to use some of the C libraries , the C type representation attributes help us .

#[repr( C )]

There are some difference in the type representation for C type corresponding rust type.

We can go-ahead and check what is the size of the below struct
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=7392513792a8d390ce4756a6a8a0ed15

use std::mem;
#[repr(C)]
struct FieldStruct {
    first: u8,
    second: u16,
    third: u8
}

// The size of the first field is 1, so add 1 to the size. Size is 1.
// The alignment of the second field is 2, so add 1 to the size for padding. Size is 2.
// The size of the second field is 2, so add 2 to the size. Size is 4.
// The alignment of the third field is 1, so add 0 to the size for padding. Size is 4.
// The size of the third field is 1, so add 1 to the size. Size is 5.
// Finally, the alignment of the struct is 2 (because the largest alignment amongst its
// fields is 2), so add 1 to the size for padding. Size is 6.
assert_eq!(6, mem::size_of::<FieldStruct>());
}

But if you remove #[repr( c )] , the struct size becomes 4.

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=f1ad5c57ae7e771ca505058784580a1e

#![allow(unused)]
fn main() {
use std::mem;
struct FieldStruct {
    first: u8,
    second: u16,
    third: u8
}
assert_eq!(6, mem::size_of::<FieldStruct>());
}

How to use a Rust function in C program.

I referred the blog for Sergey Potapov for the details.

In this below program, you would see the function print_hello_from_rust defined with extern keyword and [no_mangle] attribute.
[no_mangle] makes the compiler ignores the unknown symbols and it knows this function is going to get called from other languages.
extern keyword makes the function outside of the our library.

std::ffi::CStr. Representation of a borrowed C string. This type represents a borrowed reference to a nul-terminated array of bytes. It can be constructed safely from a &[ u8 ] slice, or unsafely from a raw *const c_char

In this example we are using *const c_char , but what is c_char ?!

c_char is coming from the standard library ‘os’ module and it is Equivalent to C’s char type.C’s char type is completely unlike Rust’s char type; while Rust’s type represents a unicode scalar value, C’s char type is just an ordinary integer. This type will always be either i8 or u8, as the type is defined as being one byte long

reference : c_char

then why *const in front of it ?

*const are called Raw pointers in Rust.Sometimes, when writing certain kinds of libraries, you’ll need to get around Rust’s safety guarantees for some reason. In this case, you can use raw pointers to implement your library, while exposing a safe interface for your users. Ref: Raw pointers

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=40d05db968f82125fb7660e67710ecff

use std::ffi::{CString,CStr};
use std::os::raw::{c_char,c_int};

#[repr(C)]
pub struct Point{
    x: c_int,
    y: c_int,
}

impl Point {

    fn new(x:c_int,y:c_int) -> Point{
//          println!("Creating a Point with x = {},y = {}",x,y);
          Point {x: x,y: y }

    }
}
#[no_mangle]
pub extern fn create_point(x:c_int,y:c_int) -> *mut Point{

        Box::into_raw(Box::new(Point::new(x,y)))
}
#[no_mangle]
pub extern fn print_hello_from_rust(data: *const c_char ){

    unsafe{
          let c_str =       CStr::from_ptr(data);
          println!("hello from rust {:?}",c_str.to_str().unwrap());
    }
}

You can build the rust program with cargo

cargo new whatland -- lib
cd whatland

edit the lib.rs file with above code.

also make sure that your cargo file has

 [lib]
 name = "whatland"
 crate-type = ["staticlib","cdylib"]

cdylib helps - A dynamic system library creation. This is used when compiling a dynamic library to be loaded from another language. This output type will create *.so files on Linux, *.dylib files on macOS, and *.dll files on Windows.

cargo build --release

C program would need to compile with linking the .so file generated.

I am not detailing the C program compilation, but it detailed in the blogpost: https://www.greyblake.com/blog/2017-08-10-exposing-rust-library-to-c/

You would need to use,

gcc -o ./examples/hello ./examples/hello.c -Isrc  -L. -l:target/release/libwhatlang.so

Passing String parameter from C to Rust function.

We can use the trick of accepting the string as a Raw pointer using *const c_char
In order to print that bytes into a valid string slice in Rust, first we need to convert that to CStr - Representation of a borrowed C string.

then we can convert that to Str ( rust string slice) using c_str.to_str().unwrap()

How to use a C struct in Rust program

I believe , Its always recommended to use #[repr©] when working with C structs, enums because it makes alignment https://doc.rust-lang.org/reference/type-layout.html#the-c-representation

#[repr(C)]
pub struct Point{
   x: c_int,
   y: c_int,
  
  //    x:u8, -- if you are using u8, compilier throws error,
  //    y:u8,    stating "expected `u8`, found `i32'"
  }

We implemented a method new in the rust program so that we can use in the Point struct instance creation.

impl Point {

  fn new(x:c_int,y:c_int) -> Point{

 Point {x: x,y: y }
 }
}

Next in this example we have a export function which will be called from C program to creating Point Struct. For creating any object, we need to memory. In Rust we know that we can allocate heap memory through Box::new.

But we need to return a raw pointer to the C program, which can be done through Box::into_raw which Consumes the Box, returning a wrapped raw pointer.

 23 #[no_mangle]
 24 pub extern fn create_point(x:c_int,y:c_int) -> *mut Point{
 25 
 26         Box::into_raw(Box::new(Point::new(x,y)))
 27 }

C program can now just call the Rust function to create struct.

We need to have our C program included with struct and create function declaration.
header file whatland.h

  1 void print_hello_from_rust();
  2 
  3 typedef struct Point{
  4             int x,y;
  5 }Point;
  6 
  7 Point* create_point(int x, int y);
  

Now we can just call it in our main function in C

 11  Point* p1 = create_point(10,20);
 12     printf("Point={%d},{%d}",p1 -> x,p1 -> y);

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 .