Initial database implementation
+ Using sled as a database + Added functions for inserting and fetching models from the databasemain
parent
a3f25f214c
commit
0bcb28bc47
|
@ -1,2 +1,3 @@
|
|||
/target
|
||||
.idea
|
||||
database/
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
The database is the core storage of Geoffrey. All models will be stored here. It is tightly
|
||||
coupled with the GeoffreyAPI.
|
||||
|
||||
![DB Architecture](figures/db_arch.svg)
|
||||
|
||||
## Geoffrey API
|
||||
The API provides the main logic to how models are manipulated in the Database. It is split
|
||||
into two parts, the Command API and Model API.
|
||||
|
|
|
@ -6,6 +6,24 @@ version = "1.0.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.19"
|
||||
|
@ -20,6 +38,70 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2584f639eb95fea8c798496315b297cf81b9b58b6d30ab066a75455333cf4b12"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"lazy_static",
|
||||
"memoffset",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fs2"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fxhash"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "geoffrey_db"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"geoffrey_models",
|
||||
"lazy_static",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sled",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "geoffrey_models"
|
||||
version = "0.1.0"
|
||||
|
@ -29,18 +111,60 @@ dependencies = [
|
|||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.88"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03b07a082330a35e43f63177cc01689da34fbffa0105e1246cf0311472cac73a"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312"
|
||||
dependencies = [
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.44"
|
||||
|
@ -60,6 +184,31 @@ dependencies = [
|
|||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb"
|
||||
dependencies = [
|
||||
"instant",
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"instant",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.24"
|
||||
|
@ -78,12 +227,27 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.123"
|
||||
|
@ -115,6 +279,28 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sled"
|
||||
version = "0.34.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d0132f3e393bcb7390c60bb45769498cf4550bcb7a21d7f95c02b69f6362cdc"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
"fs2",
|
||||
"fxhash",
|
||||
"libc",
|
||||
"log",
|
||||
"parking_lot",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.61"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
[workspace]
|
||||
members = [
|
||||
"geoffrey_models"
|
||||
"geoffrey_models",
|
||||
"geoffrey_db"
|
||||
]
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 12 KiB |
|
@ -0,0 +1,17 @@
|
|||
[package]
|
||||
name = "geoffrey_db"
|
||||
version = "0.1.0"
|
||||
authors = ["Joey Hines <joey@ahines.net>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
sled = "0.34.6"
|
||||
serde = "1.0"
|
||||
serde_json = "1.0"
|
||||
geoffrey_models = { path = "../geoffrey_models" }
|
||||
byteorder = "1.4.2"
|
||||
|
||||
[dev-dependencies]
|
||||
lazy_static = "1.4.0"
|
|
@ -0,0 +1,91 @@
|
|||
use crate::error::Result;
|
||||
use std::path::Path;
|
||||
use geoffrey_models::GeoffreyDatabaseModel;
|
||||
use crate::u64_to_bytes;
|
||||
|
||||
pub struct Database {
|
||||
db: sled::Db,
|
||||
}
|
||||
|
||||
impl Database {
|
||||
pub fn new(db_path: &Path) -> Result<Self> {
|
||||
let db = sled::open(db_path)?;
|
||||
|
||||
Ok(Self {
|
||||
db,
|
||||
})
|
||||
}
|
||||
|
||||
fn get_tree<T>(&self) -> Result<sled::Tree> where T: GeoffreyDatabaseModel {
|
||||
Ok(self.db.open_tree::<String>(T::tree())?)
|
||||
}
|
||||
|
||||
pub fn insert<'a, T>(&self, mut model: T) -> Result<T> where T: GeoffreyDatabaseModel {
|
||||
let id = self.db.generate_id()?;
|
||||
let tree = self.get_tree::<T>()?;
|
||||
let data = serde_json::to_vec(&model).unwrap();
|
||||
let id_bytes = u64_to_bytes(id);
|
||||
|
||||
tree.insert(id_bytes, data)?;
|
||||
|
||||
model.set_id(id);
|
||||
|
||||
Ok(model)
|
||||
}
|
||||
|
||||
|
||||
pub fn get<T>(&self, id: u64) -> Result<Option<T>> where T: GeoffreyDatabaseModel {
|
||||
let tree = self.get_tree::<T>()?;
|
||||
let id_bytes = u64_to_bytes(id);
|
||||
|
||||
if let Some(bytes) = tree.get(id_bytes)? {
|
||||
Ok(Some(T::try_from_bytes(&bytes).unwrap()))
|
||||
}
|
||||
else {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::database::{Database};
|
||||
use std::path::Path;
|
||||
use geoffrey_models::models::player::{Player, UserID};
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
|
||||
lazy_static! {
|
||||
static ref DB: Database = Database::new(Path::new("../database")).unwrap();
|
||||
}
|
||||
|
||||
fn cleanup() {
|
||||
DB.db.clear().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_insert() {
|
||||
let player = Player::new("CoolZero123", UserID::DiscordUUID(0));
|
||||
|
||||
let p2 = DB.insert::<Player>(player.clone()).unwrap();
|
||||
|
||||
assert!(p2.id.is_some());
|
||||
assert_eq!(player.name, p2.name);
|
||||
cleanup();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get() {
|
||||
let player = Player::new("CoolZero123", UserID::DiscordUUID(0));
|
||||
|
||||
let p2 = DB.insert::<Player>(player.clone()).unwrap();
|
||||
|
||||
let p3 = DB.get::<Player>(p2.id.unwrap()).unwrap();
|
||||
|
||||
assert!(p3.is_some());
|
||||
assert_eq!(p3.unwrap().name, player.name);
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
|
||||
pub type Result<T> = std::result::Result<T, GeoffreyDBError>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum GeoffreyDBError {
|
||||
SledError(sled::Error),
|
||||
SerdeJsonError(serde_json::Error),
|
||||
}
|
||||
|
||||
impl std::error::Error for GeoffreyDBError {}
|
||||
|
||||
impl std::fmt::Display for GeoffreyDBError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
GeoffreyDBError::SledError(e) => write!(f, "Sled Error: {}", e),
|
||||
GeoffreyDBError::SerdeJsonError(e) => write!(f, "Serde JSON Error: {}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<sled::Error> for GeoffreyDBError {
|
||||
fn from(e: sled::Error) -> Self {
|
||||
GeoffreyDBError::SledError(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<serde_json::Error> for GeoffreyDBError {
|
||||
fn from(e: serde_json::Error) -> Self {
|
||||
GeoffreyDBError::SerdeJsonError(e)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
use byteorder::{WriteBytesExt, BigEndian};
|
||||
|
||||
pub mod database;
|
||||
pub mod error;
|
||||
|
||||
pub fn u64_to_bytes(n: u64) -> Vec<u8> {
|
||||
let mut id_bytes= vec![0u8; 8];
|
||||
id_bytes.write_u64::<BigEndian>(n).unwrap();
|
||||
|
||||
id_bytes
|
||||
}
|
|
@ -1,3 +1,17 @@
|
|||
#[allow(dead_code)]
|
||||
|
||||
use serde::{Serialize};
|
||||
use serde::de::DeserializeOwned;
|
||||
|
||||
pub mod models;
|
||||
|
||||
pub trait GeoffreyDatabaseModel: Serialize + DeserializeOwned {
|
||||
fn id(&self) -> Option<u64>;
|
||||
fn set_id(&mut self, id: u64);
|
||||
fn tree() -> String;
|
||||
|
||||
fn try_from_bytes(v: &[u8]) -> Result<Self, serde_json::Error> {
|
||||
Ok(serde_json::from_slice::<Self>(v)?)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use crate::models::item::Item;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct FarmData {
|
||||
pub items_produced: Vec<Item>
|
||||
}
|
||||
|
|
@ -5,3 +5,11 @@ pub struct Item {
|
|||
pub name: String,
|
||||
}
|
||||
|
||||
impl Item {
|
||||
pub fn new(name: &str) -> Self {
|
||||
Self {
|
||||
name: name.to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct MarketData {
|
||||
pub shops: Vec<u64>,
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use crate::GeoffreyDatabaseModel;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
struct Meta {
|
||||
id: Option<u64>,
|
||||
version: u64,
|
||||
database_version: u64,
|
||||
}
|
||||
|
||||
impl GeoffreyDatabaseModel for Meta {
|
||||
fn id(&self) -> Option<u64> {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn set_id(&mut self, id: u64) {
|
||||
self.id = Some(id);
|
||||
}
|
||||
|
||||
fn tree() -> String {
|
||||
"meta".to_string()
|
||||
}
|
||||
}
|
|
@ -1,19 +1,28 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use crate::models::player::Player;
|
||||
use crate::models::shop::ShopData;
|
||||
use crate::models::town::TownData;
|
||||
use crate::models::market::MarketData;
|
||||
use crate::models::farm::FarmData;
|
||||
use crate::GeoffreyDatabaseModel;
|
||||
|
||||
pub mod player;
|
||||
pub mod shop;
|
||||
pub mod item;
|
||||
pub mod town;
|
||||
pub mod farm;
|
||||
pub mod market;
|
||||
pub mod token;
|
||||
mod meta;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub enum LocationData {
|
||||
Base,
|
||||
Shop(ShopData),
|
||||
Town,
|
||||
Market,
|
||||
Town(TownData),
|
||||
Market(MarketData),
|
||||
Attraction,
|
||||
PublicFarm,
|
||||
PublicFarm(FarmData),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Copy, Clone)]
|
||||
|
@ -52,7 +61,7 @@ pub struct Tunnel {
|
|||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct Location {
|
||||
id: u64,
|
||||
id: Option<u64>,
|
||||
name: String,
|
||||
position: Position,
|
||||
owners: Vec<Player>,
|
||||
|
@ -61,11 +70,10 @@ pub struct Location {
|
|||
}
|
||||
|
||||
|
||||
|
||||
impl Location {
|
||||
fn new (id: u64, name: &str, position: Position, owners: Vec<Player>, tunnel: Option<Tunnel>, loc_data: LocationData) -> Self {
|
||||
pub fn new (name: &str, position: Position, owners: Vec<Player>, tunnel: Option<Tunnel>, loc_data: LocationData) -> Self {
|
||||
Location {
|
||||
id,
|
||||
id: None,
|
||||
name: name.to_string(),
|
||||
position,
|
||||
owners,
|
||||
|
@ -75,6 +83,20 @@ impl Location {
|
|||
}
|
||||
}
|
||||
|
||||
impl GeoffreyDatabaseModel for Location {
|
||||
fn id(&self) -> Option<u64> {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn set_id(&mut self, id: u64) {
|
||||
self.id = Some(id);
|
||||
}
|
||||
|
||||
fn tree() -> String {
|
||||
"location".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::models::{Location, Position, Dimension, LocationData};
|
||||
|
@ -82,8 +104,8 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_new_base() {
|
||||
let player = Player {name: "CoolZero123".to_string(), user_ids: vec![UserID::DiscordUUID(0)]};
|
||||
Location::new(0, "test", Position {x: 0, y: 0, dimension: Dimension::Overworld}, vec![player], None, LocationData::Base);
|
||||
let player = Player::new("CoolZero123", UserID::DiscordUUID(0));
|
||||
Location::new("test", Position {x: 0, y: 0, dimension: Dimension::Overworld}, vec![player], None, LocationData::Base);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,39 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use crate::GeoffreyDatabaseModel;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub enum UserID {
|
||||
DiscordUUID(u64),
|
||||
MinecraftUUID(String),
|
||||
GeoffreyID(u64)
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct Player {
|
||||
pub id: Option<u64>,
|
||||
pub name: String,
|
||||
pub user_ids: Vec<UserID>
|
||||
}
|
||||
|
||||
impl Player {
|
||||
pub fn new(name: &str, user_id: UserID) -> Self {
|
||||
Self {
|
||||
id: None,
|
||||
name: name.to_string(),
|
||||
user_ids: vec![user_id]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GeoffreyDatabaseModel for Player {
|
||||
fn id(&self) -> Option<u64> {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn set_id(&mut self, id: u64) {
|
||||
self.id = Some(id);
|
||||
}
|
||||
|
||||
fn tree() -> String {
|
||||
"player".to_string()
|
||||
}
|
||||
}
|
|
@ -27,16 +27,3 @@ pub struct ShopData {
|
|||
pub item_listings: Vec<ItemListing>
|
||||
}
|
||||
|
||||
impl ShopData {
|
||||
fn add_item(&mut self, item_listing: ItemListing) {
|
||||
self.item_listings.push(item_listing);
|
||||
}
|
||||
|
||||
fn filter_items<F>(&self, filter: F) -> Vec<ItemListing> where F: FnMut(&&ItemListing) -> bool {
|
||||
self.item_listings.iter().filter(filter).cloned().collect()
|
||||
}
|
||||
|
||||
fn remove_item(&mut self, item_name: &str) {
|
||||
self.item_listings.retain(|listing| &listing.item.name != item_name)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use chrono::{DateTime, Utc};
|
||||
use crate::GeoffreyDatabaseModel;
|
||||
|
||||
pub enum Permissions {
|
||||
ModelGet = 0,
|
||||
ModelPost,
|
||||
Command,
|
||||
ModCommand,
|
||||
Admin,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
struct Token {
|
||||
pub id: Option<u64>,
|
||||
permission: u64,
|
||||
pub created: DateTime<Utc>,
|
||||
pub modified: DateTime<Utc>
|
||||
}
|
||||
|
||||
impl Token {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
id: None,
|
||||
permission: 0,
|
||||
created: Utc::now(),
|
||||
modified: Utc::now()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_permission(&mut self, permission: Permissions) {
|
||||
self.permission = self.permission | (1u64 << permission as u32);
|
||||
}
|
||||
|
||||
pub fn clear_permission(&mut self, permission: Permissions) {
|
||||
self.permission = self.permission & !(1u64 << permission as u32);
|
||||
}
|
||||
|
||||
pub fn check_permission(&self, permission: Permissions) -> bool {
|
||||
(self.permission >> permission as u32) & 0x1u64 == 0x1u64
|
||||
}
|
||||
|
||||
pub fn clear_all_permission(&mut self) {
|
||||
self.permission = 0x0u64;
|
||||
}
|
||||
}
|
||||
|
||||
impl GeoffreyDatabaseModel for Token {
|
||||
fn id(&self) -> Option<u64> {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn set_id(&mut self, id: u64) {
|
||||
self.id = Some(id);
|
||||
}
|
||||
|
||||
fn tree() -> String {
|
||||
"token".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Token {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.permission == other.permission
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::models::token::{Token, Permissions};
|
||||
|
||||
#[test]
|
||||
fn test_token() {
|
||||
let mut token = Token::new(0);
|
||||
|
||||
token.set_permission(Permissions::ModelGet);
|
||||
assert_eq!(token.permission, 0x1u64);
|
||||
|
||||
token.set_permission(Permissions::ModelPost);
|
||||
assert_eq!(token.permission, 0x3u64);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Default, Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct TownData {
|
||||
pub resident: Vec<u64>
|
||||
}
|
||||
|
Loading…
Reference in New Issue