]> git.proxmox.com Git - proxmox.git/commitdiff
schema: implement split_list iterator
authorWolfgang Bumiller <w.bumiller@proxmox.com>
Tue, 4 Apr 2023 14:00:59 +0000 (16:00 +0200)
committerWolfgang Bumiller <w.bumiller@proxmox.com>
Fri, 2 Feb 2024 11:06:46 +0000 (12:06 +0100)
and reuse splitting code in no_schema's SeqAccess as well

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
Reviewed-by: Lukas Wagner <l.wagner@proxmox.com>
proxmox-schema/src/de/mod.rs
proxmox-schema/src/de/no_schema.rs

index 60b40771e767f3e471b0c27c28107402ce5a5e81..75b500e5427682089da6099f0c6132fffb9e9de9 100644 (file)
@@ -19,6 +19,8 @@ pub use extract::ExtractValueDeserializer;
 
 use cow3::{str_slice_to_range, Cow3};
 
+pub use no_schema::{split_list, SplitList};
+
 // Used to disable calling `check_constraints` on a `StringSchema` if it is being deserialized
 // for a `PropertyString`, which performs its own checking.
 thread_local! {
@@ -350,7 +352,7 @@ impl<'de, 'i> de::Deserializer<'de> for SchemaDeserializer<'de, 'i> {
     }
 }
 
-fn next_str_entry(input: &str, at: &mut usize, has_null: bool) -> Option<Range<usize>> {
+pub(crate) fn next_str_entry(input: &str, at: &mut usize, has_null: bool) -> Option<Range<usize>> {
     while *at != input.len() {
         let begin = *at;
 
@@ -373,7 +375,7 @@ fn next_str_entry(input: &str, at: &mut usize, has_null: bool) -> Option<Range<u
             }
         };
 
-        if input[..end].is_empty() {
+        if begin == end || input[..end].is_empty() {
             continue;
         }
 
@@ -420,10 +422,6 @@ impl<'de, 'i, 's> de::SeqAccess<'de> for SeqAccess<'de, 'i, 's> {
         }
 
         while let Some(el_range) = next_str_entry(&self.input, &mut self.at, self.has_null) {
-            if el_range.is_empty() {
-                continue;
-            }
-
             if let Some(max) = self.schema.max_length {
                 if self.count == max {
                     return Err(Error::msg("too many elements"));
index 254ebd96e01cc4142de1e9ea1d519ded4f11a01c..546e500178e3cb62da961ea14629816f3ca1d649 100644 (file)
@@ -271,41 +271,39 @@ impl<'de, 'i> de::SeqAccess<'de> for SimpleSeqAccess<'de, 'i> {
     where
         T: de::DeserializeSeed<'de>,
     {
-        while self.at != self.input.len() {
-            let begin = self.at;
-
-            let input = &self.input[self.at..];
-
-            let end = if self.has_null {
-                input.find('\0')
-            } else {
-                input.find(|c: char| c == ',' || c == ';' || char::is_ascii_whitespace(&c))
-            };
-
-            let end = match end {
-                None => {
-                    self.at = self.input.len();
-                    input.len()
-                }
-                Some(pos) => {
-                    self.at += pos + 1;
-                    pos
-                }
-            };
-
-            if input[..end].is_empty() {
-                continue;
-            }
-
-            return seed
-                .deserialize(NoSchemaDeserializer::new(match &self.input {
-                    Cow3::Original(input) => Cow::Borrowed(&input[begin..end]),
-                    Cow3::Intermediate(input) => Cow::Owned(input[begin..end].to_string()),
-                    Cow3::Owned(input) => Cow::Owned(input[begin..end].to_string()),
-                }))
-                .map(Some);
-        }
+        let range = match super::next_str_entry(&self.input, &mut self.at, self.has_null) {
+            None => return Ok(None),
+            Some(range) => range,
+        };
+
+        seed.deserialize(NoSchemaDeserializer::new(match &self.input {
+            Cow3::Original(input) => Cow::Borrowed(&input[range]),
+            Cow3::Intermediate(input) => Cow::Owned(input[range].to_string()),
+            Cow3::Owned(input) => Cow::Owned(input[range].to_string()),
+        }))
+        .map(Some)
+    }
+}
+
+pub fn split_list(input: &str) -> SplitList<'_> {
+    SplitList {
+        has_null: input.contains('\0'),
+        input,
+        at: 0,
+    }
+}
+
+pub struct SplitList<'a> {
+    input: &'a str,
+    has_null: bool,
+    at: usize,
+}
+
+impl<'a> Iterator for SplitList<'a> {
+    type Item = &'a str;
 
-        Ok(None)
+    fn next(&mut self) -> Option<&'a str> {
+        let range = super::next_str_entry(&self.input, &mut self.at, self.has_null)?;
+        Some(&self.input[range])
     }
 }