1use crate::error::Error;
2use chrono::{DateTime, Utc};
3use lazy_static::lazy_static;
4use regex::Regex;
5use serde::{Deserialize, Serialize};
6use std::{collections::VecDeque, str::FromStr};
7use utoipa::ToSchema;
8use uuid::Uuid;
9use validator::Validate;
10
11lazy_static! {
12 static ref VALID_KEY: Regex = Regex::new(r"^[a-zA-Z0-9._~!$&'()*+,;=:@/?-]+$").unwrap();
13}
14
15#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize, ToSchema)]
16#[serde(untagged)]
17pub enum Value {
18 Array(VecDeque<Value>),
19 Boolean(bool),
20 Integer(i64),
21 String(String),
22}
23
24impl FromStr for Value {
25 type Err = Error;
26
27 fn from_str(s: &str) -> Result<Self, Self::Err> {
28 let mut destination_value = match s.parse::<bool>() {
29 Err(_) => None,
30 Ok(value) => Some(Value::Boolean(value)),
31 };
32
33 if destination_value.is_none() {
34 destination_value = match s.parse::<i64>() {
35 Err(_) => None,
36 Ok(value) => Some(Value::Integer(value)),
37 };
38 }
39
40 if destination_value.is_none() {
41 let splitted_arguments = s.split("::").into_iter().collect::<Vec<&str>>();
42 if splitted_arguments.len() > 1 {
43 let mut splitted_argument_values = VecDeque::new();
44 for splitted_argument in splitted_arguments {
45 let splitted_argument_value = Self::from_str(splitted_argument)?;
46 splitted_argument_values.push_back(splitted_argument_value);
47 }
48 destination_value = Some(Value::Array(splitted_argument_values));
49 }
50 }
51
52 if destination_value.is_none() {
53 destination_value = Some(Value::String(s.to_string()));
54 }
55
56 let value = destination_value.ok_or(Error::ValueParse)?;
57
58 Ok(value)
59 }
60}
61
62#[derive(Clone, Debug, Deserialize, Serialize, ToSchema, Validate)]
63pub struct ValueAppend {
64 pub append: Value,
65}
66
67#[derive(Clone, Debug, Deserialize, Serialize, ToSchema, Validate)]
68pub struct ValueDecrement {
69 pub decrement: Option<i64>,
70}
71
72#[derive(Clone, Debug, Deserialize, Serialize, ToSchema, Validate)]
73pub struct ValueIncrement {
74 pub increment: Option<i64>,
75}
76
77#[derive(Clone, Debug, Deserialize, Serialize, ToSchema, Validate)]
78pub struct ValuePost {
79 #[validate(regex = "VALID_KEY")]
80 pub key: String,
81 pub ttl: Option<i64>,
82 pub value: Value,
83}
84
85#[derive(Clone, Debug, Deserialize, Serialize, ToSchema, Validate)]
86pub struct ValuePopBack {
87 pub pop_back: Option<usize>,
88}
89
90#[derive(Clone, Debug, Deserialize, Serialize, ToSchema, Validate)]
91pub struct ValuePopFront {
92 pub pop_front: Option<usize>,
93}
94
95#[derive(Clone, Debug, Deserialize, Serialize, ToSchema, Validate)]
96pub struct ValuePrepend {
97 pub prepend: Value,
98}
99
100#[derive(Clone, Debug, Deserialize, Serialize, ToSchema, Validate)]
101pub struct ValuePut {
102 pub ttl: Option<i64>,
103 pub value: Value,
104}
105
106#[derive(Clone, Debug, Deserialize, Serialize)]
107pub struct ValueRecord {
108 pub id: Uuid,
109 pub key: String,
110 pub value: Value,
111 pub created_at: DateTime<Utc>,
112 pub delete_at: Option<DateTime<Utc>>,
113 pub updated_at: DateTime<Utc>,
114}
115
116impl ValueRecord {
117 pub fn new(
118 id: Uuid,
119 key: &str,
120 value: &Value,
121 created_at: DateTime<Utc>,
122 delete_at: Option<DateTime<Utc>>,
123 updated_at: DateTime<Utc>,
124 ) -> Self {
125 Self {
126 id,
127 key: key.into(),
128 value: value.clone(),
129 created_at,
130 delete_at,
131 updated_at,
132 }
133 }
134}
135
136#[derive(Clone, Debug, Deserialize, Serialize, ToSchema)]
137pub struct ValueResponse {
138 pub key: String,
139 pub value: Value,
140}
141
142impl From<ValueRecord> for ValueResponse {
143 fn from(db_record: ValueRecord) -> Self {
144 ValueResponse {
145 key: db_record.key,
146 value: db_record.value,
147 }
148 }
149}