Skip to content

Instantly share code, notes, and snippets.

@ivanitskiy
Last active March 17, 2020 20:43
Show Gist options
  • Save ivanitskiy/9b1126a72b4e23f752f7d71b5f8c6b01 to your computer and use it in GitHub Desktop.
Save ivanitskiy/9b1126a72b4e23f752f7d71b5f8c6b01 to your computer and use it in GitHub Desktop.
Example of using ARC (Atomically Reference Counted)
[package]
name = "clumpctrl"
version = "0.1.0"
authors = ["Maxim Ivanitskiy <[email protected]>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rocket = "0.4.4"
serde = { version = "1.0", features = ["derive"] }
serde_yaml = {version = "0.8.11" }
lazy_static = "1.4.0"
tera = "1.1.0"
[dependencies.rocket_contrib]
version = "0.4.4"
default-features = false
features = ["tera_templates", "serve"]
[dependencies.uuid]
features = ["serde", "v4"]
version = "0.8.1"

This example demonstrates how to use "global" variable, which is a Vector of "Clusters". that can be used in a simple web-app powered by Rocket.

The idea is that whenever user opens a web-page, a new object is added into a Vector of clusters and tera template will just pint the length of the clusters. Because this is a web-application, we need to use lock (read/write) in order to add/remove clusters from the vector.

// Nightly-only language features needed by Rocket
#![feature(proc_macro_hygiene, decl_macro)]
// Import the rocket macros
#[macro_use]
extern crate rocket;
#[macro_use]
extern crate serde;
#[macro_use]
extern crate lazy_static;
use rocket_contrib::templates::Template;
use rocket_contrib::serve::StaticFiles;
use serde::{Deserialize, Serialize};
use std::{
sync::{Arc, RwLock},
};
use uuid::Uuid;
use tera::Context;
use serde_yaml;
type Clusters = Arc<RwLock<Vec<Cluster>>>;
lazy_static! {
pub static ref CLUSTERS: Clusters = Arc::new(RwLock::new(Vec::new()));
}
fn add_cluster(c: Cluster) {
let clusters = Arc::clone(&CLUSTERS);
let mut lock = clusters.write().unwrap();
lock.push(c);
}
fn remove_cluster(id: Uuid) {
let clusters = Arc::clone(&CLUSTERS);
let mut lock = clusters.write().unwrap();
// find the index
let mut idx = lock.len();
for (i, cluster) in lock.iter().enumerate() {
if cluster.id == id {
idx = i;
}
}
// remove that element if found
if idx < lock.len() {
lock.remove(idx);
}
}
#[derive(Serialize, Deserialize, Debug)]
struct Person {
name: String,
age: u8,
phones: Vec<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Cluster {
name: String,
id: Uuid,
}
impl Cluster {
fn new(name: &str) -> Self {
Self {
id: Uuid::new_v4(),
name: String::from(name),
}
}
}
/// Create route /index that returns html page
#[get("/")]
fn index() -> Template {
let clustername = String::from("cluster1");
add_cluster(Cluster::new(&clustername));
// just to test that context can have many objects
let p = Person {
name: "Maxim".to_owned(),
age: 18,
phones: vec!["1234".to_owned()],
};
let clusters = Arc::clone(&CLUSTERS);
let lock = clusters.read().unwrap();
let mut ctx = Context::new();
ctx.insert("clusters", &*lock);
ctx.insert("clustersLen", &(*lock).len());
ctx.insert("person", &p);
Template::render("index", ctx.into_json())
}
fn main() {
rocket::ignite()
.mount("/", routes![index])
.mount("/vendor", StaticFiles::from(concat!(env!("CARGO_MANIFEST_DIR"), "/static/vendor")))
.attach(Template::fairing())
.launch();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment