Initial commit

This commit is contained in:
Dániel Szabó 2022-04-10 23:21:45 +01:00
commit d42a361e95
9 changed files with 363 additions and 0 deletions

61
src/animalnumbers.rs Normal file
View file

@ -0,0 +1,61 @@
const animal_names: &[&str] = &[
"ant", "eel", "mole", "sloth",
"ape", "emu", "monkey", "snail",
"bat", "falcon", "mouse", "snake",
"bear", "fish", "otter", "spider",
"bee", "fly", "parrot", "squid",
"bird", "fox", "panda", "swan",
"bison", "frog", "pig", "tiger",
"camel", "gecko", "pigeon", "toad",
"cat", "goat", "pony", "turkey",
"cobra", "goose", "pug", "turtle",
"crow", "hawk", "rabbit", "viper",
"deer", "horse", "rat", "wasp",
"dog", "jaguar", "raven", "whale",
"dove", "koala", "seal", "wolf",
"duck", "lion", "shark", "worm",
"eagle", "lizard", "sheep", "zebra",
];
pub fn to_animal_names(mut n: u64) -> String {
let mut result: Vec<&str> = Vec::new();
if n == 0 {
return animal_names[0].parse().unwrap();
} else if n == 1 {
return animal_names[1].parse().unwrap();
}
// max 4 animals so 6 * 6 = 64 bits
let mut power = 6;
loop {
let d = n / animal_names.len().pow(power) as u64;
if !(result.is_empty() && d == 0) {
result.push(animal_names[d as usize]);
}
n -= d * animal_names.len().pow(power) as u64;
if power > 0 {
power -= 1;
} else { break; }
}
result.join("-")
}
pub fn to_u64(n: &str) -> u64 {
let mut result: u64 = 0;
let mut animals: Vec<&str> = n.split("-").collect();
let mut pow = animals.len();
for i in 0..animals.len() {
pow -= 1;
result += (animal_names.iter().position(|&r| r == animals[i]).unwrap() * animal_names.len().pow(pow as u32)) as u64;
}
result
}

137
src/main.rs Normal file
View file

@ -0,0 +1,137 @@
extern crate core;
use std::path::PathBuf;
use std::sync::Mutex;
use std::time::{SystemTime, UNIX_EPOCH};
use actix_files::NamedFile;
use actix_web::{App, get, HttpRequest, HttpResponse, HttpServer, post, Responder, Result, web};
use actix_web::web::Data;
use askama::Template;
use rand::Rng;
use crate::animalnumbers::{to_animal_names, to_u64};
use crate::pasta::{Pasta, PastaFormData};
mod pasta;
mod animalnumbers;
struct AppState {
pastas: Mutex<Vec<Pasta>>,
}
#[derive(Template)]
#[template(path = "index.html")]
struct IndexTemplate {}
#[derive(Template)]
#[template(path = "pasta.html")]
struct PastaTemplate<'a> {
pasta: &'a Pasta,
}
#[derive(Template)]
#[template(path = "pastalist.html")]
struct PastaListTemplate<'a> {
pastas: &'a Vec<Pasta>,
}
#[get("/")]
async fn index() -> impl Responder {
HttpResponse::Found().content_type("text/html").body(IndexTemplate {}.render().unwrap())
}
#[post("/create")]
async fn create(data: web::Data<AppState>, pasta: web::Form<PastaFormData>) -> impl Responder {
let mut pastas = data.pastas.lock().unwrap();
let mut innerPasta = pasta.into_inner();
let timenow: i64 = match SystemTime::now().duration_since(UNIX_EPOCH) {
Ok(n) => n.as_secs(),
Err(_) => panic!("SystemTime before UNIX EPOCH!"),
} as i64;
let expiration = match innerPasta.expiration.as_str() {
"firstread" => 1,
"10min" => timenow + 60 * 10,
"1hour" => timenow + 60 * 60,
"24hour" => timenow + 60 * 60 * 24,
"1week" => timenow + 60 * 60 * 24 * 7,
"never" => 0,
_ => panic!("Unexpected expiration time!")
};
let mut newPasta = Pasta {
id: rand::thread_rng().gen::<u16>() as u64,
content: innerPasta.content,
created: timenow,
expiration,
};
let id = newPasta.id;
pastas.push(newPasta);
HttpResponse::Found().append_header(("Location", format!("/pasta/{}", to_animal_names(id)))).finish()
}
#[get("/pasta/{id}")]
async fn getpasta(data: web::Data<AppState>, id: web::Path<String>) -> HttpResponse {
let pastas = data.pastas.lock().unwrap();
let id = to_u64(&*id.into_inner());
for pasta in pastas.iter() {
if pasta.id == id {
return HttpResponse::Found().content_type("text/html").body(PastaTemplate { pasta }.render().unwrap());
}
}
HttpResponse::Found().body("Pasta not found! :-(")
}
#[get("/rawpasta/{id}")]
async fn getrawpasta(data: web::Data<AppState>, id: web::Path<String>) -> String {
let pastas = data.pastas.lock().unwrap();
let id = to_u64(&*id.into_inner());
for pasta in pastas.iter() {
if pasta.id == id {
return pasta.content.to_owned();
}
}
String::from("Pasta not found! :-(")
}
#[get("/remove/{id}")]
async fn remove(data: web::Data<AppState>, id: web::Path<String>) -> HttpResponse {
let mut pastas = data.pastas.lock().unwrap();
let id = to_u64(&*id.into_inner());
for (i, pasta) in pastas.iter().enumerate() {
if pasta.id == id {
pastas.remove(i);
return HttpResponse::Found().append_header(("Location", "/pastalist")).finish();
}
}
HttpResponse::Found().body("Pasta not found! :-(")
}
#[get("/pastalist")]
async fn list(data: web::Data<AppState>) -> HttpResponse {
let mut pastas = data.pastas.lock().unwrap();
HttpResponse::Found().content_type("text/html").body(PastaListTemplate { pastas: &pastas }.render().unwrap())
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let data = web::Data::new(AppState {
pastas: Mutex::new(Vec::new()),
});
HttpServer::new(move || App::new().app_data(data.clone()).service(index).service(create).service(getpasta).service(getrawpasta).service(remove).service(list)
).bind("127.0.0.1:8080")?.run().await
}

57
src/pasta.rs Normal file
View file

@ -0,0 +1,57 @@
use std::fmt;
use actix_web::cookie::time::macros::format_description;
use chrono::{Datelike, DateTime, NaiveDateTime, Timelike, Utc};
use serde::Deserialize;
use crate::to_animal_names;
pub struct Pasta {
pub id: u64,
pub content: String,
pub created: i64,
pub expiration: i64
}
#[derive(Deserialize)]
pub struct PastaFormData {
pub content: String,
pub expiration: String
}
impl Pasta {
pub fn idAsAnimals(&self) -> String {
to_animal_names(self.id)
}
pub fn createdAsString(&self) -> String {
let date = DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(self.created, 0), Utc);
format!(
"{}-{:02}-{:02} {}:{}",
date.year(),
date.month(),
date.day(),
date.hour(),
date.minute(),
)
}
pub fn expirationAsString(&self) -> String {
let date = DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(self.expiration, 0), Utc);
format!(
"{}-{:02}-{:02} {}:{}",
date.year(),
date.month(),
date.day(),
date.hour(),
date.minute(),
)
}
}
impl fmt::Display for Pasta {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.content)
}
}