From 31a3fa2e466b1b9bd51533ff99283328b72a05a4 Mon Sep 17 00:00:00 2001 From: jeff Date: Wed, 9 Dec 2020 21:25:31 +0000 Subject: [PATCH] Finished and mostly clean new character flow. Lots of changes and reorganization to support the ability to create new characters. --- Cargo.lock | 22 +++ Cargo.toml | 1 + src/models.rs | 1 + src/models/characters.rs | 28 +++- src/models/convert.rs | 28 ++++ src/routes/characters.rs | 2 +- src/routes/characters/new.rs | 129 ++++++++---------- templates/characters/new_character.html.tera | 15 +- .../view_changeling_character.html.tera | 11 ++ templates/characters/view_character.html.tera | 1 + 10 files changed, 163 insertions(+), 75 deletions(-) create mode 100644 src/models/convert.rs create mode 100644 templates/characters/view_changeling_character.html.tera diff --git a/Cargo.lock b/Cargo.lock index 7994578..233b9de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1404,6 +1404,27 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3015a7d0a5fd5105c91c3710d42f9ccf0abfb287d62206484dcc67f9569a6483" +[[package]] +name = "strum" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7318c509b5ba57f18533982607f24070a55d353e90d4cae30c467cdb2ad5ac5c" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee8bc6b87a5112aeeab1f4a9f7ab634fe6cbefc4850006df31267f4cfb9e3149" +dependencies = [ + "heck", + "proc-macro2 1.0.24", + "quote 1.0.7", + "syn 1.0.53", +] + [[package]] name = "subtle" version = "1.0.0" @@ -1469,6 +1490,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", + "strum", "thiserror", ] diff --git a/Cargo.toml b/Cargo.toml index 14bb83c..b367eae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ rust-argon2 = "0.8" log = "0.4" rand = "0.7" rocket = { version= "0.4.6", features = ["private-cookies"] } +strum = { version = "0.20", features = ["derive"] } [dependencies.rocket_contrib] version = "0.4.6" diff --git a/src/models.rs b/src/models.rs index cb0c1b1..b390c55 100644 --- a/src/models.rs +++ b/src/models.rs @@ -1,3 +1,4 @@ pub mod characters; +pub mod convert; pub mod proto; pub mod users; diff --git a/src/models/characters.rs b/src/models/characters.rs index 716ed22..a8f17d9 100644 --- a/src/models/characters.rs +++ b/src/models/characters.rs @@ -3,7 +3,9 @@ use crate::models::proto::cofd::*; use crate::models::users::User; use crate::schema::characters; use diesel_derive_enum::DbEnum; +use prost::bytes::BytesMut; use serde_derive::Serialize; +use strum::{EnumIter, EnumString}; /// Dynamic character data is an opaque container type that holds /// successfully deserialized character data protobuf object of any @@ -39,12 +41,36 @@ pub(crate) trait Visibility { } } -#[derive(DbEnum, Debug, Serialize, PartialEq, Clone, Copy)] +#[derive(DbEnum, Debug, Serialize, PartialEq, Clone, Copy, EnumIter, EnumString)] pub enum CharacterDataType { ChroniclesOfDarknessV1, ChangelingV1, } +impl CharacterDataType { + pub fn create_data(&self) -> Result { + use prost::Message; + use CharacterDataType::*; + let data: BytesMut = match self { + ChroniclesOfDarknessV1 => { + let sheet = CofdSheet::default(); + let mut buf = BytesMut::with_capacity(std::mem::size_of_val(&sheet)); + sheet.encode(&mut buf)?; + buf + } + ChangelingV1 => { + let mut sheet = ChangelingSheet::default(); + sheet.base = Some(CofdSheet::default()); + let mut buf = BytesMut::with_capacity(std::mem::size_of_val(&sheet)); + sheet.encode(&mut buf)?; + buf + } + }; + + Ok(data) + } +} + /// An entry that appears in a user's character list. Properties are /// in order of table columns. #[derive(Serialize, Debug, Queryable)] diff --git a/src/models/convert.rs b/src/models/convert.rs new file mode 100644 index 0000000..c108555 --- /dev/null +++ b/src/models/convert.rs @@ -0,0 +1,28 @@ +use super::characters::CharacterDataType; +use rocket::http::RawStr; +use rocket::request::FromFormValue; +use std::str::FromStr; +use thiserror::Error; + +/// Validation errors specific to the new character form. +#[derive(Serialize, Error, Debug, Clone)] +pub enum ValidationError { + #[error("bad UTF-8 encoding")] + BadEncoding, + + #[error("invalid game system: {0}")] + InvalidGameSystem(String), +} + +impl<'v> FromFormValue<'v> for CharacterDataType { + type Error = ValidationError; + + fn from_form_value(form_value: &'v RawStr) -> Result { + let system = form_value + .url_decode() + .or(Err(ValidationError::BadEncoding))?; + + CharacterDataType::from_str(&system) + .or_else(|_| Err(ValidationError::InvalidGameSystem(system.to_string()))) + } +} diff --git a/src/routes/characters.rs b/src/routes/characters.rs index 69e4610..425f1b6 100644 --- a/src/routes/characters.rs +++ b/src/routes/characters.rs @@ -38,7 +38,7 @@ fn view_character_template(user: &User, character: Character) -> Result