1use std::fmt;
51
52use crate::io::{ClickHouseRead, ClickHouseWrite};
53use crate::native::protocol::DBMS_MIN_REVISION_WITH_SETTINGS_SERIALIZED_AS_STRINGS;
54use crate::{Error, Result};
55
56const SETTING_FLAG_IMPORTANT: u64 = 0x01;
57pub(crate) const SETTING_FLAG_CUSTOM: u64 = 0x02;
58
59#[derive(Debug, Clone, PartialEq, PartialOrd)]
81pub enum SettingValue {
82 Int(i64),
83 Bool(bool),
84 Float(f64),
85 String(String),
86}
87
88impl SettingValue {
89 #[allow(unused)]
91 pub(crate) fn unwrap_float(&self) -> f64 {
92 match self {
93 SettingValue::Float(f) => *f,
94 _ => panic!("Expected Float variant"),
95 }
96 }
97}
98
99impl Eq for SettingValue {}
100
101macro_rules! setting_value {
102 ($ty:ident, $inner:ty) => {
103 impl From<$inner> for SettingValue {
104 fn from(value: $inner) -> Self { SettingValue::$ty(value) }
105 }
106 };
107 ($ty:ident, $inner:ty, $override:ty) => {
108 impl From<$override> for SettingValue {
109 #[allow(clippy::cast_lossless)]
110 #[allow(clippy::cast_possible_wrap)]
111 fn from(value: $override) -> Self { SettingValue::$ty(value as $inner) }
112 }
113 };
114 ($ty:ident, $inner:ty, $v:tt => { $override:expr }) => {
115 impl From<$inner> for SettingValue {
116 fn from($v: $inner) -> Self { SettingValue::$ty($override) }
117 }
118 };
119}
120
121setting_value!(Int, i64, u8);
122setting_value!(Int, i64, u16);
123setting_value!(Int, i64, u32);
124setting_value!(Int, i64, u64);
125setting_value!(Int, i64, i8);
126setting_value!(Int, i64, i16);
127setting_value!(Int, i64, i32);
128setting_value!(Int, i64);
129setting_value!(Bool, bool);
130setting_value!(Float, f64, f32);
131setting_value!(Float, f64);
132setting_value!(String, &str, v => { v.to_string() });
133setting_value!(String, Box<str>, v => { v.to_string() });
134setting_value!(String, std::sync::Arc<str>, v => { v.to_string() });
135setting_value!(String, String);
136
137macro_rules! setting_value_array {
139 ($ty:ty) => {
140 impl From<Vec<$ty>> for SettingValue {
141 fn from(value: Vec<$ty>) -> Self {
142 let formatted = value.iter().map(ToString::to_string).collect::<Vec<_>>().join(",");
143 SettingValue::String(format!("[{formatted}]"))
144 }
145 }
146
147 impl From<&[$ty]> for SettingValue {
148 fn from(value: &[$ty]) -> Self {
149 let formatted = value.iter().map(ToString::to_string).collect::<Vec<_>>().join(",");
150 SettingValue::String(format!("[{formatted}]"))
151 }
152 }
153 };
154}
155
156setting_value_array!(i8);
158setting_value_array!(i16);
159setting_value_array!(i32);
160setting_value_array!(i64);
161setting_value_array!(u8);
162setting_value_array!(u16);
163setting_value_array!(u32);
164setting_value_array!(u64);
165setting_value_array!(f32);
166setting_value_array!(f64);
167
168impl From<Vec<String>> for SettingValue {
170 fn from(value: Vec<String>) -> Self {
171 let formatted = value
172 .iter()
173 .map(|s| format!("'{}'", s.replace('\'', "\\'")))
174 .collect::<Vec<_>>()
175 .join(",");
176 SettingValue::String(format!("[{formatted}]"))
177 }
178}
179
180impl From<&[String]> for SettingValue {
181 fn from(value: &[String]) -> Self {
182 let formatted = value
183 .iter()
184 .map(|s| format!("'{}'", s.replace('\'', "\\'")))
185 .collect::<Vec<_>>()
186 .join(",");
187 SettingValue::String(format!("[{formatted}]"))
188 }
189}
190
191impl From<Vec<&str>> for SettingValue {
192 fn from(value: Vec<&str>) -> Self {
193 let formatted = value
194 .iter()
195 .map(|s| format!("'{}'", s.replace('\'', "\\'")))
196 .collect::<Vec<_>>()
197 .join(",");
198 SettingValue::String(format!("[{formatted}]"))
199 }
200}
201
202impl From<&[&str]> for SettingValue {
203 fn from(value: &[&str]) -> Self {
204 let formatted = value
205 .iter()
206 .map(|s| format!("'{}'", s.replace('\'', "\\'")))
207 .collect::<Vec<_>>()
208 .join(",");
209 SettingValue::String(format!("[{formatted}]"))
210 }
211}
212
213impl fmt::Display for SettingValue {
214 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
215 match self {
216 SettingValue::Int(i) => write!(f, "{i}"),
217 SettingValue::Bool(b) => write!(f, "{b}"),
218 SettingValue::Float(fl) => write!(f, "{fl}"),
219 SettingValue::String(s) => write!(f, "{s}"),
220 }
221 }
222}
223
224#[derive(Debug, Clone, PartialEq, PartialOrd)]
242#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
243pub struct Setting {
244 key: String,
245 value: SettingValue,
246 important: bool,
247 custom: bool,
248}
249
250impl Setting {
251 async fn encode<W: ClickHouseWrite>(&self, writer: &mut W, revision: u64) -> Result<()> {
266 tracing::trace!(setting = ?self, "Writing setting");
267
268 if revision <= DBMS_MIN_REVISION_WITH_SETTINGS_SERIALIZED_AS_STRINGS {
269 if !matches!(self.value, SettingValue::Int(_) | SettingValue::Bool(_)) {
270 return Err(Error::UnsupportedSettingType(self.key.clone()));
271 }
272
273 writer.write_string(&self.key).await?;
275
276 #[expect(clippy::cast_sign_loss)]
278 match &self.value {
279 SettingValue::Int(i) => writer.write_var_uint(*i as u64).await?,
280 SettingValue::Bool(b) => writer.write_var_uint(u64::from(*b)).await?,
281 _ => unreachable!("Checked above"),
282 }
283 } else {
284 writer.write_string(&self.key).await?;
286
287 let mut flags = 0u64;
289 if self.important {
290 flags |= SETTING_FLAG_IMPORTANT;
291 }
292 if self.custom {
293 flags |= SETTING_FLAG_CUSTOM;
294 }
295 writer.write_var_uint(flags).await?;
296
297 if self.custom {
299 let field_dump = self.encode_field_dump()?;
300 writer.write_string(&field_dump).await?;
301 } else {
302 writer.write_string(self.value.to_string()).await?;
303 }
304 }
305
306 Ok(())
307 }
308
309 async fn decode<R: ClickHouseRead>(reader: &mut R, key: String) -> Result<Self> {
322 let flags = reader.read_var_uint().await?;
324 let is_important = (flags & SETTING_FLAG_IMPORTANT) != 0;
325 let is_custom = (flags & SETTING_FLAG_CUSTOM) != 0;
326
327 let value = if is_custom {
329 let field_dump = reader.read_string().await?;
331 SettingValue::String(String::from_utf8_lossy(&field_dump).to_string())
332 } else {
333 let value_str = reader.read_string().await?;
335 Self::parse_setting_value(&String::from_utf8_lossy(&value_str))
336 };
337
338 Ok(Setting { key, value, important: is_important, custom: is_custom })
339 }
340
341 fn encode_field_dump(&self) -> Result<String> {
349 match &self.value {
350 SettingValue::String(s) => Ok(s.clone()),
351 _ => Err(Error::UnsupportedFieldType(format!("{:?}", self.value))),
352 }
353 }
354
355 fn parse_setting_value(value_str: &str) -> SettingValue {
366 match value_str.to_lowercase().as_str() {
368 "true" | "1" => return SettingValue::Bool(true),
369 "false" | "0" => return SettingValue::Bool(false),
370 _ => {}
371 }
372
373 if let Ok(int_val) = value_str.parse::<i64>() {
375 return SettingValue::Int(int_val);
376 }
377
378 if let Ok(float_val) = value_str.parse::<f64>() {
380 return SettingValue::Float(float_val);
381 }
382
383 SettingValue::String(value_str.to_string())
385 }
386}
387
388impl<T: Into<String>, U: Into<SettingValue>> From<(T, U)> for Setting {
389 fn from(value: (T, U)) -> Self {
390 Setting {
391 key: value.0.into(),
392 value: value.1.into(),
393 important: false,
394 custom: false,
395 }
396 }
397}
398
399#[derive(Debug, Clone, Default, PartialEq, PartialOrd)]
427#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
428pub struct Settings(pub Vec<Setting>);
429
430impl Settings {
431 pub fn add_setting<S>(&mut self, name: impl Into<String>, setting: S)
449 where
450 SettingValue: From<S>,
451 {
452 let key = name.into();
453 if let Some(current) = self.0.iter_mut().find(|s| s.key == key) {
454 current.value = setting.into();
455 } else {
456 self.0.push(Setting { key, value: setting.into(), important: false, custom: false });
457 }
458 }
459
460 #[must_use]
478 pub fn with_setting<S>(mut self, name: impl Into<String>, setting: S) -> Self
479 where
480 SettingValue: From<S>,
481 {
482 let key = name.into();
483 if let Some(current) = self.0.iter_mut().find(|s| s.key == key) {
484 current.value = setting.into();
485 } else {
486 self.0.push(Setting { key, value: setting.into(), important: false, custom: false });
487 }
488 self
489 }
490
491 pub fn encode_to_key_value_strings(&self) -> Vec<(String, String)> {
504 self.0.iter().map(|setting| (setting.key.clone(), setting.value.to_string())).collect()
505 }
506
507 pub fn encode_to_strings(&self) -> Vec<String> {
520 self.0.iter().map(|setting| format!("{} = {}", setting.key, setting.value)).collect()
521 }
522
523 pub(crate) async fn encode<W: ClickHouseWrite>(
525 &self,
526 writer: &mut W,
527 revision: u64,
528 ) -> Result<()> {
529 for setting in &self.0 {
530 setting.encode(writer, revision).await?;
531 }
532 Ok(())
533 }
534
535 pub(crate) async fn encode_with_ignore<W: ClickHouseWrite>(
537 &self,
538 writer: &mut W,
539 revision: u64,
540 ignore: &Settings,
541 ) -> Result<()> {
542 for setting in &self.0 {
543 if ignore.get(&setting.key).is_some_and(|s| s.value == setting.value) {
544 continue;
545 }
546
547 setting.encode(writer, revision).await?;
548 }
549 Ok(())
550 }
551
552 pub(crate) async fn decode<R: ClickHouseRead>(reader: &mut R) -> Result<Self> {
566 let mut settings = Vec::new();
567 loop {
568 let key = reader.read_string().await?;
570 if key.is_empty() {
572 break;
573 }
574 settings
575 .push(Setting::decode(reader, String::from_utf8_lossy(&key).to_string()).await?);
576 }
577 Ok(Settings(settings))
578 }
579
580 pub(crate) fn get(&self, key: &str) -> Option<&Setting> { self.0.iter().find(|s| s.key == key) }
582}
583
584impl<T, K, S> From<T> for Settings
585where
586 T: IntoIterator<Item = (K, S)>,
587 K: Into<String>,
588 SettingValue: From<S>,
589{
590 fn from(value: T) -> Self {
591 Self(
592 value
593 .into_iter()
594 .map(|(k, v)| Setting {
595 key: k.into(),
596 value: v.into(),
597 important: false,
598 custom: false,
599 })
600 .collect(),
601 )
602 }
603}
604
605impl<K, S> FromIterator<(K, S)> for Settings
606where
607 K: Into<String>,
608 SettingValue: From<S>,
609{
610 fn from_iter<T>(iter: T) -> Self
611 where
612 T: IntoIterator<Item = (K, S)>,
613 {
614 Self::from(iter)
615 }
616}
617
618impl std::ops::Deref for Settings {
619 type Target = [Setting];
620
621 fn deref(&self) -> &Self::Target { &self.0 }
622}
623
624#[cfg(feature = "serde")]
625pub mod deser {
626 use serde::{Deserialize, Serialize};
627
628 use super::*;
629
630 impl Serialize for SettingValue {
631 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
632 where
633 S: serde::Serializer,
634 {
635 match self {
636 SettingValue::Int(i) => ::serde::Serialize::serialize(i, serializer),
637 SettingValue::Bool(b) => ::serde::Serialize::serialize(b, serializer),
638 SettingValue::Float(f) => ::serde::Serialize::serialize(f, serializer),
639 SettingValue::String(s) => ::serde::Serialize::serialize(s, serializer),
640 }
641 }
642 }
643
644 impl<'de> Deserialize<'de> for SettingValue {
645 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
646 where
647 D: serde::Deserializer<'de>,
648 {
649 fn deserialize_setting<'d, De>(deserializer: De) -> Result<SettingValue, De::Error>
650 where
651 De: serde::Deserializer<'d>,
652 {
653 use serde::de::Visitor;
654
655 struct SettingVisitor;
656
657 type Result<E> = std::result::Result<SettingValue, E>;
658
659 impl Visitor<'_> for SettingVisitor {
660 type Value = SettingValue;
661
662 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
663 formatter.write_str("a number, float or string")
664 }
665
666 fn visit_bool<E>(self, value: bool) -> Result<E>
667 where
668 E: serde::de::Error,
669 {
670 Ok(value.into())
671 }
672
673 fn visit_u8<E>(self, value: u8) -> Result<E>
674 where
675 E: serde::de::Error,
676 {
677 Ok(value.into())
678 }
679
680 fn visit_u16<E>(self, value: u16) -> Result<E>
681 where
682 E: serde::de::Error,
683 {
684 Ok(value.into())
685 }
686
687 fn visit_u32<E>(self, value: u32) -> Result<E>
688 where
689 E: serde::de::Error,
690 {
691 Ok(value.into())
692 }
693
694 fn visit_u64<E>(self, value: u64) -> Result<E>
695 where
696 E: serde::de::Error,
697 {
698 Ok(value.into())
699 }
700
701 fn visit_i8<E>(self, value: i8) -> Result<E>
702 where
703 E: serde::de::Error,
704 {
705 Ok(value.into())
706 }
707
708 fn visit_i16<E>(self, value: i16) -> Result<E>
709 where
710 E: serde::de::Error,
711 {
712 Ok(value.into())
713 }
714
715 fn visit_i32<E>(self, value: i32) -> Result<E>
716 where
717 E: serde::de::Error,
718 {
719 Ok(value.into())
720 }
721
722 fn visit_i64<E>(self, value: i64) -> Result<E>
723 where
724 E: serde::de::Error,
725 {
726 Ok(value.into())
727 }
728
729 fn visit_f32<E>(self, value: f32) -> Result<E>
730 where
731 E: serde::de::Error,
732 {
733 Ok(value.into())
734 }
735
736 fn visit_f64<E>(self, value: f64) -> Result<E>
737 where
738 E: serde::de::Error,
739 {
740 Ok(value.into())
741 }
742
743 fn visit_str<E>(self, value: &str) -> Result<E>
744 where
745 E: serde::de::Error,
746 {
747 Ok(value.into())
748 }
749
750 fn visit_string<E>(self, value: String) -> Result<E>
751 where
752 E: serde::de::Error,
753 {
754 self.visit_str(&value)
755 }
756 }
757
758 deserializer.deserialize_any(SettingVisitor)
759 }
760 deserialize_setting(deserializer)
761 }
762 }
763
764 #[cfg(test)]
765 mod tests {
766 use super::*;
767
768 #[test]
769 fn test_setting_value_serialize_deserialize() {
770 let values = vec![
772 SettingValue::Int(42),
773 SettingValue::Bool(true),
774 SettingValue::Float(3.15),
775 SettingValue::String("test".to_string()),
776 ];
777
778 for value in values {
779 let json = serde_json::to_string(&value).unwrap();
781
782 let deserialized: SettingValue = serde_json::from_str(&json).unwrap();
784
785 match (value, deserialized) {
787 (SettingValue::Int(a), SettingValue::Int(b)) => assert_eq!(a, b),
788 (SettingValue::Bool(a), SettingValue::Bool(b)) => assert_eq!(a, b),
789 (SettingValue::Float(a), SettingValue::Float(b)) => {
790 assert!((a - b).abs() < 1e-6);
791 }
792 (SettingValue::String(a), SettingValue::String(b)) => assert_eq!(a, b),
793 _ => panic!("Mismatched variants"),
794 }
795 }
796 }
797
798 #[test]
799 fn test_setting_value_deserialize_variants() {
800 assert_eq!(serde_json::from_str::<SettingValue>("42").unwrap(), SettingValue::Int(42));
802 assert_eq!(
803 serde_json::from_str::<SettingValue>("true").unwrap(),
804 SettingValue::Bool(true)
805 );
806 assert!(
807 (serde_json::from_str::<SettingValue>("3.15").unwrap().unwrap_float() - 3.15).abs()
808 < 1e-6
809 );
810 assert_eq!(
811 serde_json::from_str::<SettingValue>("\"test\"").unwrap(),
812 SettingValue::String("test".to_string())
813 );
814
815 assert_eq!(
817 serde_json::from_str::<SettingValue>("255").unwrap(),
818 SettingValue::Int(255)
819 ); assert_eq!(
821 serde_json::from_str::<SettingValue>("65535").unwrap(),
822 SettingValue::Int(65535)
823 ); assert_eq!(
825 serde_json::from_str::<SettingValue>("4294967295").unwrap(),
826 SettingValue::Int(4_294_967_295)
827 ); assert_eq!(
829 serde_json::from_str::<SettingValue>("-128").unwrap(),
830 SettingValue::Int(-128)
831 ); assert_eq!(
833 serde_json::from_str::<SettingValue>("-32768").unwrap(),
834 SettingValue::Int(-32768)
835 ); assert_eq!(
837 serde_json::from_str::<SettingValue>("-2147483648").unwrap(),
838 SettingValue::Int(-2_147_483_648)
839 ); }
841
842 #[test]
843 fn test_setting_value_deserialize_invalid() {
844 assert!(serde_json::from_str::<SettingValue>("null").is_err());
846 assert!(serde_json::from_str::<SettingValue>("[]").is_err());
847 assert!(serde_json::from_str::<SettingValue>("{}").is_err());
848 }
849 }
850}
851
852#[cfg(test)]
853mod tests {
854 use std::io::Cursor;
855
856 use tokio::io::AsyncWriteExt;
857
858 use super::*;
859 use crate::io::ClickHouseRead;
860
861 type MockWriter = Cursor<Vec<u8>>;
862
863 fn create_setting<S>(key: &str, value: S, important: bool, custom: bool) -> Setting
865 where
866 SettingValue: From<S>,
867 {
868 Setting { key: key.to_string(), value: value.into(), important, custom }
869 }
870
871 #[test]
872 fn test_setting_value_from_primitives() {
873 assert_eq!(SettingValue::from(8_i8), SettingValue::Int(8));
875 assert_eq!(SettingValue::from(8_i16), SettingValue::Int(8));
876 assert_eq!(SettingValue::from(8_i32), SettingValue::Int(8));
877 assert_eq!(SettingValue::from(8_i64), SettingValue::Int(8));
878 assert_eq!(SettingValue::from(8_u8), SettingValue::Int(8));
879 assert_eq!(SettingValue::from(8_u16), SettingValue::Int(8));
880 assert_eq!(SettingValue::from(8_u32), SettingValue::Int(8));
881 assert_eq!(SettingValue::from(8_u64), SettingValue::Int(8));
882 assert_eq!(SettingValue::from(true), SettingValue::Bool(true));
883 assert!((SettingValue::from(3.15_f32).unwrap_float() - 3.15).abs() < 1e-6);
884 assert_eq!(SettingValue::from(3.15_f64), SettingValue::Float(3.15));
885 assert_eq!(SettingValue::from("test"), SettingValue::String("test".to_string()));
886 assert_eq!(
887 SettingValue::from("test".to_string()),
888 SettingValue::String("test".to_string())
889 );
890 assert_eq!(
891 SettingValue::from(Box::<str>::from("test")),
892 SettingValue::String("test".to_string())
893 );
894 assert_eq!(
895 SettingValue::from(std::sync::Arc::<str>::from("test")),
896 SettingValue::String("test".to_string())
897 );
898 }
899
900 #[test]
901 fn test_setting_value_display() {
902 assert_eq!(SettingValue::Int(42).to_string(), "42");
904 assert_eq!(SettingValue::Bool(true).to_string(), "true");
905 assert_eq!(SettingValue::Float(3.15).to_string(), "3.15");
906 assert_eq!(SettingValue::String("test".to_string()).to_string(), "test");
907 }
908
909 #[test]
910 fn test_setting_encode_field_dump() {
911 let setting = create_setting("key", "value", false, true);
913 assert_eq!(setting.encode_field_dump().unwrap(), "value");
914
915 let setting = create_setting("key", "val'ue", false, true);
917 assert_eq!(setting.encode_field_dump().unwrap(), "val'ue");
918
919 let setting = create_setting("key", 42_i32, false, true);
921 assert!(setting.encode_field_dump().is_err());
922 }
923
924 #[tokio::test]
925 async fn test_setting_encode_legacy_revision() {
926 let setting = create_setting("max_threads", 8_i32, false, false);
928 let mut writer = MockWriter::default();
929 setting
930 .encode(&mut writer, DBMS_MIN_REVISION_WITH_SETTINGS_SERIALIZED_AS_STRINGS)
931 .await
932 .unwrap();
933 writer.flush().await.unwrap();
934
935 let mut reader = Cursor::new(writer.into_inner());
937 let key = reader.read_utf8_string().await.unwrap();
938 assert_eq!(key, "max_threads");
939 let value = reader.read_var_uint().await.unwrap();
940 assert_eq!(value, 8);
941
942 let setting = create_setting("allow_experimental", true, false, false);
944 let mut writer = MockWriter::default();
945 setting
946 .encode(&mut writer, DBMS_MIN_REVISION_WITH_SETTINGS_SERIALIZED_AS_STRINGS)
947 .await
948 .unwrap();
949 writer.flush().await.unwrap();
950
951 let mut reader = Cursor::new(writer.into_inner());
952 let key = reader.read_utf8_string().await.unwrap();
953 assert_eq!(key, "allow_experimental");
954 let value = reader.read_var_uint().await.unwrap();
955 assert_eq!(value, 1);
956
957 let setting = create_setting("default_format", "JSON", false, false);
959 let mut writer = MockWriter::default();
960 assert!(matches!(
961 setting
962 .encode(&mut writer, DBMS_MIN_REVISION_WITH_SETTINGS_SERIALIZED_AS_STRINGS)
963 .await,
964 Err(Error::UnsupportedSettingType(key)) if key == "default_format"
965 ));
966 }
967
968 #[tokio::test]
969 async fn test_setting_encode_modern_revision() {
970 let setting = create_setting("max_threads", 8_i32, false, false);
972 let mut writer = MockWriter::default();
973 setting
974 .encode(&mut writer, DBMS_MIN_REVISION_WITH_SETTINGS_SERIALIZED_AS_STRINGS + 1)
975 .await
976 .unwrap();
977 writer.flush().await.unwrap();
978
979 let mut reader = Cursor::new(writer.into_inner());
981 let key = reader.read_utf8_string().await.unwrap();
982 assert_eq!(key, "max_threads");
983 let flags = reader.read_var_uint().await.unwrap();
984 assert_eq!(flags, 0);
985 let value = reader.read_utf8_string().await.unwrap();
986 assert_eq!(value, "8");
987
988 let setting = create_setting("custom_key", "value", true, true);
990 let mut writer = MockWriter::default();
991 setting
992 .encode(&mut writer, DBMS_MIN_REVISION_WITH_SETTINGS_SERIALIZED_AS_STRINGS + 1)
993 .await
994 .unwrap();
995 writer.flush().await.unwrap();
996
997 let mut reader = Cursor::new(writer.into_inner());
998 let key = reader.read_utf8_string().await.unwrap();
999 assert_eq!(key, "custom_key");
1000 let flags = reader.read_var_uint().await.unwrap();
1001 assert_eq!(flags, SETTING_FLAG_IMPORTANT | SETTING_FLAG_CUSTOM);
1002 let value = reader.read_utf8_string().await.unwrap();
1003 assert_eq!(value, "value");
1004 }
1005
1006 #[test]
1007 fn test_settings_add_setting() {
1008 let mut settings = Settings::default();
1009 settings.add_setting("max_threads", 8_i32);
1010 settings.add_setting("default_format", "JSON");
1011
1012 assert_eq!(settings.0.len(), 2);
1013 assert_eq!(settings.0[0].key, "max_threads");
1014 assert_eq!(settings.0[0].value, SettingValue::Int(8));
1015 assert_eq!(settings.0[1].key, "default_format");
1016 assert_eq!(settings.0[1].value, SettingValue::String("JSON".to_string()));
1017 }
1018
1019 #[test]
1020 fn test_settings_from_iterator() {
1021 let settings = Settings::from(vec![
1022 ("max_threads".to_string(), SettingValue::Int(8)),
1023 ("allow_experimental".to_string(), SettingValue::Bool(true)),
1024 ]);
1025
1026 assert_eq!(settings.0.len(), 2);
1027 assert_eq!(settings.0[0].key, "max_threads");
1028 assert_eq!(settings.0[0].value, SettingValue::Int(8));
1029 assert_eq!(settings.0[1].key, "allow_experimental");
1030 assert_eq!(settings.0[1].value, SettingValue::Bool(true));
1031 }
1032
1033 #[test]
1034 fn test_settings_encode_to_key_value_strings() {
1035 let settings = Settings::from(vec![
1036 ("max_threads".to_string(), SettingValue::Int(8)),
1037 ("default_format".to_string(), "JSON".into()),
1038 ]);
1039
1040 let kv_pairs = settings.encode_to_key_value_strings();
1041 assert_eq!(kv_pairs, vec![
1042 ("max_threads".to_string(), "8".to_string()),
1043 ("default_format".to_string(), "JSON".to_string()),
1044 ]);
1045 }
1046
1047 #[test]
1048 fn test_settings_encode_to_strings() {
1049 let settings = Settings::from(vec![
1050 ("max_threads".to_string(), SettingValue::Int(8)),
1051 ("default_format".to_string(), "JSON".into()),
1052 ]);
1053
1054 let strings = settings.encode_to_strings();
1055 assert_eq!(strings, vec!["max_threads = 8", "default_format = JSON"]);
1056 }
1057
1058 #[tokio::test]
1059 async fn test_settings_encode() {
1060 let settings = Settings::from(vec![
1061 ("max_threads".to_string(), SettingValue::Int(8)),
1062 ("allow_experimental".to_string(), SettingValue::Bool(true)),
1063 ]);
1064
1065 let mut writer = MockWriter::default();
1066 settings
1067 .encode(&mut writer, DBMS_MIN_REVISION_WITH_SETTINGS_SERIALIZED_AS_STRINGS + 1)
1068 .await
1069 .unwrap();
1070 writer.write_string("").await.unwrap();
1071 writer.flush().await.unwrap();
1072
1073 let mut reader = Cursor::new(writer.into_inner());
1075 let key1 = reader.read_utf8_string().await.unwrap();
1076 assert_eq!(key1, "max_threads");
1077 let flags1 = reader.read_var_uint().await.unwrap();
1078 assert_eq!(flags1, 0);
1079 let value1 = reader.read_utf8_string().await.unwrap();
1080 assert_eq!(value1, "8");
1081
1082 let key2 = reader.read_utf8_string().await.unwrap();
1083 assert_eq!(key2, "allow_experimental");
1084 let flags2 = reader.read_var_uint().await.unwrap();
1085 assert_eq!(flags2, 0);
1086 let value2 = reader.read_utf8_string().await.unwrap();
1087 assert_eq!(value2, "true");
1088 }
1089
1090 #[test]
1091 fn test_settings_deref() {
1092 let settings = Settings::from(vec![("max_threads".to_string(), 8_i32)]);
1093 let slice: &[Setting] = &settings;
1094 assert_eq!(slice.len(), 1);
1095 assert_eq!(slice[0].key, "max_threads");
1096 }
1097
1098 #[cfg(feature = "serde")]
1099 #[test]
1100 fn test_serde_serialization() {
1101 use serde_json;
1102
1103 let settings = Settings::from(vec![
1104 ("max_threads".to_string(), SettingValue::Int(8)),
1105 ("allow_experimental".to_string(), SettingValue::Bool(true)),
1106 ("default_format".to_string(), "JSON".into()),
1107 ]);
1108
1109 let json = serde_json::to_string(&settings).unwrap();
1110 let deserialized: Settings = serde_json::from_str(&json).unwrap();
1111 assert_eq!(settings, deserialized);
1112
1113 let setting = create_setting("max_threads", 8_i32, true, false);
1115 let json = serde_json::to_string(&setting).unwrap();
1116 let deserialized: Setting = serde_json::from_str(&json).unwrap();
1117 assert_eq!(setting, deserialized);
1118 }
1119
1120 #[tokio::test]
1121 async fn test_settings_decode_empty() {
1122 let mut writer = Cursor::new(Vec::new());
1124
1125 writer.write_string("").await.unwrap();
1127 writer.flush().await.unwrap();
1128
1129 let mut reader = Cursor::new(writer.into_inner());
1130 let settings = Settings::decode(&mut reader).await.unwrap();
1131
1132 assert_eq!(settings.0.len(), 0);
1133 }
1134
1135 #[tokio::test]
1136 async fn test_settings_decode_single_standard_setting() {
1137 let mut writer = MockWriter::default();
1139
1140 writer.write_string("max_threads").await.unwrap();
1142 writer.write_var_uint(0).await.unwrap(); writer.write_string("8").await.unwrap();
1144 writer.write_string("").await.unwrap(); writer.flush().await.unwrap();
1146
1147 let mut reader = Cursor::new(writer.into_inner());
1148 let settings = Settings::decode(&mut reader).await.unwrap();
1149
1150 assert_eq!(settings.0.len(), 1);
1151 assert_eq!(settings.0[0].key, "max_threads");
1152 assert_eq!(settings.0[0].value, SettingValue::Int(8));
1153 assert!(!settings.0[0].important);
1154 assert!(!settings.0[0].custom);
1155 }
1156
1157 #[tokio::test]
1158 async fn test_settings_decode_custom_setting() {
1159 let mut writer = MockWriter::default();
1161
1162 writer.write_string("custom_setting").await.unwrap();
1164 writer.write_var_uint(SETTING_FLAG_CUSTOM).await.unwrap();
1165 writer.write_string("custom_value").await.unwrap();
1166 writer.write_string("").await.unwrap(); writer.flush().await.unwrap();
1168
1169 let mut reader = Cursor::new(writer.into_inner());
1170 let settings = Settings::decode(&mut reader).await.unwrap();
1171
1172 assert_eq!(settings.0.len(), 1);
1173 assert_eq!(settings.0[0].key, "custom_setting");
1174 assert_eq!(settings.0[0].value, SettingValue::String("custom_value".to_string()));
1175 assert!(!settings.0[0].important);
1176 assert!(settings.0[0].custom);
1177 }
1178
1179 #[tokio::test]
1180 async fn test_settings_decode_important_setting() {
1181 let mut writer = MockWriter::default();
1183
1184 writer.write_string("critical_setting").await.unwrap();
1186 writer.write_var_uint(SETTING_FLAG_IMPORTANT).await.unwrap();
1187 writer.write_string("true").await.unwrap();
1188 writer.write_string("").await.unwrap(); writer.flush().await.unwrap();
1190
1191 let mut reader = Cursor::new(writer.into_inner());
1192 let settings = Settings::decode(&mut reader).await.unwrap();
1193
1194 assert_eq!(settings.0.len(), 1);
1195 assert_eq!(settings.0[0].key, "critical_setting");
1196 assert_eq!(settings.0[0].value, SettingValue::Bool(true));
1197 assert!(settings.0[0].important);
1198 assert!(!settings.0[0].custom);
1199 }
1200
1201 #[tokio::test]
1202 async fn test_settings_decode_multiple_settings() {
1203 let mut writer = MockWriter::default();
1205
1206 writer.write_string("max_threads").await.unwrap();
1208 writer.write_var_uint(0).await.unwrap();
1209 writer.write_string("4").await.unwrap();
1210
1211 writer.write_string("allow_experimental").await.unwrap();
1213 writer.write_var_uint(SETTING_FLAG_IMPORTANT).await.unwrap();
1214 writer.write_string("false").await.unwrap();
1215
1216 writer.write_string("custom_config").await.unwrap();
1218 writer.write_var_uint(SETTING_FLAG_CUSTOM).await.unwrap();
1219 writer.write_string("custom_data").await.unwrap();
1220
1221 writer.write_string("important_custom").await.unwrap();
1223 writer.write_var_uint(SETTING_FLAG_IMPORTANT | SETTING_FLAG_CUSTOM).await.unwrap();
1224 writer.write_string("special_value").await.unwrap();
1225
1226 writer.write_string("timeout_ratio").await.unwrap();
1228 writer.write_var_uint(0).await.unwrap();
1229 writer.write_string("1.5").await.unwrap();
1230
1231 writer.write_string("").await.unwrap();
1233 writer.flush().await.unwrap();
1234
1235 let mut reader = Cursor::new(writer.into_inner());
1236 let settings = Settings::decode(&mut reader).await.unwrap();
1237
1238 assert_eq!(settings.0.len(), 5);
1239
1240 assert_eq!(settings.0[0].key, "max_threads");
1242 assert_eq!(settings.0[0].value, SettingValue::Int(4));
1243 assert!(!settings.0[0].important);
1244 assert!(!settings.0[0].custom);
1245
1246 assert_eq!(settings.0[1].key, "allow_experimental");
1248 assert_eq!(settings.0[1].value, SettingValue::Bool(false));
1249 assert!(settings.0[1].important);
1250 assert!(!settings.0[1].custom);
1251
1252 assert_eq!(settings.0[2].key, "custom_config");
1254 assert_eq!(settings.0[2].value, SettingValue::String("custom_data".to_string()));
1255 assert!(!settings.0[2].important);
1256 assert!(settings.0[2].custom);
1257
1258 assert_eq!(settings.0[3].key, "important_custom");
1260 assert_eq!(settings.0[3].value, SettingValue::String("special_value".to_string()));
1261 assert!(settings.0[3].important);
1262 assert!(settings.0[3].custom);
1263
1264 assert_eq!(settings.0[4].key, "timeout_ratio");
1266 assert_eq!(settings.0[4].value, SettingValue::Float(1.5));
1267 assert!(!settings.0[4].important);
1268 assert!(!settings.0[4].custom);
1269 }
1270
1271 #[tokio::test]
1272 async fn test_settings_decode_parse_setting_value_edge_cases() {
1273 let mut writer = MockWriter::default();
1275
1276 writer.write_string("bool_zero").await.unwrap();
1278 writer.write_var_uint(0).await.unwrap();
1279 writer.write_string("0").await.unwrap();
1280
1281 writer.write_string("bool_one").await.unwrap();
1283 writer.write_var_uint(0).await.unwrap();
1284 writer.write_string("1").await.unwrap();
1285
1286 writer.write_string("negative_int").await.unwrap();
1288 writer.write_var_uint(0).await.unwrap();
1289 writer.write_string("-42").await.unwrap();
1290
1291 writer.write_string("string_val").await.unwrap();
1293 writer.write_var_uint(0).await.unwrap();
1294 writer.write_string("not_a_number").await.unwrap();
1295
1296 writer.write_string("empty_val").await.unwrap();
1298 writer.write_var_uint(0).await.unwrap();
1299 writer.write_string("").await.unwrap();
1300
1301 writer.write_string("").await.unwrap();
1303 writer.flush().await.unwrap();
1304
1305 let mut reader = Cursor::new(writer.into_inner());
1306 let settings = Settings::decode(&mut reader).await.unwrap();
1307
1308 assert_eq!(settings.0.len(), 5);
1309 assert_eq!(settings.0[0].value, SettingValue::Bool(false)); assert_eq!(settings.0[1].value, SettingValue::Bool(true)); assert_eq!(settings.0[2].value, SettingValue::Int(-42)); assert_eq!(settings.0[3].value, SettingValue::String("not_a_number".to_string())); assert_eq!(settings.0[4].value, SettingValue::String(String::new())); }
1315
1316 #[tokio::test]
1317 async fn test_settings_decode_roundtrip() {
1318 let original_settings = Settings::from(vec![
1320 ("max_threads".to_string(), SettingValue::Int(8)),
1321 ("allow_experimental".to_string(), SettingValue::Bool(true)),
1322 ("custom_setting".to_string(), SettingValue::String("custom_value".to_string())),
1323 ]);
1324
1325 let mut settings_with_custom = original_settings.clone();
1327 settings_with_custom.0[2].custom = true;
1328 settings_with_custom.0[1].important = true;
1329
1330 let mut writer = MockWriter::default();
1332 settings_with_custom
1333 .encode(&mut writer, DBMS_MIN_REVISION_WITH_SETTINGS_SERIALIZED_AS_STRINGS + 1)
1334 .await
1335 .unwrap();
1336 writer.write_string("").await.unwrap();
1337 writer.flush().await.unwrap();
1338
1339 let mut reader = Cursor::new(writer.into_inner());
1341
1342 let decoded_settings = Settings::decode(&mut reader).await.unwrap();
1343
1344 assert_eq!(decoded_settings.0.len(), 3);
1346 assert_eq!(decoded_settings.0[0].key, "max_threads");
1347 assert_eq!(decoded_settings.0[0].value, SettingValue::Int(8));
1348 assert!(!decoded_settings.0[0].important);
1349 assert!(!decoded_settings.0[0].custom);
1350
1351 assert_eq!(decoded_settings.0[1].key, "allow_experimental");
1352 assert_eq!(decoded_settings.0[1].value, SettingValue::Bool(true));
1353 assert!(decoded_settings.0[1].important);
1354 assert!(!decoded_settings.0[1].custom);
1355
1356 assert_eq!(decoded_settings.0[2].key, "custom_setting");
1357 assert_eq!(decoded_settings.0[2].value, SettingValue::String("custom_value".to_string()));
1358 assert!(!decoded_settings.0[2].important);
1359 assert!(decoded_settings.0[2].custom);
1360 }
1361
1362 #[test]
1363 fn test_from_iterator_no_stack_overflow() {
1364 let data = vec![
1368 ("param1", SettingValue::from("value1")),
1369 ("param2", SettingValue::from(42_i32)),
1370 ("param3", SettingValue::from(true)),
1371 ];
1372
1373 let settings: Settings = data.into_iter().collect();
1375
1376 assert_eq!(settings.0.len(), 3);
1377 assert_eq!(settings.0[0].key, "param1");
1378 assert_eq!(settings.0[0].value, SettingValue::String("value1".to_string()));
1379 assert_eq!(settings.0[1].key, "param2");
1380 assert_eq!(settings.0[1].value, SettingValue::Int(42));
1381 assert_eq!(settings.0[2].key, "param3");
1382 assert_eq!(settings.0[2].value, SettingValue::Bool(true));
1383 }
1384
1385 #[test]
1386 fn test_setting_value_from_integer_arrays() {
1387 assert_eq!(
1389 SettingValue::from(vec![1_i32, 2_i32, 3_i32]),
1390 SettingValue::String("[1,2,3]".to_string())
1391 );
1392 assert_eq!(
1393 SettingValue::from(vec![1_i64, 2_i64, 3_i64]),
1394 SettingValue::String("[1,2,3]".to_string())
1395 );
1396 assert_eq!(
1397 SettingValue::from(vec![1_u32, 2_u32, 3_u32]),
1398 SettingValue::String("[1,2,3]".to_string())
1399 );
1400
1401 let arr = [1_i32, 2_i32, 3_i32];
1403 assert_eq!(SettingValue::from(&arr[..]), SettingValue::String("[1,2,3]".to_string()));
1404
1405 assert_eq!(SettingValue::from(Vec::<i32>::new()), SettingValue::String("[]".to_string()));
1407 }
1408
1409 #[test]
1410 fn test_setting_value_from_float_arrays() {
1411 assert_eq!(
1412 SettingValue::from(vec![1.5_f64, 2.5_f64, 3.15_f64]),
1413 SettingValue::String("[1.5,2.5,3.15]".to_string())
1414 );
1415 assert_eq!(
1416 SettingValue::from(vec![1.5_f32, 2.5_f32]),
1417 SettingValue::String("[1.5,2.5]".to_string())
1418 );
1419
1420 let arr = [1.5_f64, 2.5_f64];
1422 assert_eq!(SettingValue::from(&arr[..]), SettingValue::String("[1.5,2.5]".to_string()));
1423 }
1424
1425 #[test]
1426 fn test_setting_value_from_string_arrays() {
1427 assert_eq!(
1429 SettingValue::from(vec!["a".to_string(), "b".to_string(), "c".to_string()]),
1430 SettingValue::String("['a','b','c']".to_string())
1431 );
1432
1433 assert_eq!(
1435 SettingValue::from(vec!["a", "b", "c"]),
1436 SettingValue::String("['a','b','c']".to_string())
1437 );
1438
1439 let arr = ["a", "b", "c"];
1441 assert_eq!(SettingValue::from(&arr[..]), SettingValue::String("['a','b','c']".to_string()));
1442
1443 assert_eq!(
1445 SettingValue::from(vec!["it's", "a", "test"]),
1446 SettingValue::String("['it\\'s','a','test']".to_string())
1447 );
1448
1449 assert_eq!(
1451 SettingValue::from(Vec::<String>::new()),
1452 SettingValue::String("[]".to_string())
1453 );
1454 }
1455
1456 #[test]
1457 fn test_setting_value_array_edge_cases() {
1458 assert_eq!(SettingValue::from(vec![42_i32]), SettingValue::String("[42]".to_string()));
1460
1461 assert_eq!(
1463 SettingValue::from(vec![i64::MAX, i64::MIN]),
1464 SettingValue::String(format!("[{},{}]", i64::MAX, i64::MIN))
1465 );
1466
1467 assert_eq!(
1469 SettingValue::from(vec!["'quoted'", "normal"]),
1470 SettingValue::String("['\\'quoted\\'','normal']".to_string())
1471 );
1472 }
1473}