From b768d27f83385f16e8e3182dd9b1f7da1595525b Mon Sep 17 00:00:00 2001
From: Dmitry <b4tm4n@mail.ru>
Date: Tue, 8 Aug 2023 14:22:29 +0300
Subject: [PATCH] combine convert sync/async features

---
 lib/src/lib.rs       |  5 ---
 lib/src/questions.rs | 92 +++++++++++++-------------------------------
 2 files changed, 27 insertions(+), 70 deletions(-)

diff --git a/lib/src/lib.rs b/lib/src/lib.rs
index f4193f5..9288f96 100644
--- a/lib/src/lib.rs
+++ b/lib/src/lib.rs
@@ -1,8 +1,3 @@
-#[cfg(all(feature = "convert", feature = "convert_async"))]
-compile_error!(
-    "feature \"convert\" and feature \"convert_async\" cannot be enabled at the same time"
-);
-
 #[cfg(feature = "async")]
 pub mod async_db;
 #[cfg(feature = "sync")]
diff --git a/lib/src/questions.rs b/lib/src/questions.rs
index 409f018..ff46b41 100644
--- a/lib/src/questions.rs
+++ b/lib/src/questions.rs
@@ -69,8 +69,8 @@ pub struct Question {
     pub batch_info: BatchInfo,
 }
 
-#[cfg(feature = "convert")]
-pub mod convert {
+#[cfg(any(feature = "convert", feature = "convert_async"))]
+pub mod convert_common {
     use super::{BatchInfo, Question};
     use crate::source::{SourceQuestion, SourceQuestionsBatch};
 
@@ -116,6 +116,12 @@ pub mod convert {
             result
         }
     }
+}
+
+#[cfg(feature = "convert")]
+pub mod convert {
+    use super::Question;
+    use crate::source::SourceQuestionsBatch;
 
     pub trait QuestionsConverter {
         fn convert<'a>(&'a mut self) -> Box<dyn Iterator<Item = Question> + 'a>;
@@ -145,58 +151,10 @@ pub use convert::QuestionsConverter;
 pub mod convert_async {
     use futures::stream;
     use futures_core::stream::Stream;
-    use futures_core::Future;
-    use futures_util::{pin_mut, StreamExt};
+    use futures_util::StreamExt;
 
-    use std::future;
-    use std::pin::Pin;
-    use std::task::{Context, Poll};
-
-    use super::{BatchInfo, Question};
-    use crate::source::{SourceQuestion, SourceQuestionsBatch};
-
-    macro_rules! make {
-        ($Target:ident; by {$($field:ident),+}; from $src:expr) => {$Target {$(
-            $field: $src.$field
-        ),+}};
-        ($Target:ident; with defaults and by {$($field:ident),+}; from $src:expr) => {$Target {$(
-            $field: $src.$field
-        ),+ ,..$Target::default()}}
-    }
-
-    impl From<SourceQuestion> for Question {
-        fn from(src: SourceQuestion) -> Self {
-            make! {Self; with defaults and by {
-                num, id, description, answer, author, comment, comment1, tour, url,
-                date, processed_by, redacted_by, copyright, theme, kind, source, rating
-            }; from src}
-        }
-    }
-
-    impl From<SourceQuestionsBatch> for BatchInfo {
-        fn from(src: SourceQuestionsBatch) -> Self {
-            make! {Self; by {
-                filename, description, author, comment, url, date,
-                processed_by, redacted_by, copyright, theme, kind, source, rating
-            }; from src}
-        }
-    }
-
-    impl From<SourceQuestionsBatch> for Vec<Question> {
-        fn from(src: SourceQuestionsBatch) -> Self {
-            let mut result: Vec<Question> = src
-                .questions
-                .iter()
-                .map(|item| item.clone().into())
-                .collect();
-            let batch_info = BatchInfo::from(src);
-            result.iter_mut().for_each(|question| {
-                question.batch_info = batch_info.clone();
-            });
-
-            result
-        }
-    }
+    use super::Question;
+    use crate::source::SourceQuestionsBatch;
 
     pub struct QuestionsConverterAsync<T>
     where
@@ -222,18 +180,22 @@ pub mod convert_async {
             + std::marker::Unpin,
     {
         pub fn convert(self) -> impl Stream<Item = Question> {
-            self.inner.filter_map(|(name,r)| async move {
-                if r.is_err() {
-                    None
-                } else {
-                    Some((name, r.unwrap()))
-                }
-            }).flat_map(|(filename, batch)| stream::iter({
-                let mut batch = batch;
-                batch.filename = filename;
-                let questions: Vec<Question> = batch.into();
-                questions
-            }))
+            self.inner
+                .filter_map(|(name, res)| async move {
+                    if let Ok(item) = res {
+                        Some((name, item))
+                    } else {
+                        None
+                    }
+                })
+                .flat_map(|(filename, batch)| {
+                    stream::iter({
+                        let mut batch = batch;
+                        batch.filename = filename;
+                        let questions: Vec<Question> = batch.into();
+                        questions
+                    })
+                })
         }
     }
 }