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;
57const 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
137impl fmt::Display for SettingValue {
138 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139 match self {
140 SettingValue::Int(i) => write!(f, "{i}"),
141 SettingValue::Bool(b) => write!(f, "{b}"),
142 SettingValue::Float(fl) => write!(f, "{fl}"),
143 SettingValue::String(s) => write!(f, "{s}"),
144 }
145 }
146}
147
148#[derive(Debug, Clone, PartialEq, PartialOrd)]
166#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
167pub struct Setting {
168 key: String,
169 value: SettingValue,
170 important: bool,
171 custom: bool,
172}
173
174impl Setting {
175 async fn encode<W: ClickHouseWrite>(&self, writer: &mut W, revision: u64) -> Result<()> {
190 tracing::trace!(setting = ?self, "Writing setting");
191
192 if revision <= DBMS_MIN_REVISION_WITH_SETTINGS_SERIALIZED_AS_STRINGS {
193 if !matches!(self.value, SettingValue::Int(_) | SettingValue::Bool(_)) {
194 return Err(Error::UnsupportedSettingType(self.key.clone()));
195 }
196
197 writer.write_string(&self.key).await?;
199
200 #[expect(clippy::cast_sign_loss)]
202 match &self.value {
203 SettingValue::Int(i) => writer.write_var_uint(*i as u64).await?,
204 SettingValue::Bool(b) => writer.write_var_uint(u64::from(*b)).await?,
205 _ => unreachable!("Checked above"),
206 }
207 } else {
208 writer.write_string(&self.key).await?;
210
211 let mut flags = 0u64;
213 if self.important {
214 flags |= SETTING_FLAG_IMPORTANT;
215 }
216 if self.custom {
217 flags |= SETTING_FLAG_CUSTOM;
218 }
219 writer.write_var_uint(flags).await?;
220
221 if self.custom {
223 let field_dump = self.encode_field_dump()?;
224 writer.write_string(&field_dump).await?;
225 } else {
226 writer.write_string(self.value.to_string()).await?;
227 }
228 }
229
230 Ok(())
231 }
232
233 async fn decode<R: ClickHouseRead>(reader: &mut R, key: String) -> Result<Self> {
246 let flags = reader.read_var_uint().await?;
248 let is_important = (flags & SETTING_FLAG_IMPORTANT) != 0;
249 let is_custom = (flags & SETTING_FLAG_CUSTOM) != 0;
250
251 let value = if is_custom {
253 let field_dump = reader.read_string().await?;
255 SettingValue::String(String::from_utf8_lossy(&field_dump).to_string())
256 } else {
257 let value_str = reader.read_string().await?;
259 Self::parse_setting_value(&String::from_utf8_lossy(&value_str))
260 };
261
262 Ok(Setting { key, value, important: is_important, custom: is_custom })
263 }
264
265 fn encode_field_dump(&self) -> Result<String> {
273 match &self.value {
274 SettingValue::String(s) => Ok(s.clone()),
275 _ => Err(Error::UnsupportedFieldType(format!("{:?}", self.value))),
276 }
277 }
278
279 fn parse_setting_value(value_str: &str) -> SettingValue {
290 match value_str.to_lowercase().as_str() {
292 "true" | "1" => return SettingValue::Bool(true),
293 "false" | "0" => return SettingValue::Bool(false),
294 _ => {}
295 }
296
297 if let Ok(int_val) = value_str.parse::<i64>() {
299 return SettingValue::Int(int_val);
300 }
301
302 if let Ok(float_val) = value_str.parse::<f64>() {
304 return SettingValue::Float(float_val);
305 }
306
307 SettingValue::String(value_str.to_string())
309 }
310}
311
312impl<T: Into<String>, U: Into<SettingValue>> From<(T, U)> for Setting {
313 fn from(value: (T, U)) -> Self {
314 Setting {
315 key: value.0.into(),
316 value: value.1.into(),
317 important: false,
318 custom: false,
319 }
320 }
321}
322
323#[derive(Debug, Clone, Default, PartialEq, PartialOrd)]
351#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
352pub struct Settings(pub Vec<Setting>);
353
354impl Settings {
355 pub fn add_setting<S>(&mut self, name: impl Into<String>, setting: S)
373 where
374 SettingValue: From<S>,
375 {
376 let key = name.into();
377 if let Some(current) = self.0.iter_mut().find(|s| s.key == key) {
378 current.value = setting.into();
379 } else {
380 self.0.push(Setting { key, value: setting.into(), important: false, custom: false });
381 }
382 }
383
384 #[must_use]
402 pub fn with_setting<S>(mut self, name: impl Into<String>, setting: S) -> Self
403 where
404 SettingValue: From<S>,
405 {
406 let key = name.into();
407 if let Some(current) = self.0.iter_mut().find(|s| s.key == key) {
408 current.value = setting.into();
409 } else {
410 self.0.push(Setting { key, value: setting.into(), important: false, custom: false });
411 }
412 self
413 }
414
415 pub fn encode_to_key_value_strings(&self) -> Vec<(String, String)> {
428 self.0.iter().map(|setting| (setting.key.clone(), setting.value.to_string())).collect()
429 }
430
431 pub fn encode_to_strings(&self) -> Vec<String> {
444 self.0.iter().map(|setting| format!("{} = {}", setting.key, setting.value)).collect()
445 }
446
447 pub(crate) async fn encode<W: ClickHouseWrite>(
449 &self,
450 writer: &mut W,
451 revision: u64,
452 ) -> Result<()> {
453 for setting in &self.0 {
454 setting.encode(writer, revision).await?;
455 }
456 Ok(())
457 }
458
459 pub(crate) async fn encode_with_ignore<W: ClickHouseWrite>(
461 &self,
462 writer: &mut W,
463 revision: u64,
464 ignore: &Settings,
465 ) -> Result<()> {
466 for setting in &self.0 {
467 if ignore.get(&setting.key).is_some_and(|s| s.value == setting.value) {
468 continue;
469 }
470
471 setting.encode(writer, revision).await?;
472 }
473 Ok(())
474 }
475
476 pub(crate) async fn decode<R: ClickHouseRead>(reader: &mut R) -> Result<Self> {
490 let mut settings = Vec::new();
491 loop {
492 let key = reader.read_string().await?;
494 if key.is_empty() {
496 break;
497 }
498 settings
499 .push(Setting::decode(reader, String::from_utf8_lossy(&key).to_string()).await?);
500 }
501 Ok(Settings(settings))
502 }
503
504 pub(crate) fn get(&self, key: &str) -> Option<&Setting> { self.0.iter().find(|s| s.key == key) }
506}
507
508impl<T, K, S> From<T> for Settings
509where
510 T: IntoIterator<Item = (K, S)>,
511 K: Into<String>,
512 SettingValue: From<S>,
513{
514 fn from(value: T) -> Self {
515 Self(
516 value
517 .into_iter()
518 .map(|(k, v)| Setting {
519 key: k.into(),
520 value: v.into(),
521 important: false,
522 custom: false,
523 })
524 .collect(),
525 )
526 }
527}
528
529impl<K, S> FromIterator<(K, S)> for Settings
530where
531 K: Into<String>,
532 SettingValue: From<S>,
533{
534 fn from_iter<T>(iter: T) -> Self
535 where
536 T: IntoIterator<Item = (K, S)>,
537 {
538 iter.into_iter().collect()
539 }
540}
541
542impl std::ops::Deref for Settings {
543 type Target = [Setting];
544
545 fn deref(&self) -> &Self::Target { &self.0 }
546}
547
548#[cfg(feature = "serde")]
549pub mod deser {
550 use serde::{Deserialize, Serialize};
551
552 use super::*;
553
554 impl Serialize for SettingValue {
555 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
556 where
557 S: serde::Serializer,
558 {
559 match self {
560 SettingValue::Int(i) => ::serde::Serialize::serialize(i, serializer),
561 SettingValue::Bool(b) => ::serde::Serialize::serialize(b, serializer),
562 SettingValue::Float(f) => ::serde::Serialize::serialize(f, serializer),
563 SettingValue::String(s) => ::serde::Serialize::serialize(s, serializer),
564 }
565 }
566 }
567
568 impl<'de> Deserialize<'de> for SettingValue {
569 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
570 where
571 D: serde::Deserializer<'de>,
572 {
573 fn deserialize_setting<'d, De>(deserializer: De) -> Result<SettingValue, De::Error>
574 where
575 De: serde::Deserializer<'d>,
576 {
577 use serde::de::Visitor;
578
579 struct SettingVisitor;
580
581 type Result<E> = std::result::Result<SettingValue, E>;
582
583 impl Visitor<'_> for SettingVisitor {
584 type Value = SettingValue;
585
586 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
587 formatter.write_str("a number, float or string")
588 }
589
590 fn visit_bool<E>(self, value: bool) -> Result<E>
591 where
592 E: serde::de::Error,
593 {
594 Ok(value.into())
595 }
596
597 fn visit_u8<E>(self, value: u8) -> Result<E>
598 where
599 E: serde::de::Error,
600 {
601 Ok(value.into())
602 }
603
604 fn visit_u16<E>(self, value: u16) -> Result<E>
605 where
606 E: serde::de::Error,
607 {
608 Ok(value.into())
609 }
610
611 fn visit_u32<E>(self, value: u32) -> Result<E>
612 where
613 E: serde::de::Error,
614 {
615 Ok(value.into())
616 }
617
618 fn visit_u64<E>(self, value: u64) -> Result<E>
619 where
620 E: serde::de::Error,
621 {
622 Ok(value.into())
623 }
624
625 fn visit_i8<E>(self, value: i8) -> Result<E>
626 where
627 E: serde::de::Error,
628 {
629 Ok(value.into())
630 }
631
632 fn visit_i16<E>(self, value: i16) -> Result<E>
633 where
634 E: serde::de::Error,
635 {
636 Ok(value.into())
637 }
638
639 fn visit_i32<E>(self, value: i32) -> Result<E>
640 where
641 E: serde::de::Error,
642 {
643 Ok(value.into())
644 }
645
646 fn visit_i64<E>(self, value: i64) -> Result<E>
647 where
648 E: serde::de::Error,
649 {
650 Ok(value.into())
651 }
652
653 fn visit_f32<E>(self, value: f32) -> Result<E>
654 where
655 E: serde::de::Error,
656 {
657 Ok(value.into())
658 }
659
660 fn visit_f64<E>(self, value: f64) -> Result<E>
661 where
662 E: serde::de::Error,
663 {
664 Ok(value.into())
665 }
666
667 fn visit_str<E>(self, value: &str) -> Result<E>
668 where
669 E: serde::de::Error,
670 {
671 Ok(value.into())
672 }
673
674 fn visit_string<E>(self, value: String) -> Result<E>
675 where
676 E: serde::de::Error,
677 {
678 self.visit_str(&value)
679 }
680 }
681
682 deserializer.deserialize_any(SettingVisitor)
683 }
684 deserialize_setting(deserializer)
685 }
686 }
687
688 #[cfg(test)]
689 mod tests {
690 use super::*;
691
692 #[test]
693 fn test_setting_value_serialize_deserialize() {
694 let values = vec![
696 SettingValue::Int(42),
697 SettingValue::Bool(true),
698 SettingValue::Float(3.15),
699 SettingValue::String("test".to_string()),
700 ];
701
702 for value in values {
703 let json = serde_json::to_string(&value).unwrap();
705
706 let deserialized: SettingValue = serde_json::from_str(&json).unwrap();
708
709 match (value, deserialized) {
711 (SettingValue::Int(a), SettingValue::Int(b)) => assert_eq!(a, b),
712 (SettingValue::Bool(a), SettingValue::Bool(b)) => assert_eq!(a, b),
713 (SettingValue::Float(a), SettingValue::Float(b)) => {
714 assert!((a - b).abs() < 1e-6);
715 }
716 (SettingValue::String(a), SettingValue::String(b)) => assert_eq!(a, b),
717 _ => panic!("Mismatched variants"),
718 }
719 }
720 }
721
722 #[test]
723 fn test_setting_value_deserialize_variants() {
724 assert_eq!(serde_json::from_str::<SettingValue>("42").unwrap(), SettingValue::Int(42));
726 assert_eq!(
727 serde_json::from_str::<SettingValue>("true").unwrap(),
728 SettingValue::Bool(true)
729 );
730 assert!(
731 (serde_json::from_str::<SettingValue>("3.15").unwrap().unwrap_float() - 3.15).abs()
732 < 1e-6
733 );
734 assert_eq!(
735 serde_json::from_str::<SettingValue>("\"test\"").unwrap(),
736 SettingValue::String("test".to_string())
737 );
738
739 assert_eq!(
741 serde_json::from_str::<SettingValue>("255").unwrap(),
742 SettingValue::Int(255)
743 ); assert_eq!(
745 serde_json::from_str::<SettingValue>("65535").unwrap(),
746 SettingValue::Int(65535)
747 ); assert_eq!(
749 serde_json::from_str::<SettingValue>("4294967295").unwrap(),
750 SettingValue::Int(4_294_967_295)
751 ); assert_eq!(
753 serde_json::from_str::<SettingValue>("-128").unwrap(),
754 SettingValue::Int(-128)
755 ); assert_eq!(
757 serde_json::from_str::<SettingValue>("-32768").unwrap(),
758 SettingValue::Int(-32768)
759 ); assert_eq!(
761 serde_json::from_str::<SettingValue>("-2147483648").unwrap(),
762 SettingValue::Int(-2_147_483_648)
763 ); }
765
766 #[test]
767 fn test_setting_value_deserialize_invalid() {
768 assert!(serde_json::from_str::<SettingValue>("null").is_err());
770 assert!(serde_json::from_str::<SettingValue>("[]").is_err());
771 assert!(serde_json::from_str::<SettingValue>("{}").is_err());
772 }
773 }
774}
775
776#[cfg(test)]
777mod tests {
778 use std::io::Cursor;
779
780 use tokio::io::AsyncWriteExt;
781
782 use super::*;
783 use crate::io::ClickHouseRead;
784
785 type MockWriter = Cursor<Vec<u8>>;
786
787 fn create_setting<S>(key: &str, value: S, important: bool, custom: bool) -> Setting
789 where
790 SettingValue: From<S>,
791 {
792 Setting { key: key.to_string(), value: value.into(), important, custom }
793 }
794
795 #[test]
796 fn test_setting_value_from_primitives() {
797 assert_eq!(SettingValue::from(8_i8), SettingValue::Int(8));
799 assert_eq!(SettingValue::from(8_i16), SettingValue::Int(8));
800 assert_eq!(SettingValue::from(8_i32), SettingValue::Int(8));
801 assert_eq!(SettingValue::from(8_i64), SettingValue::Int(8));
802 assert_eq!(SettingValue::from(8_u8), SettingValue::Int(8));
803 assert_eq!(SettingValue::from(8_u16), SettingValue::Int(8));
804 assert_eq!(SettingValue::from(8_u32), SettingValue::Int(8));
805 assert_eq!(SettingValue::from(8_u64), SettingValue::Int(8));
806 assert_eq!(SettingValue::from(true), SettingValue::Bool(true));
807 assert!((SettingValue::from(3.15_f32).unwrap_float() - 3.15).abs() < 1e-6);
808 assert_eq!(SettingValue::from(3.15_f64), SettingValue::Float(3.15));
809 assert_eq!(SettingValue::from("test"), SettingValue::String("test".to_string()));
810 assert_eq!(
811 SettingValue::from("test".to_string()),
812 SettingValue::String("test".to_string())
813 );
814 assert_eq!(
815 SettingValue::from(Box::<str>::from("test")),
816 SettingValue::String("test".to_string())
817 );
818 assert_eq!(
819 SettingValue::from(std::sync::Arc::<str>::from("test")),
820 SettingValue::String("test".to_string())
821 );
822 }
823
824 #[test]
825 fn test_setting_value_display() {
826 assert_eq!(SettingValue::Int(42).to_string(), "42");
828 assert_eq!(SettingValue::Bool(true).to_string(), "true");
829 assert_eq!(SettingValue::Float(3.15).to_string(), "3.15");
830 assert_eq!(SettingValue::String("test".to_string()).to_string(), "test");
831 }
832
833 #[test]
834 fn test_setting_encode_field_dump() {
835 let setting = create_setting("key", "value", false, true);
837 assert_eq!(setting.encode_field_dump().unwrap(), "value");
838
839 let setting = create_setting("key", "val'ue", false, true);
841 assert_eq!(setting.encode_field_dump().unwrap(), "val'ue");
842
843 let setting = create_setting("key", 42_i32, false, true);
845 assert!(setting.encode_field_dump().is_err());
846 }
847
848 #[tokio::test]
849 async fn test_setting_encode_legacy_revision() {
850 let setting = create_setting("max_threads", 8_i32, false, false);
852 let mut writer = MockWriter::default();
853 setting
854 .encode(&mut writer, DBMS_MIN_REVISION_WITH_SETTINGS_SERIALIZED_AS_STRINGS)
855 .await
856 .unwrap();
857 writer.flush().await.unwrap();
858
859 let mut reader = Cursor::new(writer.into_inner());
861 let key = reader.read_utf8_string().await.unwrap();
862 assert_eq!(key, "max_threads");
863 let value = reader.read_var_uint().await.unwrap();
864 assert_eq!(value, 8);
865
866 let setting = create_setting("allow_experimental", true, false, false);
868 let mut writer = MockWriter::default();
869 setting
870 .encode(&mut writer, DBMS_MIN_REVISION_WITH_SETTINGS_SERIALIZED_AS_STRINGS)
871 .await
872 .unwrap();
873 writer.flush().await.unwrap();
874
875 let mut reader = Cursor::new(writer.into_inner());
876 let key = reader.read_utf8_string().await.unwrap();
877 assert_eq!(key, "allow_experimental");
878 let value = reader.read_var_uint().await.unwrap();
879 assert_eq!(value, 1);
880
881 let setting = create_setting("default_format", "JSON", false, false);
883 let mut writer = MockWriter::default();
884 assert!(matches!(
885 setting
886 .encode(&mut writer, DBMS_MIN_REVISION_WITH_SETTINGS_SERIALIZED_AS_STRINGS)
887 .await,
888 Err(Error::UnsupportedSettingType(key)) if key == "default_format"
889 ));
890 }
891
892 #[tokio::test]
893 async fn test_setting_encode_modern_revision() {
894 let setting = create_setting("max_threads", 8_i32, false, false);
896 let mut writer = MockWriter::default();
897 setting
898 .encode(&mut writer, DBMS_MIN_REVISION_WITH_SETTINGS_SERIALIZED_AS_STRINGS + 1)
899 .await
900 .unwrap();
901 writer.flush().await.unwrap();
902
903 let mut reader = Cursor::new(writer.into_inner());
905 let key = reader.read_utf8_string().await.unwrap();
906 assert_eq!(key, "max_threads");
907 let flags = reader.read_var_uint().await.unwrap();
908 assert_eq!(flags, 0);
909 let value = reader.read_utf8_string().await.unwrap();
910 assert_eq!(value, "8");
911
912 let setting = create_setting("custom_key", "value", true, true);
914 let mut writer = MockWriter::default();
915 setting
916 .encode(&mut writer, DBMS_MIN_REVISION_WITH_SETTINGS_SERIALIZED_AS_STRINGS + 1)
917 .await
918 .unwrap();
919 writer.flush().await.unwrap();
920
921 let mut reader = Cursor::new(writer.into_inner());
922 let key = reader.read_utf8_string().await.unwrap();
923 assert_eq!(key, "custom_key");
924 let flags = reader.read_var_uint().await.unwrap();
925 assert_eq!(flags, SETTING_FLAG_IMPORTANT | SETTING_FLAG_CUSTOM);
926 let value = reader.read_utf8_string().await.unwrap();
927 assert_eq!(value, "value");
928 }
929
930 #[test]
931 fn test_settings_add_setting() {
932 let mut settings = Settings::default();
933 settings.add_setting("max_threads", 8_i32);
934 settings.add_setting("default_format", "JSON");
935
936 assert_eq!(settings.0.len(), 2);
937 assert_eq!(settings.0[0].key, "max_threads");
938 assert_eq!(settings.0[0].value, SettingValue::Int(8));
939 assert_eq!(settings.0[1].key, "default_format");
940 assert_eq!(settings.0[1].value, SettingValue::String("JSON".to_string()));
941 }
942
943 #[test]
944 fn test_settings_from_iterator() {
945 let settings = Settings::from(vec![
946 ("max_threads".to_string(), SettingValue::Int(8)),
947 ("allow_experimental".to_string(), SettingValue::Bool(true)),
948 ]);
949
950 assert_eq!(settings.0.len(), 2);
951 assert_eq!(settings.0[0].key, "max_threads");
952 assert_eq!(settings.0[0].value, SettingValue::Int(8));
953 assert_eq!(settings.0[1].key, "allow_experimental");
954 assert_eq!(settings.0[1].value, SettingValue::Bool(true));
955 }
956
957 #[test]
958 fn test_settings_encode_to_key_value_strings() {
959 let settings = Settings::from(vec![
960 ("max_threads".to_string(), SettingValue::Int(8)),
961 ("default_format".to_string(), "JSON".into()),
962 ]);
963
964 let kv_pairs = settings.encode_to_key_value_strings();
965 assert_eq!(kv_pairs, vec![
966 ("max_threads".to_string(), "8".to_string()),
967 ("default_format".to_string(), "JSON".to_string()),
968 ]);
969 }
970
971 #[test]
972 fn test_settings_encode_to_strings() {
973 let settings = Settings::from(vec![
974 ("max_threads".to_string(), SettingValue::Int(8)),
975 ("default_format".to_string(), "JSON".into()),
976 ]);
977
978 let strings = settings.encode_to_strings();
979 assert_eq!(strings, vec!["max_threads = 8", "default_format = JSON"]);
980 }
981
982 #[tokio::test]
983 async fn test_settings_encode() {
984 let settings = Settings::from(vec![
985 ("max_threads".to_string(), SettingValue::Int(8)),
986 ("allow_experimental".to_string(), SettingValue::Bool(true)),
987 ]);
988
989 let mut writer = MockWriter::default();
990 settings
991 .encode(&mut writer, DBMS_MIN_REVISION_WITH_SETTINGS_SERIALIZED_AS_STRINGS + 1)
992 .await
993 .unwrap();
994 writer.write_string("").await.unwrap();
995 writer.flush().await.unwrap();
996
997 let mut reader = Cursor::new(writer.into_inner());
999 let key1 = reader.read_utf8_string().await.unwrap();
1000 assert_eq!(key1, "max_threads");
1001 let flags1 = reader.read_var_uint().await.unwrap();
1002 assert_eq!(flags1, 0);
1003 let value1 = reader.read_utf8_string().await.unwrap();
1004 assert_eq!(value1, "8");
1005
1006 let key2 = reader.read_utf8_string().await.unwrap();
1007 assert_eq!(key2, "allow_experimental");
1008 let flags2 = reader.read_var_uint().await.unwrap();
1009 assert_eq!(flags2, 0);
1010 let value2 = reader.read_utf8_string().await.unwrap();
1011 assert_eq!(value2, "true");
1012 }
1013
1014 #[test]
1015 fn test_settings_deref() {
1016 let settings = Settings::from(vec![("max_threads".to_string(), 8_i32)]);
1017 let slice: &[Setting] = &settings;
1018 assert_eq!(slice.len(), 1);
1019 assert_eq!(slice[0].key, "max_threads");
1020 }
1021
1022 #[cfg(feature = "serde")]
1023 #[test]
1024 fn test_serde_serialization() {
1025 use serde_json;
1026
1027 let settings = Settings::from(vec![
1028 ("max_threads".to_string(), SettingValue::Int(8)),
1029 ("allow_experimental".to_string(), SettingValue::Bool(true)),
1030 ("default_format".to_string(), "JSON".into()),
1031 ]);
1032
1033 let json = serde_json::to_string(&settings).unwrap();
1034 let deserialized: Settings = serde_json::from_str(&json).unwrap();
1035 assert_eq!(settings, deserialized);
1036
1037 let setting = create_setting("max_threads", 8_i32, true, false);
1039 let json = serde_json::to_string(&setting).unwrap();
1040 let deserialized: Setting = serde_json::from_str(&json).unwrap();
1041 assert_eq!(setting, deserialized);
1042 }
1043
1044 #[tokio::test]
1045 async fn test_settings_decode_empty() {
1046 let mut writer = Cursor::new(Vec::new());
1048
1049 writer.write_string("").await.unwrap();
1051 writer.flush().await.unwrap();
1052
1053 let mut reader = Cursor::new(writer.into_inner());
1054 let settings = Settings::decode(&mut reader).await.unwrap();
1055
1056 assert_eq!(settings.0.len(), 0);
1057 }
1058
1059 #[tokio::test]
1060 async fn test_settings_decode_single_standard_setting() {
1061 let mut writer = MockWriter::default();
1063
1064 writer.write_string("max_threads").await.unwrap();
1066 writer.write_var_uint(0).await.unwrap(); writer.write_string("8").await.unwrap();
1068 writer.write_string("").await.unwrap(); writer.flush().await.unwrap();
1070
1071 let mut reader = Cursor::new(writer.into_inner());
1072 let settings = Settings::decode(&mut reader).await.unwrap();
1073
1074 assert_eq!(settings.0.len(), 1);
1075 assert_eq!(settings.0[0].key, "max_threads");
1076 assert_eq!(settings.0[0].value, SettingValue::Int(8));
1077 assert!(!settings.0[0].important);
1078 assert!(!settings.0[0].custom);
1079 }
1080
1081 #[tokio::test]
1082 async fn test_settings_decode_custom_setting() {
1083 let mut writer = MockWriter::default();
1085
1086 writer.write_string("custom_setting").await.unwrap();
1088 writer.write_var_uint(SETTING_FLAG_CUSTOM).await.unwrap();
1089 writer.write_string("custom_value").await.unwrap();
1090 writer.write_string("").await.unwrap(); writer.flush().await.unwrap();
1092
1093 let mut reader = Cursor::new(writer.into_inner());
1094 let settings = Settings::decode(&mut reader).await.unwrap();
1095
1096 assert_eq!(settings.0.len(), 1);
1097 assert_eq!(settings.0[0].key, "custom_setting");
1098 assert_eq!(settings.0[0].value, SettingValue::String("custom_value".to_string()));
1099 assert!(!settings.0[0].important);
1100 assert!(settings.0[0].custom);
1101 }
1102
1103 #[tokio::test]
1104 async fn test_settings_decode_important_setting() {
1105 let mut writer = MockWriter::default();
1107
1108 writer.write_string("critical_setting").await.unwrap();
1110 writer.write_var_uint(SETTING_FLAG_IMPORTANT).await.unwrap();
1111 writer.write_string("true").await.unwrap();
1112 writer.write_string("").await.unwrap(); writer.flush().await.unwrap();
1114
1115 let mut reader = Cursor::new(writer.into_inner());
1116 let settings = Settings::decode(&mut reader).await.unwrap();
1117
1118 assert_eq!(settings.0.len(), 1);
1119 assert_eq!(settings.0[0].key, "critical_setting");
1120 assert_eq!(settings.0[0].value, SettingValue::Bool(true));
1121 assert!(settings.0[0].important);
1122 assert!(!settings.0[0].custom);
1123 }
1124
1125 #[tokio::test]
1126 async fn test_settings_decode_multiple_settings() {
1127 let mut writer = MockWriter::default();
1129
1130 writer.write_string("max_threads").await.unwrap();
1132 writer.write_var_uint(0).await.unwrap();
1133 writer.write_string("4").await.unwrap();
1134
1135 writer.write_string("allow_experimental").await.unwrap();
1137 writer.write_var_uint(SETTING_FLAG_IMPORTANT).await.unwrap();
1138 writer.write_string("false").await.unwrap();
1139
1140 writer.write_string("custom_config").await.unwrap();
1142 writer.write_var_uint(SETTING_FLAG_CUSTOM).await.unwrap();
1143 writer.write_string("custom_data").await.unwrap();
1144
1145 writer.write_string("important_custom").await.unwrap();
1147 writer.write_var_uint(SETTING_FLAG_IMPORTANT | SETTING_FLAG_CUSTOM).await.unwrap();
1148 writer.write_string("special_value").await.unwrap();
1149
1150 writer.write_string("timeout_ratio").await.unwrap();
1152 writer.write_var_uint(0).await.unwrap();
1153 writer.write_string("1.5").await.unwrap();
1154
1155 writer.write_string("").await.unwrap();
1157 writer.flush().await.unwrap();
1158
1159 let mut reader = Cursor::new(writer.into_inner());
1160 let settings = Settings::decode(&mut reader).await.unwrap();
1161
1162 assert_eq!(settings.0.len(), 5);
1163
1164 assert_eq!(settings.0[0].key, "max_threads");
1166 assert_eq!(settings.0[0].value, SettingValue::Int(4));
1167 assert!(!settings.0[0].important);
1168 assert!(!settings.0[0].custom);
1169
1170 assert_eq!(settings.0[1].key, "allow_experimental");
1172 assert_eq!(settings.0[1].value, SettingValue::Bool(false));
1173 assert!(settings.0[1].important);
1174 assert!(!settings.0[1].custom);
1175
1176 assert_eq!(settings.0[2].key, "custom_config");
1178 assert_eq!(settings.0[2].value, SettingValue::String("custom_data".to_string()));
1179 assert!(!settings.0[2].important);
1180 assert!(settings.0[2].custom);
1181
1182 assert_eq!(settings.0[3].key, "important_custom");
1184 assert_eq!(settings.0[3].value, SettingValue::String("special_value".to_string()));
1185 assert!(settings.0[3].important);
1186 assert!(settings.0[3].custom);
1187
1188 assert_eq!(settings.0[4].key, "timeout_ratio");
1190 assert_eq!(settings.0[4].value, SettingValue::Float(1.5));
1191 assert!(!settings.0[4].important);
1192 assert!(!settings.0[4].custom);
1193 }
1194
1195 #[tokio::test]
1196 async fn test_settings_decode_parse_setting_value_edge_cases() {
1197 let mut writer = MockWriter::default();
1199
1200 writer.write_string("bool_zero").await.unwrap();
1202 writer.write_var_uint(0).await.unwrap();
1203 writer.write_string("0").await.unwrap();
1204
1205 writer.write_string("bool_one").await.unwrap();
1207 writer.write_var_uint(0).await.unwrap();
1208 writer.write_string("1").await.unwrap();
1209
1210 writer.write_string("negative_int").await.unwrap();
1212 writer.write_var_uint(0).await.unwrap();
1213 writer.write_string("-42").await.unwrap();
1214
1215 writer.write_string("string_val").await.unwrap();
1217 writer.write_var_uint(0).await.unwrap();
1218 writer.write_string("not_a_number").await.unwrap();
1219
1220 writer.write_string("empty_val").await.unwrap();
1222 writer.write_var_uint(0).await.unwrap();
1223 writer.write_string("").await.unwrap();
1224
1225 writer.write_string("").await.unwrap();
1227 writer.flush().await.unwrap();
1228
1229 let mut reader = Cursor::new(writer.into_inner());
1230 let settings = Settings::decode(&mut reader).await.unwrap();
1231
1232 assert_eq!(settings.0.len(), 5);
1233 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())); }
1239
1240 #[tokio::test]
1241 async fn test_settings_decode_roundtrip() {
1242 let original_settings = Settings::from(vec![
1244 ("max_threads".to_string(), SettingValue::Int(8)),
1245 ("allow_experimental".to_string(), SettingValue::Bool(true)),
1246 ("custom_setting".to_string(), SettingValue::String("custom_value".to_string())),
1247 ]);
1248
1249 let mut settings_with_custom = original_settings.clone();
1251 settings_with_custom.0[2].custom = true;
1252 settings_with_custom.0[1].important = true;
1253
1254 let mut writer = MockWriter::default();
1256 settings_with_custom
1257 .encode(&mut writer, DBMS_MIN_REVISION_WITH_SETTINGS_SERIALIZED_AS_STRINGS + 1)
1258 .await
1259 .unwrap();
1260 writer.write_string("").await.unwrap();
1261 writer.flush().await.unwrap();
1262
1263 let mut reader = Cursor::new(writer.into_inner());
1265
1266 let decoded_settings = Settings::decode(&mut reader).await.unwrap();
1267
1268 assert_eq!(decoded_settings.0.len(), 3);
1270 assert_eq!(decoded_settings.0[0].key, "max_threads");
1271 assert_eq!(decoded_settings.0[0].value, SettingValue::Int(8));
1272 assert!(!decoded_settings.0[0].important);
1273 assert!(!decoded_settings.0[0].custom);
1274
1275 assert_eq!(decoded_settings.0[1].key, "allow_experimental");
1276 assert_eq!(decoded_settings.0[1].value, SettingValue::Bool(true));
1277 assert!(decoded_settings.0[1].important);
1278 assert!(!decoded_settings.0[1].custom);
1279
1280 assert_eq!(decoded_settings.0[2].key, "custom_setting");
1281 assert_eq!(decoded_settings.0[2].value, SettingValue::String("custom_value".to_string()));
1282 assert!(!decoded_settings.0[2].important);
1283 assert!(decoded_settings.0[2].custom);
1284 }
1285}