progress on overall structure

This commit is contained in:
Jolimaitre Matthieu 2021-11-12 21:01:35 +01:00
parent 5235ca9308
commit 3938b2032d
18 changed files with 272 additions and 58 deletions

View file

@ -1,13 +1,61 @@
use std::fs::{read_to_string, write};
use ron;
use serde::{Deserialize, Serialize};
use super::harsh::Error;
///
/// Encapsulate a configuration for the server
///
#[derive(Clone, Serialize, Deserialize)]
pub struct Configuration {
pub path: String, //
pub database_path: String, //
pub port: u32,
}
static CONFIG_PATHS: [&str; 2] = ["./config.ron", "/etc/harsh/harsh.ron"];
impl Configuration {
/// try to read the configuration from local file or load default
pub fn read() -> Self {
todo!()
pub fn get() -> Self {
match Self::try_from_file() {
Ok(config) => config,
Err(_) => {
let result = Configuration::default();
Configuration::write_config(&result);
result
}
}
}
fn try_from_file() -> Result<Self, Error> {
let content = Self::try_read()?;
let config: Configuration = ron::from_str(&content)?;
Ok(config)
}
fn try_read() -> Result<String, Error> {
for path in CONFIG_PATHS {
match read_to_string(path) {
Ok(serialized) => return Ok(serialized),
_ => (),
}
}
Err("unable to locate or read config file".to_string().into())
}
fn write_config(data: &Self) {
let serialized = ron::to_string(data).unwrap();
write(CONFIG_PATHS[0], serialized);
}
}
impl Default for Configuration {
fn default() -> Self {
Self {
database_path: "./database".to_string(),
port: 42069, // haha funny number
}
}
}

View file

@ -1,15 +0,0 @@
use super::config::Configuration;
///
/// handle the database access
///
pub struct DbManager {
//
}
impl DbManager {
/// constructor
pub fn new(_config: &Configuration) -> Self {
todo!()
}
}

20
src/lib/db/mod.rs Normal file
View file

@ -0,0 +1,20 @@
pub mod models;
use sled::Db;
use super::{config::Configuration, harsh::Error};
///
/// handle the database access
///
pub struct DbManager {
handle: Db,
}
impl DbManager {
/// constructor
pub fn new(config: Configuration) -> Result<Self, Error> {
let handle = sled::open(config.database_path)?;
Ok(DbManager { handle })
}
}

18
src/lib/db/models.rs Normal file
View file

@ -0,0 +1,18 @@
type Id = u64;
pub struct User {
username: String,
password: String,
id: Id,
}
pub struct Channel {
name: String,
id: Id,
messages: Vec<Id>,
}
pub struct Message {
content: String,
id: Id,
}

View file

@ -1,33 +1,68 @@
use std::error;
use std::sync::{Arc, RwLock};
use super::config::Configuration;
use super::database::DbManager;
use super::db::DbManager;
use super::http::HttpManager;
use super::log::Logger;
///
/// main function
///
pub fn main() {
let configuration = Configuration::read();
pub async fn main() {
let configuration = Configuration::get();
let instance = Harsh::new(configuration);
instance.serve().await;
}
pub struct Harsh {
db_manager: DbManager,
logger: Logger,
http_manager: HttpManager,
pub shared_state: SharedState,
pub http_manager: HttpManager,
}
impl Harsh {
pub fn new(configuration: Configuration) -> Self {
let db_manager = DbManager::new(&configuration);
let logger = Logger::new(&configuration);
let http_manager = HttpManager::new();
let db_manager =
DbManager::new(configuration.clone()).expect("failed to open / create the database");
let logger = Logger::new(configuration.clone());
let shared_state = State::new_shared(db_manager, logger);
let http_manager = HttpManager::new(configuration.clone(), shared_state.clone());
Harsh {
logger,
db_manager,
shared_state,
http_manager,
}
}
fn serve(&mut self) {}
pub async fn serve(self) {
self.http_manager.serve().await;
}
}
///
/// shared state arround the app
///
pub struct State {
pub db_manager: RwLock<DbManager>,
pub logger: RwLock<Logger>,
}
impl State {
pub fn new_shared(db_manager: DbManager, logger: Logger) -> SharedState {
let state = State {
db_manager: RwLock::new(db_manager),
logger: RwLock::new(logger),
};
Arc::new(state)
}
}
///
/// safe pointer to the shared state
///
pub type SharedState = Arc<State>;
///
/// error type for now..
///
pub type Error = Box<dyn error::Error>;

View file

@ -1,20 +0,0 @@
use super::config::Configuration;
use super::database::DbManager;
///
/// listen for incoming requests and handle both incoming and outgoing requests
///
pub struct HttpManager {
//
}
impl HttpManager {
pub fn new() -> Self {
HttpManager {}
}
/// listen for and handle received requests
pub fn serve(_config: &Configuration, _db_manager: &mut DbManager) {
todo!()
}
}

45
src/lib/http/mod.rs Normal file
View file

@ -0,0 +1,45 @@
///
/// contains every route handlers
///
mod routes;
///
/// contains every models used by the http server
///
pub mod models;
use axum::{AddExtensionLayer, Router};
use self::routes::setup_routes;
use super::config::Configuration;
use super::harsh::SharedState;
///
/// listen for incoming requests and handle both incoming and outgoing requests
///
pub struct HttpManager {
_shared_state: SharedState,
app: Router,
}
impl HttpManager {
/// constructor
pub fn new(_config: Configuration, shared_state: SharedState) -> Self {
let app = setup_routes(Router::new()).layer(AddExtensionLayer::new(shared_state.clone()));
HttpManager {
_shared_state: shared_state.clone(),
app,
}
}
/// listen for and handle received requests
pub async fn serve(self) {
let address = "0.0.0.0:3000".parse().unwrap();
axum::Server::bind(&address)
.serve(self.app.into_make_service())
.await
.unwrap();
}
}

16
src/lib/http/models.rs Normal file
View file

@ -0,0 +1,16 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
pub struct CreateUser {
name: String,
password: String,
}
pub struct EditUser {
//
}
pub struct DeleteUser {
name: String,
password: String,
}

15
src/lib/http/routes.rs Normal file
View file

@ -0,0 +1,15 @@
use axum::extract::{Extension, Json};
use axum::routing::get;
use axum::Router;
use crate::lib::harsh::SharedState;
use super::models::*;
pub fn setup_routes(app: Router) -> Router {
app.route("/user/create", get(create_user))
}
async fn create_user(Extension(state): Extension<SharedState>, Json(payload): Json<CreateUser>) {
//
}

View file

@ -11,7 +11,7 @@ pub struct Logger {
impl Logger {
/// adapt the static instance according to parameters specified by the configuration
pub fn new(_config: &Configuration) -> Self {
pub fn new(_config: Configuration) -> Self {
Logger {}
}

View file

@ -1,5 +1,24 @@
///
/// encapsulate the logic responsible for reading and parsing the server configuration
///
pub mod config;
pub mod database;
///
/// encapsulate the logic responsible for interacting with the database
///
pub mod db;
///
/// main module, exposes the highest level structure holding the whole server runtime logic
///
pub mod harsh;
///
/// encapsulate the logic responsible for receiving and routing http requests
///
pub mod http;
///
/// encapsulate the logic responsible for logging events occuring while the server is running
///
pub mod log;

View file

@ -1,6 +1,10 @@
///
/// library module
///
pub mod lib;
pub fn main() {
#[tokio::main]
pub async fn main() {
println!("Hello, harmony!");
lib::harsh::main();
lib::harsh::main().await;
}