ferrin_core/stream_text/transforms/
mod.rs1mod smooth;
9
10use crate::error::Error;
11use std::fmt;
12use std::sync::Arc;
13use std::sync::Mutex;
14
15use ferrin_tool::ToolSet;
16use tokio_util::sync::CancellationToken;
17
18use super::result::EventStream;
19
20pub use smooth::ChunkDetector;
21pub use smooth::Chunking;
22pub use smooth::SmoothStream;
23pub use smooth::SmoothStreamConfig;
24pub use smooth::smooth_stream;
25
26#[derive(Clone)]
28pub struct TransformContext {
29 tools: Arc<ToolSet>,
30 cancellation: CancellationToken,
31 stop: CancellationToken,
32 failure: Arc<Mutex<Option<Error>>>,
33}
34
35impl TransformContext {
36 pub(crate) fn new(tools: Arc<ToolSet>, cancellation: CancellationToken) -> Self {
37 Self {
38 tools,
39 cancellation,
40 stop: CancellationToken::new(),
41 failure: Arc::new(Mutex::new(None)),
42 }
43 }
44
45 pub(crate) fn stop_token(&self) -> CancellationToken {
48 self.stop.clone()
49 }
50
51 pub(crate) fn take_failure(&self) -> Option<Error> {
52 self.failure
53 .lock()
54 .unwrap_or_else(std::sync::PoisonError::into_inner)
55 .take()
56 }
57
58 pub(crate) fn cancellation(&self) -> &CancellationToken {
59 &self.cancellation
60 }
61
62 pub fn fail(&self, error: Error) {
67 let mut failure = self
68 .failure
69 .lock()
70 .unwrap_or_else(std::sync::PoisonError::into_inner);
71 if failure.is_none() {
72 *failure = Some(error);
73 }
74 drop(failure);
75 self.stop();
76 }
77
78 #[must_use]
80 pub fn tools(&self) -> &ToolSet {
81 &self.tools
82 }
83
84 pub fn stop(&self) {
89 self.stop.cancel();
90 self.cancellation.cancel();
91 }
92}
93
94impl fmt::Debug for TransformContext {
95 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
96 f.debug_struct("TransformContext")
97 .field("tools", &self.tools.names().collect::<Vec<_>>())
98 .field("stopped", &self.stop.is_cancelled())
99 .finish()
100 }
101}
102
103pub trait StreamTransform: Send + Sync {
108 fn apply(&self, input: EventStream, ctx: TransformContext) -> EventStream;
110}
111
112impl<F> StreamTransform for F
113where
114 F: Fn(EventStream, TransformContext) -> EventStream + Send + Sync,
115{
116 fn apply(&self, input: EventStream, ctx: TransformContext) -> EventStream {
117 self(input, ctx)
118 }
119}