From 0db4790a00c92f8d1f0789ec595d44c8e8015f74 Mon Sep 17 00:00:00 2001 From: Andrea Zagli Date: Sat, 11 Feb 2023 16:05:10 +0100 Subject: [PATCH] Use of Box and Any for polymorphism. --- examples/form.rs | 24 +++++++------ src/fields.rs | 94 +++++++++++++++++++++++++++--------------------- src/form.rs | 23 ++++++------ 3 files changed, 79 insertions(+), 62 deletions(-) diff --git a/examples/form.rs b/examples/form.rs index e621365..3943ef7 100644 --- a/examples/form.rs +++ b/examples/form.rs @@ -1,7 +1,5 @@ extern crate zakform; -use zakform::{form, fields, filters, fields::TField}; - use std::collections::HashMap; use config::{Config, ConfigError}; @@ -57,25 +55,29 @@ async fn index( let mut f = zakform::form::Form::new(); let mut fi = zakform::fields::FieldText::new("text"); - f.add_field(zakform::form::TFields::TFieldText(fi)); + f.add_field(Box::new(fi)); let mut fi = zakform::fields::FieldRadio::new("radio"); fi.add_option(zakform::fields::FOption{ value: String::from("F"), label: String::from("Female") }); fi.add_option(zakform::fields::FOption{ value: String::from("M"), label: String::from("Male") }); - let single = fi.render_single(1); - - f.add_field(zakform::form::TFields::TFieldRadio(fi)); + f.add_field(Box::new(fi)); let fs = f.fields(); for fi in fs { - match fi { - zakform::form::TFields::TFieldText(fi) => { s.push_str(fi.render().as_str()); }, - zakform::form::TFields::TFieldRadio(fi) => { s.push_str(fi.render().as_str()); }, - } + s.push_str(fi.render().as_str()); } - s.push_str(&single); + let mut single = f.get_field("radio").unwrap().any().downcast_ref::().unwrap(); + + /*single.add_option(zakform::fields::FOption{ value: String::from("X"), label: String::from("Unknown") }); + + let single = f.get_field("radio").unwrap().any().downcast_ref::().unwrap(); + + let ssingle = single.render_single(2);*/ + let ssingle = single.render_single(1); + + s.push_str(&ssingle); s.push_str(r#""#); diff --git a/src/fields.rs b/src/fields.rs index 107de22..0bcfe52 100644 --- a/src/fields.rs +++ b/src/fields.rs @@ -1,7 +1,9 @@ -use serde_derive::{Serialize}; - use std::default::Default; +use std::any::Any; + +use serde_derive::{Serialize}; + #[derive(Default)] struct Field { name: String, @@ -15,11 +17,11 @@ struct Field { } pub trait TField { - fn new(name: &str) -> Self; - fn get_name(&self) -> String; fn render(&self) -> String; + + fn any(&self) -> &dyn Any; } #[derive(Default)] @@ -29,7 +31,33 @@ pub struct FieldText { } impl TField for FieldText { - fn new(name: &str) -> Self { + fn get_name(&self) -> String { + String::from(&self.field.name) + } + + fn render(&self) -> String { + let mut s = String::new(); + + let mut context = tera::Context::new(); + context.insert("name", &self.field.name); + context.insert("label", &self.field.label); + context.insert("maxlen", &self.maxlen); + context.insert("disabled", &self.field.disabled); + context.insert("invisible", &self.field.invisible); + context.insert("help", &self.field.help); + context.insert("value", &self.field.value); + s.push_str(self.field.tmpl.render("field", &context).unwrap().as_str()); + + s + } + + fn any(&self) -> &dyn Any { + self + } +} + +impl FieldText { + pub fn new(name: &str) -> Self { let mut f: FieldText = Default::default(); f.field.name = String::from(name); @@ -46,7 +74,21 @@ _ => {}, f } +} + +#[derive(Serialize)] +pub struct FOption { + pub value: String, + pub label: String, +} + +#[derive(Default)] +pub struct FieldRadio { + field: Field, + options: Vec, +} +impl TField for FieldRadio { fn get_name(&self) -> String { String::from(&self.field.name) } @@ -57,31 +99,23 @@ _ => {}, let mut context = tera::Context::new(); context.insert("name", &self.field.name); context.insert("label", &self.field.label); - context.insert("maxlen", &self.maxlen); context.insert("disabled", &self.field.disabled); context.insert("invisible", &self.field.invisible); context.insert("help", &self.field.help); context.insert("value", &self.field.value); + context.insert("options", &self.options); s.push_str(self.field.tmpl.render("field", &context).unwrap().as_str()); s } -} -#[derive(Serialize)] -pub struct FOption { - pub value: String, - pub label: String, -} - -#[derive(Default)] -pub struct FieldRadio { - field: Field, - options: Vec, + fn any(&self) -> &dyn Any { + self + } } -impl TField for FieldRadio { - fn new(name: &str) -> Self { +impl FieldRadio { + pub fn new(name: &str) -> Self { let mut f: FieldRadio = Default::default(); f.field.name = String::from(name); @@ -112,28 +146,6 @@ _ => {}, f } - fn get_name(&self) -> String { - String::from(&self.field.name) - } - - fn render(&self) -> String { - let mut s = String::new(); - - let mut context = tera::Context::new(); - context.insert("name", &self.field.name); - context.insert("label", &self.field.label); - context.insert("disabled", &self.field.disabled); - context.insert("invisible", &self.field.invisible); - context.insert("help", &self.field.help); - context.insert("value", &self.field.value); - context.insert("options", &self.options); - s.push_str(self.field.tmpl.render("field", &context).unwrap().as_str()); - - s - } -} - -impl FieldRadio { pub fn add_option(&mut self, option: FOption) { self.options.push(option); } diff --git a/src/form.rs b/src/form.rs index ed88716..89760dd 100644 --- a/src/form.rs +++ b/src/form.rs @@ -1,12 +1,5 @@ -use super::fields; - -pub enum TFields { - TFieldText(super::fields::FieldText), - TFieldRadio(super::fields::FieldRadio), -} - pub struct Form { - fields: Vec, + fields: Vec>, } impl Form { @@ -16,11 +9,21 @@ impl Form { } } - pub fn add_field(&mut self, field: TFields) { + pub fn add_field(&mut self, field: Box) { self.fields.push(field); } - pub fn fields(&self) -> &Vec { + pub fn fields(&self) -> &Vec> { &self.fields } + + pub fn get_field(&self, field_name: &str) -> Result<&Box, ()> { + for f in &self.fields { + if f.get_name().as_str() == field_name { + return Ok(f); + } + } + + Err(()) + } } -- 2.49.0