use std::collections::BTreeMap;
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct FormValues {
values: BTreeMap<String, FormValue>,
}
impl FormValues {
pub fn new() -> Self {
Self::default()
}
pub fn is_empty(&self) -> bool {
self.values.is_empty()
}
pub fn len(&self) -> usize {
self.values.len()
}
pub fn get(&self, key: &str) -> Option<&FormValue> {
self.values.get(key)
}
pub fn text(&self, key: &str) -> Option<&str> {
self.get(key).and_then(FormValue::as_text)
}
pub fn list(&self, key: &str) -> Option<&[String]> {
self.get(key).and_then(FormValue::as_list)
}
pub fn rows(&self, key: &str) -> Option<&[FormValues]> {
self.get(key).and_then(FormValue::as_rows)
}
pub fn contains(&self, key: &str) -> bool {
self.values.contains_key(key)
}
pub fn insert(
&mut self,
key: impl Into<String>,
value: impl Into<FormValue>,
) -> Option<FormValue> {
self.values.insert(key.into(), value.into())
}
pub fn remove(&mut self, key: &str) -> Option<FormValue> {
self.values.remove(key)
}
pub fn keys(&self) -> impl Iterator<Item = &str> {
self.values.keys().map(String::as_str)
}
pub fn iter(&self) -> impl Iterator<Item = (&str, &FormValue)> {
self.values.iter().map(|(key, value)| (key.as_str(), value))
}
}
impl<K: Into<String>, V: Into<FormValue>> FromIterator<(K, V)> for FormValues {
fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
let mut values = Self::new();
values.extend(iter);
values
}
}
impl<K: Into<String>, V: Into<FormValue>> Extend<(K, V)> for FormValues {
fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
for (key, value) in iter {
self.insert(key, value);
}
}
}
impl IntoIterator for FormValues {
type Item = (String, FormValue);
type IntoIter = std::collections::btree_map::IntoIter<String, FormValue>;
fn into_iter(self) -> Self::IntoIter {
self.values.into_iter()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum FormValue {
Text(String),
List(Vec<String>),
Rows(Vec<FormValues>),
}
impl FormValue {
pub fn as_text(&self) -> Option<&str> {
match self {
Self::Text(text) => Some(text),
_ => None,
}
}
pub fn as_list(&self) -> Option<&[String]> {
match self {
Self::List(items) => Some(items),
_ => None,
}
}
pub fn as_rows(&self) -> Option<&[FormValues]> {
match self {
Self::Rows(rows) => Some(rows),
_ => None,
}
}
}
impl From<String> for FormValue {
fn from(text: String) -> Self {
Self::Text(text)
}
}
impl From<&str> for FormValue {
fn from(text: &str) -> Self {
Self::Text(text.to_string())
}
}
impl From<&String> for FormValue {
fn from(text: &String) -> Self {
Self::Text(text.clone())
}
}
impl From<Vec<String>> for FormValue {
fn from(items: Vec<String>) -> Self {
Self::List(items)
}
}
impl From<Vec<FormValues>> for FormValue {
fn from(rows: Vec<FormValues>) -> Self {
Self::Rows(rows)
}
}