Skip to main content

qubit_mime/classifier/
media_stream_classifier.rs

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