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
429 .iter()
430 .map(|setting| (setting.key.to_string(), setting.value.to_string()))
431 .collect()
432 }
433
434 pub fn encode_to_strings(&self) -> Vec<String> {
447 self.0.iter().map(|setting| format!("{} = {}", setting.key, setting.value)).collect()
448 }
449
450 pub(crate) async fn encode<W: ClickHouseWrite>(
452 &self,
453 writer: &mut W,
454 revision: u64,
455 ) -> Result<()> {
456 for setting in &self.0 {
457 setting.encode(writer, revision).await?;
458 }
459 Ok(())
460 }
461
462 pub(crate) async fn encode_with_ignore<W: ClickHouseWrite>(
464 &self,
465 writer: &mut W,
466 revision: u64,
467 ignore: &Settings,
468 ) -> Result<()> {
469 for setting in &self.0 {
470 if ignore.get(&setting.key).is_some_and(|s| s.value == setting.value) {
471 continue;
472 }
473
474 setting.encode(writer, revision).await?;
475 }
476 Ok(())
477 }
478
479 pub(crate) async fn decode<R: ClickHouseRead>(reader: &mut R) -> Result<Self> {
493 let mut settings = Vec::new();
494 loop {
495 let key = reader.read_string().await?;
497 if key.is_empty() {
499 break;
500 }
501 settings
502 .push(Setting::decode(reader, String::from_utf8_lossy(&key).to_string()).await?);
503 }
504 Ok(Settings(settings))
505 }
506
507 pub(crate) fn get(&self, key: &str) -> Option<&Setting> { self.0.iter().find(|s| s.key == key) }
509}
510
511impl<T, K, S> From<T> for Settings
512where
513 T: IntoIterator<Item = (K, S)>,
514 K: Into<String>,
515 SettingValue: From<S>,
516{
517 fn from(value: T) -> Self {
518 Self(
519 value
520 .into_iter()
521 .map(|(k, v)| Setting {
522 key: k.into(),
523 value: v.into(),
524 important: false,
525 custom: false,
526 })
527 .collect(),
528 )
529 }
530}
531
532impl<K, S> FromIterator<(K, S)> for Settings
533where
534 K: Into<String>,
535 SettingValue: From<S>,
536{
537 fn from_iter<T>(iter: T) -> Self
538 where
539 T: IntoIterator<Item = (K, S)>,
540 {
541 iter.into_iter().collect()
542 }
543}
544
545impl std::ops::Deref for Settings {
546 type Target = [Setting];
547
548 fn deref(&self) -> &Self::Target { &self.0 }
549}
550
551#[cfg(feature = "serde")]
552pub mod deser {
553 use serde::{Deserialize, Serialize};
554
555 use super::*;
556
557 impl Serialize for SettingValue {
558 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
559 where
560 S: serde::Serializer,
561 {
562 match self {
563 SettingValue::Int(i) => ::serde::Serialize::serialize(i, serializer),
564 SettingValue::Bool(b) => ::serde::Serialize::serialize(b, serializer),
565 SettingValue::Float(f) => ::serde::Serialize::serialize(f, serializer),
566 SettingValue::String(s) => ::serde::Serialize::serialize(s, serializer),
567 }
568 }
569 }
570
571 impl<'de> Deserialize<'de> for SettingValue {
572 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
573 where
574 D: serde::Deserializer<'de>,
575 {
576 fn deserialize_setting<'d, De>(deserializer: De) -> Result<SettingValue, De::Error>
577 where
578 De: serde::Deserializer<'d>,
579 {
580 use serde::de::Visitor;
581
582 struct SettingVisitor;
583
584 type Result<E> = std::result::Result<SettingValue, E>;
585
586 impl Visitor<'_> for SettingVisitor {
587 type Value = SettingValue;
588
589 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
590 formatter.write_str("a number, float or string")
591 }
592
593 fn visit_bool<E>(self, value: bool) -> Result<E>
594 where
595 E: serde::de::Error,
596 {
597 Ok(value.into())
598 }
599
600 fn visit_u8<E>(self, value: u8) -> Result<E>
601 where
602 E: serde::de::Error,
603 {
604 Ok(value.into())
605 }
606
607 fn visit_u16<E>(self, value: u16) -> Result<E>
608 where
609 E: serde::de::Error,
610 {
611 Ok(value.into())
612 }
613
614 fn visit_u32<E>(self, value: u32) -> Result<E>
615 where
616 E: serde::de::Error,
617 {
618 Ok(value.into())
619 }
620
621 fn visit_u64<E>(self, value: u64) -> Result<E>
622 where
623 E: serde::de::Error,
624 {
625 Ok(value.into())
626 }
627
628 fn visit_i8<E>(self, value: i8) -> Result<E>
629 where
630 E: serde::de::Error,
631 {
632 Ok(value.into())
633 }
634
635 fn visit_i16<E>(self, value: i16) -> Result<E>
636 where
637 E: serde::de::Error,
638 {
639 Ok(value.into())
640 }
641
642 fn visit_i32<E>(self, value: i32) -> Result<E>
643 where
644 E: serde::de::Error,
645 {
646 Ok(value.into())
647 }
648
649 fn visit_i64<E>(self, value: i64) -> Result<E>
650 where
651 E: serde::de::Error,
652 {
653 Ok(value.into())
654 }
655
656 fn visit_f32<E>(self, value: f32) -> Result<E>
657 where
658 E: serde::de::Error,
659 {
660 Ok(value.into())
661 }
662
663 fn visit_f64<E>(self, value: f64) -> Result<E>
664 where
665 E: serde::de::Error,
666 {
667 Ok(value.into())
668 }
669
670 fn visit_str<E>(self, value: &str) -> Result<E>
671 where
672 E: serde::de::Error,
673 {
674 Ok(value.into())
675 }
676
677 fn visit_string<E>(self, value: String) -> Result<E>
678 where
679 E: serde::de::Error,
680 {
681 self.visit_str(&value)
682 }
683 }
684
685 deserializer.deserialize_any(SettingVisitor)
686 }
687 deserialize_setting(deserializer)
688 }
689 }
690
691 #[cfg(test)]
692 mod tests {
693 use super::*;
694
695 #[test]
696 fn test_setting_value_serialize_deserialize() {
697 let values = vec![
699 SettingValue::Int(42),
700 SettingValue::Bool(true),
701 SettingValue::Float(3.15),
702 SettingValue::String("test".to_string()),
703 ];
704
705 for value in values {
706 let json = serde_json::to_string(&value).unwrap();
708
709 let deserialized: SettingValue = serde_json::from_str(&json).unwrap();
711
712 match (value, deserialized) {
714 (SettingValue::Int(a), SettingValue::Int(b)) => assert_eq!(a, b),
715 (SettingValue::Bool(a), SettingValue::Bool(b)) => assert_eq!(a, b),
716 (SettingValue::Float(a), SettingValue::Float(b)) => {
717 assert!((a - b).abs() < 1e-6);
718 }
719 (SettingValue::String(a), SettingValue::String(b)) => assert_eq!(a, b),
720 _ => panic!("Mismatched variants"),
721 }
722 }
723 }
724
725 #[test]
726 fn test_setting_value_deserialize_variants() {
727 assert_eq!(serde_json::from_str::<SettingValue>("42").unwrap(), SettingValue::Int(42));
729 assert_eq!(
730 serde_json::from_str::<SettingValue>("true").unwrap(),
731 SettingValue::Bool(true)
732 );
733 assert!(
734 (serde_json::from_str::<SettingValue>("3.15").unwrap().unwrap_float() - 3.15).abs()
735 < 1e-6
736 );
737 assert_eq!(
738 serde_json::from_str::<SettingValue>("\"test\"").unwrap(),
739 SettingValue::String("test".to_string())
740 );
741
742 assert_eq!(
744 serde_json::from_str::<SettingValue>("255").unwrap(),
745 SettingValue::Int(255)
746 ); assert_eq!(
748 serde_json::from_str::<SettingValue>("65535").unwrap(),
749 SettingValue::Int(65535)
750 ); assert_eq!(
752 serde_json::from_str::<SettingValue>("4294967295").unwrap(),
753 SettingValue::Int(4_294_967_295)
754 ); assert_eq!(
756 serde_json::from_str::<SettingValue>("-128").unwrap(),
757 SettingValue::Int(-128)
758 ); assert_eq!(
760 serde_json::from_str::<SettingValue>("-32768").unwrap(),
761 SettingValue::Int(-32768)
762 ); assert_eq!(
764 serde_json::from_str::<SettingValue>("-2147483648").unwrap(),
765 SettingValue::Int(-2_147_483_648)
766 ); }
768
769 #[test]
770 fn test_setting_value_deserialize_invalid() {
771 assert!(serde_json::from_str::<SettingValue>("null").is_err());
773 assert!(serde_json::from_str::<SettingValue>("[]").is_err());
774 assert!(serde_json::from_str::<SettingValue>("{}").is_err());
775 }
776 }
777}
778
779#[cfg(test)]
780mod tests {
781 use std::io::Cursor;
782
783 use tokio::io::AsyncWriteExt;
784
785 use super::*;
786 use crate::io::ClickHouseRead;
787
788 type MockWriter = Cursor<Vec<u8>>;
789
790 fn create_setting<S>(key: &str, value: S, important: bool, custom: bool) -> Setting
792 where
793 SettingValue: From<S>,
794 {
795 Setting { key: key.to_string(), value: value.into(), important, custom }
796 }
797
798 #[test]
799 fn test_setting_value_from_primitives() {
800 assert_eq!(SettingValue::from(8_i8), SettingValue::Int(8));
802 assert_eq!(SettingValue::from(8_i16), SettingValue::Int(8));
803 assert_eq!(SettingValue::from(8_i32), SettingValue::Int(8));
804 assert_eq!(SettingValue::from(8_i64), SettingValue::Int(8));
805 assert_eq!(SettingValue::from(8_u8), SettingValue::Int(8));
806 assert_eq!(SettingValue::from(8_u16), SettingValue::Int(8));
807 assert_eq!(SettingValue::from(8_u32), SettingValue::Int(8));
808 assert_eq!(SettingValue::from(8_u64), SettingValue::Int(8));
809 assert_eq!(SettingValue::from(true), SettingValue::Bool(true));
810 assert!((SettingValue::from(3.15_f32).unwrap_float() - 3.15).abs() < 1e-6);
811 assert_eq!(SettingValue::from(3.15_f64), SettingValue::Float(3.15));
812 assert_eq!(SettingValue::from("test"), SettingValue::String("test".to_string()));
813 assert_eq!(
814 SettingValue::from("test".to_string()),
815 SettingValue::String("test".to_string())
816 );
817 assert_eq!(
818 SettingValue::from(Box::<str>::from("test")),
819 SettingValue::String("test".to_string())
820 );
821 assert_eq!(
822 SettingValue::from(std::sync::Arc::<str>::from("test")),
823 SettingValue::String("test".to_string())
824 );
825 }
826
827 #[test]
828 fn test_setting_value_display() {
829 assert_eq!(SettingValue::Int(42).to_string(), "42");
831 assert_eq!(SettingValue::Bool(true).to_string(), "true");
832 assert_eq!(SettingValue::Float(3.15).to_string(), "3.15");
833 assert_eq!(SettingValue::String("test".to_string()).to_string(), "test");
834 }
835
836 #[test]
837 fn test_setting_encode_field_dump() {
838 let setting = create_setting("key", "value", false, true);
840 assert_eq!(setting.encode_field_dump().unwrap(), "value");
841
842 let setting = create_setting("key", "val'ue", false, true);
844 assert_eq!(setting.encode_field_dump().unwrap(), "val'ue");
845
846 let setting = create_setting("key", 42_i32, false, true);
848 assert!(setting.encode_field_dump().is_err());
849 }
850
851 #[tokio::test]
852 async fn test_setting_encode_legacy_revision() {
853 let setting = create_setting("max_threads", 8_i32, false, false);
855 let mut writer = MockWriter::default();
856 setting
857 .encode(&mut writer, DBMS_MIN_REVISION_WITH_SETTINGS_SERIALIZED_AS_STRINGS)
858 .await
859 .unwrap();
860 writer.flush().await.unwrap();
861
862 let mut reader = Cursor::new(writer.into_inner());
864 let key = reader.read_utf8_string().await.unwrap();
865 assert_eq!(key, "max_threads");
866 let value = reader.read_var_uint().await.unwrap();
867 assert_eq!(value, 8);
868
869 let setting = create_setting("allow_experimental", true, false, false);
871 let mut writer = MockWriter::default();
872 setting
873 .encode(&mut writer, DBMS_MIN_REVISION_WITH_SETTINGS_SERIALIZED_AS_STRINGS)
874 .await
875 .unwrap();
876 writer.flush().await.unwrap();
877
878 let mut reader = Cursor::new(writer.into_inner());
879 let key = reader.read_utf8_string().await.unwrap();
880 assert_eq!(key, "allow_experimental");
881 let value = reader.read_var_uint().await.unwrap();
882 assert_eq!(value, 1);
883
884 let setting = create_setting("default_format", "JSON", false, false);
886 let mut writer = MockWriter::default();
887 assert!(matches!(
888 setting
889 .encode(&mut writer, DBMS_MIN_REVISION_WITH_SETTINGS_SERIALIZED_AS_STRINGS)
890 .await,
891 Err(Error::UnsupportedSettingType(key)) if key == "default_format"
892 ));
893 }
894
895 #[tokio::test]
896 async fn test_setting_encode_modern_revision() {
897 let setting = create_setting("max_threads", 8_i32, false, false);
899 let mut writer = MockWriter::default();
900 setting
901 .encode(&mut writer, DBMS_MIN_REVISION_WITH_SETTINGS_SERIALIZED_AS_STRINGS + 1)
902 .await
903 .unwrap();
904 writer.flush().await.unwrap();
905
906 let mut reader = Cursor::new(writer.into_inner());
908 let key = reader.read_utf8_string().await.unwrap();
909 assert_eq!(key, "max_threads");
910 let flags = reader.read_var_uint().await.unwrap();
911 assert_eq!(flags, 0);
912 let value = reader.read_utf8_string().await.unwrap();
913 assert_eq!(value, "8");
914
915 let setting = create_setting("custom_key", "value", true, true);
917 let mut writer = MockWriter::default();
918 setting
919 .encode(&mut writer, DBMS_MIN_REVISION_WITH_SETTINGS_SERIALIZED_AS_STRINGS + 1)
920 .await
921 .unwrap();
922 writer.flush().await.unwrap();
923
924 let mut reader = Cursor::new(writer.into_inner());
925 let key = reader.read_utf8_string().await.unwrap();
926 assert_eq!(key, "custom_key");
927 let flags = reader.read_var_uint().await.unwrap();
928 assert_eq!(flags, SETTING_FLAG_IMPORTANT | SETTING_FLAG_CUSTOM);
929 let value = reader.read_utf8_string().await.unwrap();
930 assert_eq!(value, "value");
931 }
932
933 #[test]
934 fn test_settings_add_setting() {
935 let mut settings = Settings::default();
936 settings.add_setting("max_threads", 8_i32);
937 settings.add_setting("default_format", "JSON");
938
939 assert_eq!(settings.0.len(), 2);
940 assert_eq!(settings.0[0].key, "max_threads");
941 assert_eq!(settings.0[0].value, SettingValue::Int(8));
942 assert_eq!(settings.0[1].key, "default_format");
943 assert_eq!(settings.0[1].value, SettingValue::String("JSON".to_string()));
944 }
945
946 #[test]
947 fn test_settings_from_iterator() {
948 let settings = Settings::from(vec![
949 ("max_threads".to_string(), SettingValue::Int(8)),
950 ("allow_experimental".to_string(), SettingValue::Bool(true)),
951 ]);
952
953 assert_eq!(settings.0.len(), 2);
954 assert_eq!(settings.0[0].key, "max_threads");
955 assert_eq!(settings.0[0].value, SettingValue::Int(8));
956 assert_eq!(settings.0[1].key, "allow_experimental");
957 assert_eq!(settings.0[1].value, SettingValue::Bool(true));
958 }
959
960 #[test]
961 fn test_settings_encode_to_key_value_strings() {
962 let settings = Settings::from(vec![
963 ("max_threads".to_string(), SettingValue::Int(8)),
964 ("default_format".to_string(), "JSON".into()),
965 ]);
966
967 let kv_pairs = settings.encode_to_key_value_strings();
968 assert_eq!(kv_pairs, vec![
969 ("max_threads".to_string(), "8".to_string()),
970 ("default_format".to_string(), "JSON".to_string()),
971 ]);
972 }
973
974 #[test]
975 fn test_settings_encode_to_strings() {
976 let settings = Settings::from(vec![
977 ("max_threads".to_string(), SettingValue::Int(8)),
978 ("default_format".to_string(), "JSON".into()),
979 ]);
980
981 let strings = settings.encode_to_strings();
982 assert_eq!(strings, vec!["max_threads = 8", "default_format = JSON"]);
983 }
984
985 #[tokio::test]
986 async fn test_settings_encode() {
987 let settings = Settings::from(vec![
988 ("max_threads".to_string(), SettingValue::Int(8)),
989 ("allow_experimental".to_string(), SettingValue::Bool(true)),
990 ]);
991
992 let mut writer = MockWriter::default();
993 settings
994 .encode(&mut writer, DBMS_MIN_REVISION_WITH_SETTINGS_SERIALIZED_AS_STRINGS + 1)
995 .await
996 .unwrap();
997 writer.write_string("").await.unwrap();
998 writer.flush().await.unwrap();
999
1000 let mut reader = Cursor::new(writer.into_inner());
1002 let key1 = reader.read_utf8_string().await.unwrap();
1003 assert_eq!(key1, "max_threads");
1004 let flags1 = reader.read_var_uint().await.unwrap();
1005 assert_eq!(flags1, 0);
1006 let value1 = reader.read_utf8_string().await.unwrap();
1007 assert_eq!(value1, "8");
1008
1009 let key2 = reader.read_utf8_string().await.unwrap();
1010 assert_eq!(key2, "allow_experimental");
1011 let flags2 = reader.read_var_uint().await.unwrap();
1012 assert_eq!(flags2, 0);
1013 let value2 = reader.read_utf8_string().await.unwrap();
1014 assert_eq!(value2, "true");
1015 }
1016
1017 #[test]
1018 fn test_settings_deref() {
1019 let settings = Settings::from(vec![("max_threads".to_string(), 8_i32)]);
1020 let slice: &[Setting] = &settings;
1021 assert_eq!(slice.len(), 1);
1022 assert_eq!(slice[0].key, "max_threads");
1023 }
1024
1025 #[cfg(feature = "serde")]
1026 #[test]
1027 fn test_serde_serialization() {
1028 use serde_json;
1029
1030 let settings = Settings::from(vec![
1031 ("max_threads".to_string(), SettingValue::Int(8)),
1032 ("allow_experimental".to_string(), SettingValue::Bool(true)),
1033 ("default_format".to_string(), "JSON".into()),
1034 ]);
1035
1036 let json = serde_json::to_string(&settings).unwrap();
1037 let deserialized: Settings = serde_json::from_str(&json).unwrap();
1038 assert_eq!(settings, deserialized);
1039
1040 let setting = create_setting("max_threads", 8_i32, true, false);
1042 let json = serde_json::to_string(&setting).unwrap();
1043 let deserialized: Setting = serde_json::from_str(&json).unwrap();
1044 assert_eq!(setting, deserialized);
1045 }
1046
1047 #[tokio::test]
1048 async fn test_settings_decode_empty() {
1049 let mut writer = Cursor::new(Vec::new());
1051
1052 writer.write_string("").await.unwrap();
1054 writer.flush().await.unwrap();
1055
1056 let mut reader = Cursor::new(writer.into_inner());
1057 let settings = Settings::decode(&mut reader).await.unwrap();
1058
1059 assert_eq!(settings.0.len(), 0);
1060 }
1061
1062 #[tokio::test]
1063 async fn test_settings_decode_single_standard_setting() {
1064 let mut writer = MockWriter::default();
1066
1067 writer.write_string("max_threads").await.unwrap();
1069 writer.write_var_uint(0).await.unwrap(); writer.write_string("8").await.unwrap();
1071 writer.write_string("").await.unwrap(); writer.flush().await.unwrap();
1073
1074 let mut reader = Cursor::new(writer.into_inner());
1075 let settings = Settings::decode(&mut reader).await.unwrap();
1076
1077 assert_eq!(settings.0.len(), 1);
1078 assert_eq!(settings.0[0].key, "max_threads");
1079 assert_eq!(settings.0[0].value, SettingValue::Int(8));
1080 assert!(!settings.0[0].important);
1081 assert!(!settings.0[0].custom);
1082 }
1083
1084 #[tokio::test]
1085 async fn test_settings_decode_custom_setting() {
1086 let mut writer = MockWriter::default();
1088
1089 writer.write_string("custom_setting").await.unwrap();
1091 writer.write_var_uint(SETTING_FLAG_CUSTOM).await.unwrap();
1092 writer.write_string("custom_value").await.unwrap();
1093 writer.write_string("").await.unwrap(); writer.flush().await.unwrap();
1095
1096 let mut reader = Cursor::new(writer.into_inner());
1097 let settings = Settings::decode(&mut reader).await.unwrap();
1098
1099 assert_eq!(settings.0.len(), 1);
1100 assert_eq!(settings.0[0].key, "custom_setting");
1101 assert_eq!(settings.0[0].value, SettingValue::String("custom_value".to_string()));
1102 assert!(!settings.0[0].important);
1103 assert!(settings.0[0].custom);
1104 }
1105
1106 #[tokio::test]
1107 async fn test_settings_decode_important_setting() {
1108 let mut writer = MockWriter::default();
1110
1111 writer.write_string("critical_setting").await.unwrap();
1113 writer.write_var_uint(SETTING_FLAG_IMPORTANT).await.unwrap();
1114 writer.write_string("true").await.unwrap();
1115 writer.write_string("").await.unwrap(); writer.flush().await.unwrap();
1117
1118 let mut reader = Cursor::new(writer.into_inner());
1119 let settings = Settings::decode(&mut reader).await.unwrap();
1120
1121 assert_eq!(settings.0.len(), 1);
1122 assert_eq!(settings.0[0].key, "critical_setting");
1123 assert_eq!(settings.0[0].value, SettingValue::Bool(true));
1124 assert!(settings.0[0].important);
1125 assert!(!settings.0[0].custom);
1126 }
1127
1128 #[tokio::test]
1129 async fn test_settings_decode_multiple_settings() {
1130 let mut writer = MockWriter::default();
1132
1133 writer.write_string("max_threads").await.unwrap();
1135 writer.write_var_uint(0).await.unwrap();
1136 writer.write_string("4").await.unwrap();
1137
1138 writer.write_string("allow_experimental").await.unwrap();
1140 writer.write_var_uint(SETTING_FLAG_IMPORTANT).await.unwrap();
1141 writer.write_string("false").await.unwrap();
1142
1143 writer.write_string("custom_config").await.unwrap();
1145 writer.write_var_uint(SETTING_FLAG_CUSTOM).await.unwrap();
1146 writer.write_string("custom_data").await.unwrap();
1147
1148 writer.write_string("important_custom").await.unwrap();
1150 writer.write_var_uint(SETTING_FLAG_IMPORTANT | SETTING_FLAG_CUSTOM).await.unwrap();
1151 writer.write_string("special_value").await.unwrap();
1152
1153 writer.write_string("timeout_ratio").await.unwrap();
1155 writer.write_var_uint(0).await.unwrap();
1156 writer.write_string("1.5").await.unwrap();
1157
1158 writer.write_string("").await.unwrap();
1160 writer.flush().await.unwrap();
1161
1162 let mut reader = Cursor::new(writer.into_inner());
1163 let settings = Settings::decode(&mut reader).await.unwrap();
1164
1165 assert_eq!(settings.0.len(), 5);
1166
1167 assert_eq!(settings.0[0].key, "max_threads");
1169 assert_eq!(settings.0[0].value, SettingValue::Int(4));
1170 assert!(!settings.0[0].important);
1171 assert!(!settings.0[0].custom);
1172
1173 assert_eq!(settings.0[1].key, "allow_experimental");
1175 assert_eq!(settings.0[1].value, SettingValue::Bool(false));
1176 assert!(settings.0[1].important);
1177 assert!(!settings.0[1].custom);
1178
1179 assert_eq!(settings.0[2].key, "custom_config");
1181 assert_eq!(settings.0[2].value, SettingValue::String("custom_data".to_string()));
1182 assert!(!settings.0[2].important);
1183 assert!(settings.0[2].custom);
1184
1185 assert_eq!(settings.0[3].key, "important_custom");
1187 assert_eq!(settings.0[3].value, SettingValue::String("special_value".to_string()));
1188 assert!(settings.0[3].important);
1189 assert!(settings.0[3].custom);
1190
1191 assert_eq!(settings.0[4].key, "timeout_ratio");
1193 assert_eq!(settings.0[4].value, SettingValue::Float(1.5));
1194 assert!(!settings.0[4].important);
1195 assert!(!settings.0[4].custom);
1196 }
1197
1198 #[tokio::test]
1199 async fn test_settings_decode_parse_setting_value_edge_cases() {
1200 let mut writer = MockWriter::default();
1202
1203 writer.write_string("bool_zero").await.unwrap();
1205 writer.write_var_uint(0).await.unwrap();
1206 writer.write_string("0").await.unwrap();
1207
1208 writer.write_string("bool_one").await.unwrap();
1210 writer.write_var_uint(0).await.unwrap();
1211 writer.write_string("1").await.unwrap();
1212
1213 writer.write_string("negative_int").await.unwrap();
1215 writer.write_var_uint(0).await.unwrap();
1216 writer.write_string("-42").await.unwrap();
1217
1218 writer.write_string("string_val").await.unwrap();
1220 writer.write_var_uint(0).await.unwrap();
1221 writer.write_string("not_a_number").await.unwrap();
1222
1223 writer.write_string("empty_val").await.unwrap();
1225 writer.write_var_uint(0).await.unwrap();
1226 writer.write_string("").await.unwrap();
1227
1228 writer.write_string("").await.unwrap();
1230 writer.flush().await.unwrap();
1231
1232 let mut reader = Cursor::new(writer.into_inner());
1233 let settings = Settings::decode(&mut reader).await.unwrap();
1234
1235 assert_eq!(settings.0.len(), 5);
1236 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())); }
1242
1243 #[tokio::test]
1244 async fn test_settings_decode_roundtrip() {
1245 let original_settings = Settings::from(vec![
1247 ("max_threads".to_string(), SettingValue::Int(8)),
1248 ("allow_experimental".to_string(), SettingValue::Bool(true)),
1249 ("custom_setting".to_string(), SettingValue::String("custom_value".to_string())),
1250 ]);
1251
1252 let mut settings_with_custom = original_settings.clone();
1254 settings_with_custom.0[2].custom = true;
1255 settings_with_custom.0[1].important = true;
1256
1257 let mut writer = MockWriter::default();
1259 settings_with_custom
1260 .encode(&mut writer, DBMS_MIN_REVISION_WITH_SETTINGS_SERIALIZED_AS_STRINGS + 1)
1261 .await
1262 .unwrap();
1263 writer.write_string("").await.unwrap();
1264 writer.flush().await.unwrap();
1265
1266 let mut reader = Cursor::new(writer.into_inner());
1268
1269 let decoded_settings = Settings::decode(&mut reader).await.unwrap();
1270
1271 assert_eq!(decoded_settings.0.len(), 3);
1273 assert_eq!(decoded_settings.0[0].key, "max_threads");
1274 assert_eq!(decoded_settings.0[0].value, SettingValue::Int(8));
1275 assert!(!decoded_settings.0[0].important);
1276 assert!(!decoded_settings.0[0].custom);
1277
1278 assert_eq!(decoded_settings.0[1].key, "allow_experimental");
1279 assert_eq!(decoded_settings.0[1].value, SettingValue::Bool(true));
1280 assert!(decoded_settings.0[1].important);
1281 assert!(!decoded_settings.0[1].custom);
1282
1283 assert_eq!(decoded_settings.0[2].key, "custom_setting");
1284 assert_eq!(decoded_settings.0[2].value, SettingValue::String("custom_value".to_string()));
1285 assert!(!decoded_settings.0[2].important);
1286 assert!(decoded_settings.0[2].custom);
1287 }
1288}