qubit_mime/classifier/file_based_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//! File-backed media stream classifier helpers.
9
10use std::fmt::Debug;
11use std::io::Read;
12use std::path::Path;
13
14use crate::DEFAULT_MEDIA_STREAM_MAX_STAGING_SIZE;
15use crate::{
16 MediaStreamClassifierBackend,
17 MediaStreamType,
18 MimeResult,
19};
20
21use super::media_stream_classifier_helpers::with_temp_reader;
22
23/// Core implementation contract for classifiers that only operate on local
24/// files.
25pub trait FileBasedMediaStreamClassifier: Debug + Send + Sync {
26 /// Gets the maximum bytes staged from reader/content input.
27 ///
28 /// # Returns
29 /// Maximum accepted stream size before staging is rejected.
30 fn max_staging_size(&self) -> u64 {
31 DEFAULT_MEDIA_STREAM_MAX_STAGING_SIZE
32 }
33
34 /// Classifies one validated local file.
35 ///
36 /// # Parameters
37 /// - `file`: Readable local media file.
38 ///
39 /// # Returns
40 /// Media stream classification.
41 ///
42 /// # Errors
43 /// Returns [`MimeError::Io`](crate::MimeError::Io) or another
44 /// [`MimeError`](crate::MimeError) when backend classification fails.
45 fn classify_by_local_file(
46 &self,
47 file: &Path,
48 ) -> MimeResult<MediaStreamType>;
49}
50
51impl<T> MediaStreamClassifierBackend for T
52where
53 T: FileBasedMediaStreamClassifier,
54{
55 /// Delegates local-file classification to the file-based hook.
56 fn classify_by_local_file(
57 &self,
58 file: &Path,
59 ) -> MimeResult<MediaStreamType> {
60 FileBasedMediaStreamClassifier::classify_by_local_file(self, file)
61 }
62
63 /// Stages stream content to a temporary local file before classification.
64 fn classify_by_content(
65 &self,
66 reader: &mut dyn Read,
67 ) -> MimeResult<MediaStreamType> {
68 with_temp_reader(reader, self.max_staging_size(), |path| {
69 FileBasedMediaStreamClassifier::classify_by_local_file(self, path)
70 })
71 }
72}