qubit_mime/classifier/media_stream_classifier.rs
1// =============================================================================
2// Copyright (c) 2026 Haixing Hu.
3//
4// SPDX-License-Identifier: Apache-2.0
5//
6// Licensed under the Apache License, Version 2.0.
7// =============================================================================
8//! Top-level media stream classifier interface.
9
10use std::fmt::Debug;
11use std::io::{
12 Cursor,
13 Read,
14};
15use std::path::Path;
16use std::sync::Arc;
17
18use crate::MimeResult;
19
20use super::MediaStreamType;
21
22/// Classifies a media source by the audio and video streams it contains.
23pub trait MediaStreamClassifier: Debug + Send + Sync {
24 /// Classifies a local file.
25 ///
26 /// # Parameters
27 /// - `file`: Local media file.
28 ///
29 /// # Returns
30 /// Media stream classification.
31 ///
32 /// # Errors
33 /// Returns [`MimeError::Io`](crate::MimeError::Io) when the file cannot be
34 /// read, or another [`MimeError`](crate::MimeError) when the classifier
35 /// backend fails.
36 fn classify_file(&self, file: &Path) -> MimeResult<MediaStreamType>;
37
38 /// Classifies media bytes from a reader.
39 ///
40 /// # Parameters
41 /// - `reader`: Media stream to classify. The stream is consumed as needed
42 /// by the classifier.
43 ///
44 /// # Returns
45 /// Media stream classification.
46 ///
47 /// # Errors
48 /// Returns [`MimeError::Io`](crate::MimeError::Io) when the stream cannot
49 /// be read, or another [`MimeError`](crate::MimeError) when the
50 /// classifier backend fails.
51 fn classify_reader(
52 &self,
53 reader: &mut dyn Read,
54 ) -> MimeResult<MediaStreamType>;
55
56 /// Classifies an in-memory media payload.
57 ///
58 /// # Parameters
59 /// - `content`: Media bytes to classify.
60 ///
61 /// # Returns
62 /// Media stream classification.
63 ///
64 /// # Errors
65 /// Returns [`MimeError::Io`](crate::MimeError::Io) when a file-backed
66 /// classifier cannot stage the content.
67 fn classify_content(&self, content: &[u8]) -> MimeResult<MediaStreamType> {
68 let mut cursor = Cursor::new(content);
69 self.classify_reader(&mut cursor)
70 }
71}
72
73impl MediaStreamClassifier for Box<dyn MediaStreamClassifier> {
74 /// Delegates file classification to the boxed classifier.
75 fn classify_file(&self, file: &Path) -> MimeResult<MediaStreamType> {
76 self.as_ref().classify_file(file)
77 }
78
79 /// Delegates stream classification to the boxed classifier.
80 fn classify_reader(
81 &self,
82 reader: &mut dyn Read,
83 ) -> MimeResult<MediaStreamType> {
84 self.as_ref().classify_reader(reader)
85 }
86}
87
88impl MediaStreamClassifier for Arc<dyn MediaStreamClassifier> {
89 /// Delegates file classification to the shared classifier.
90 fn classify_file(&self, file: &Path) -> MimeResult<MediaStreamType> {
91 self.as_ref().classify_file(file)
92 }
93
94 /// Delegates stream classification to the shared classifier.
95 fn classify_reader(
96 &self,
97 reader: &mut dyn Read,
98 ) -> MimeResult<MediaStreamType> {
99 self.as_ref().classify_reader(reader)
100 }
101}