progress on overall structure
This commit is contained in:
parent
5235ca9308
commit
3938b2032d
18 changed files with 272 additions and 58 deletions
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
20
src/lib/db/mod.rs
Normal 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
18
src/lib/db/models.rs
Normal 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,
|
||||
}
|
|
@ -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>;
|
||||
|
|
|
@ -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
45
src/lib/http/mod.rs
Normal 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
16
src/lib/http/models.rs
Normal 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
15
src/lib/http/routes.rs
Normal 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>) {
|
||||
//
|
||||
}
|
|
@ -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 {}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue