Introduction to Rust programming language



For a long time, we are writing highly efficient applications/algorithms in C/C++.  C/C++ is always served the purpose and when it comes to speed and efficiency no other programming language is close to C/C++.
But at the same time, it requires high skills and experience for designing and development in C/C++. poorly designed applications always suffer when they come into the maintenance phase.

Memory safety has always been an issue for large scale C/C++ applications. People started using other high-level programming languages where speed/efficiency and high memory footprint are not only the prime requirement.
Combination of C/C++ with other high-level languages is also the trend now, core processing is managed by the C/C++ modules with non-critical modules are implemented in other high-level languages. 
This mix and match are widely accepted but these techniques suffer from poor support for C/C++ as these high level-languages are never designed for this purpose. For the web development, mobile application development, analytics, machine learning etc, a lot of good things are happening. But for system programming still, We can not see many new things.

Finally,  Mozilla research lab came with an entirely new open-source cross-platform language "Rust". Rust breaks down these barriers by eliminating the old pitfalls and providing a friendly, polished set of tools to help you along the way. Programmers who need lower-level control can do so with Rust, without taking on the risk of crashes or security holes. the language is designed to guide you naturally towards reliable code that is efficient in terms of speed and memory usage.

From Rust website (https://www.rust-lang.org)

Rust is a systems programming language that runs blazingly fast, prevents segfaults, and guarantees thread safety

Key features 
  • zero-cost abstractions
  • move semantics
  • guaranteed memory safety
  • threads without data races
  • type inference
  • minimal runtime
  • efficient C bindings

Let us walk through the few highlights

Variable Mutability

fn main() {
    let x = 5;
    println!("The value of x is: {}", x);
    x = 6;
    println!("The value of x is: {}", x);
}

See the above program and assume if it is written in C/C++. We can say this is a valid program and outputs 5 and 6 on the console. 

but if we write into rust and compile, check what happens,

error[E0384]: cannot assign twice to immutable variable `x`
 --> src/main.rs:4:5
  |
2 |     let x = 5;
  |         - first assignment to `x`
3 |     println!("The value of x is: {}", x);
4 |     x = 6;
  |     ^^^^^ cannot assign twice to immutable variable

By default Rust variables are immutable. This way Rust gives you the advantage of the safety and easy concurrency. However, you still have the option to make your variables mutable.

Rust has the mut keyword to make a variable mutable.

fn main() {
    let mut x = 5;
    println!("The value of x is: {}", x);
    x = 6;
    println!("The value of x is: {}", x);
}



If we compile now


$ cargo run
   Compiling variables v0.1.0 (file:///projects/variables)
    Finished dev [unoptimized + debuginfo] target(s) in 0.30 secs
     Running `target/debug/variables`
The value of x is: 5
The value of x is: 6

Note* mut and constant are not same. a constant variable always refers to a constant expression. It can not have an expression that has variables and can compute different values at runtime.


Ownership

Each value in Rust has a variable that’s called its owner.

fn main() {
    let s = String::from("hello");  // s comes into scope
    takes_ownership(s);             // s's value moves into the function 
println!("{}", some_string);    // It will not compile because s is no longer valid here
}

fn takes_ownership(some_string: String) { // some_string comes into scope
    println!("{}", some_string);
} // Here, some_string goes out of scope and `drop` is called. The backing memory is freed.


There can only be one owner at a time of a value.

let s1 = String::from("hello");
let s2 = s1;
println!("{}, world!", s1);

Above code compiles to errors

error[E0382]: use of moved value: `s1`
 --> src/main.rs:5:28
  |
3 |     let s2 = s1;
  |         -- value moved here
4 |
5 |     println!("{}, world!", s1);
  |                            ^^ value used here after move
  |
  = note: move occurs because `s1` has type `std::string::String`, which does
  not implement the `Copy` trait


When the owner goes out of scope, the value will be destroyed.

{
    let s = String::from("hello"); // s is valid from this point forward
    // do stuff with s
} // this scope is now over, and s is no longer valid




References and borrowing

Rust provides a way to use the value after passing to function, that is via reference (&). When we assign a value by reference it does not transfer the ownership, it just shares the reference to that object.

fn main() {
    let s1 = String::from("hello");
    let len = calculate_length(&s1);
    println!("The length of '{}' is {}.", s1, len);
}

fn calculate_length(s: &String) -> usize {
    s.len()
}

Above program compiles and run without any issue. As s1 is passed as a reference to calculate_length() function, this function does not try to drop s1 at the completion of the function.

More details: https://doc.rust-lang.org/book/2018-edition/ch04-02-references-and-borrowing.html#references-and-borrowing

Ahh! It will be an injustice to the book that I read and trying to explain the Rust language concepts.
This book has everything to start with. I would strongly recommend this book to any beginner.

At last, I would say Rust-lang is a fantastic language along with its cool toolchain that makes system programming awesome without having fear of seg-fault and memory leak.


References:
https://www.rust-lang.org/en-US/
https://doc.rust-lang.org/book/2018-edition/foreword.html
https://www.youtube.com/watch?v=_jMSrMex6R0














Test the performance of flutter grid control (GridView)

Before giving a try for my production app, I wanted to test the performance of google flutter.
I tested it to the extreme and at last, I was surprised to see the performance.

  1. Create an image gallery type grid control 
  2. Add a new image to GridView every 10 milliseconds.
  3. Perform the scrolling as fast as I can.
Conclusion: Scrolling was buttery smooth at any time no matter images are getting added at every 10 milliseconds and the total number of items reached to 30 thousand.


Here is the source of test case

import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:math';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: "Image grid demo",
      home: new HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  MyState createState() {
    return new MyState();
  }
}

class MyState extends State<HomePage> {
  MyState() {
    const duration = const Duration(milliseconds: 10);
    _timer = new Timer.periodic(duration, (Timer timer) {
      setState(() {
        int size = _random.nextInt(25) + 200;
        String url = 'https://placeimg.com/$size/$size/any';
        _items.add(url);

        if (_items.length > 30000)
          _timer.cancel();
      });
    });
  }

  Timer _timer;
  Random _random = new Random();
  List<String> _items = [];

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        backgroundColor: Colors.brown,
        title: new Text("Image Grid:" + _items.length.toString()),
      ),
      body: new Center(
        child: new GridView.count(
            crossAxisCount: 4,
            childAspectRatio: 1.0,
            padding: const EdgeInsets.all(5.0),
            mainAxisSpacing: 5.0,
            crossAxisSpacing: 5.0,
            children: _items.map((String url) {
              return new GridTile(
                child: new Image.network(url, fit: BoxFit.cover),
              );
            }).toList()),
      ),
    );
  }
}

Communication between widgets using InheritedWidget (Flutter)

I started using flutter and came accross the problem where I need communication between two widgets of my application.  I found InheritedWidget  easy and serve this purpose.

Let us make the problem simple.

  1. Button in App footer (MyFancyButton ) :On click on button increment the counter
  2. Counter widget (MyBox): It is in center of App.

Concept is simple. First create a StatefulWidget (MyApp/MyAppState) class that has count variable and a method (onTap) that increments the variable count.
In the build method of MyAppState return the InheritedWidget  (MyInheritedWidget)

Associate HomePage widget as a child to MyInheritedWidget.

  @override  Widget build(BuildContext context) {
     return new MyInheritedWidget(
      count: count,
      onTap: onTap,
      child: new HomePage(),
    );
  }
Now any change in count variable in State widget will result in rebuilding of child widget wherever MyInheritedWidget.

Complete code:
import 'package:flutter/material.dart';

void main() =>
    runApp(new MaterialApp(title: "Count Click App", home: new MyApp()));

class MyApp extends StatefulWidget {
  @override  MyAppState createState() {
    return new MyAppState();
  }
}

class MyAppState extends State<MyApp> {
  int count = 0;
  void onTap() {
    setState(() {
      count++;
    });
  }

  @override  Widget build(BuildContext context) {
     return new MyInheritedWidget(
      count: count,
      onTap: onTap,
      child: new HomePage(),
    );
  }
}

class MyInheritedWidget extends InheritedWidget {
  final int count;
  final Function onTap;

  const MyInheritedWidget({Key key, this.count, this.onTap, child})
      : super(key: key, child: child);

  @override  bool updateShouldNotify(MyInheritedWidget oldWidget) {
    return oldWidget.count != count;
  }

  static MyInheritedWidget of(BuildContext context) {
    return context.inheritFromWidgetOfExactType(MyInheritedWidget);
  }
}

class HomePage extends StatelessWidget {
  HomePage();

  @override  build(BuildContext context) {
    return new Scaffold(
      appBar:
          new AppBar(backgroundColor: Colors.amber, title: new Text("Count Click Demo")),
      body: new Center(child: new MyBox()),
      persistentFooterButtons: <Widget>[
        new MyFancyButton(),
      ],
    );
  }
}

class MyBox extends StatelessWidget {
  @override  Widget build(BuildContext context) {
    return new Center(
      child: new Text(
        "Counter: " + MyInheritedWidget.of(context).count.toString(),
        style: new TextStyle(fontWeight: FontWeight.w900, fontSize: 34.0),
      ),
    );
  }
}

class MyFancyButton extends StatelessWidget {
  @override  Widget build(BuildContext context) {
    return new RaisedButton(
      onPressed: () {
        MyInheritedWidget.of(context).onTap();
      },
      child: new Text("Click Me"),
      color: Colors.red,
      textColor: Colors.white,
    );
  }
}

Ionic2 multi columns Image Grid


I had a requirement to have an image grid-like image gallery.



I gone through the many tutorials and blogs. All were not suitable for my purpose.

  1. Some works with square sized images.
  2. Some works with hard-coded grid tile width.
  3. Some works on responsive design using fixed with image tile. I could not use this one because I need to use virtual-scroll.
  4. All work with the known number of items. All number of rows and columns are decided in the beginning.
I wanted to add image delete image and update image at the run time via some action without compromising the performance (with 10,000 image items). After searching here and there on Internet finally, I decided to sit calm and find the solution myself. After few hours a fairly simple solution came on the table.


Let's try with a sample application.


Create a blank App with the name 'ImageGrid'

ionic start ImageGrid

this will create the starting project. We will focus on the home.html, home.ts and home.scss only.

Image grid can be visualized as a 2D matrix with a fixed number of columns and variable numbers of row.
As I came from C/C++ background and know that internally 2D array is a contiguous memory allocation. So I decided to handle the 2D image matrix like a simple array.

Check the basic concept

// Create a type, you can add more fields to this type as per your requirement.
interface FileObject {
  public thumbnail: string;
}

const _grid_columns_count: number = 3; // Number of columns in image grid

//Get a specific item by row and column
yourFunction(row: number, col: number) {
  let i = row * _grid_columns_count + col;
}
// Here i is index by which you can query an item by row and column.
Full Source code
Home.ts
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

interface FileObject {
  thumbnail: string;
}

const _grid_columns_count: number = 3; // Number of columns in image grid

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  private columns: Array<number>;
  private rows: Array<number>;
  private fileObjects: FileObject[];


  constructor(public navCtrl: NavController) {
    // Create column array for number of columns you want
    this.columns = new Array(_grid_columns_count);

    // This array will hold the number of rows
    this.rows = new Array<number>();

    // This array will hold all the items in the grid.
    // Add a item by appending or inserting
    // Remove a item by delete your item from the array
    this.fileObjects = new Array<FileObject>();
  }

  // Add item
  addItem(obj: FileObject) {
    this.fileObjects.push(obj);

    // true of if condition indicates that we need a new row.
    if ((this.rows.length * _grid_columns_count) < this.fileObjects.length) {
      this.rows.push(this.rows.length);
    }
  }

  // Get an item by row and column
  getItemThumbnail(row: number, col: number) {
    let i = row * _grid_columns_count + col;

    if (i < this.fileObjects.length) {
      return this.fileObjects[i].thumbnail;
    }
    else {
      return "no found";
    }
  }

  isValid(row: number, col: number): boolean {
    let i = row * _grid_columns_count + col;
    return (i < this.fileObjects.length);
  }

  onTapImage(row, col) {
    let i = row * _grid_columns_count + col;

    if (i < this.fileObjects.length) {
      alert(this.fileObjects[i].thumbnail);
    }
  }

  getTileHeight(): string {
    return "100px;"
  }

  /*
  This is a method just to simulate how we can items
  change the image path as per your wish
*/
  addImages() {
    for (let i = 0; i < 8; ++i) {
      let obj: FileObject = {
        thumbnail: 'url("../assets/icon/image.jpg")'
      }

      this.addItem(obj);
    }
  }
}
Home.html
<ion-header>
  <ion-navbar color="dark">
    <ion-title>
      {{fileObjects.length}} files
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding style="background-color:#222">

  <ion-list [virtualScroll]="rows" approxItemHeight="{{getTileHeight()}}" no-margin>
    <ion-row *virtualItem="let row" class="item-row">
      <ion-col *ngFor="let column of columns; let col = index">
        <div *ngIf="isValid(row, col)" [style.background-image]="getItemThumbnail(row, col)" class="image-background" (tap)="onTapImage(row, col)">
        </div>
      </ion-col>
    </ion-row>
  </ion-list>

</ion-content>

<ion-footer>
  <ion-toolbar color="dark" style="text-align:center;">
    <!-- Button just to trigger the adding items -->
    <button ion-button round (tap)="addImages()">Add Images</button>
  </ion-toolbar>
</ion-footer>
Home.scss
page-home {
    .item-row {
        width: 100%;
        height: 120px;
    }
    .image-background {
        border: 2px solid #222;
        background-color: rgba(92, 90, 87, 0.644);
        background-size: cover;
        background-position: center;
        background-repeat: no-repeat;
        height: 100%;
    }
}


You can find the working project at Github
https://github.com/Anil8753/ImageGrid

Total Pageviews