cadmpeg_core/decode/
companion.rs1use std::fmt::Debug;
5
6use crate::CodecError;
7
8use super::context::DecodeContext;
9use super::view::{u64_from_index, View};
10
11#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct Companion {
14 pub id: String,
17 pub bytes: Vec<u8>,
19}
20
21pub trait Companions: Debug {
23 fn open(&self, anchor: Option<&str>, path: &str, max_bytes: u64) -> Result<Companion, String>;
28
29 fn locate(&self, _anchor: Option<&str>, _path: &str) -> Result<String, String> {
34 Err("the companion file source does not locate files".to_owned())
35 }
36}
37
38#[derive(Debug, Clone)]
40pub enum CompanionLoad<'a> {
41 Loaded {
43 id: String,
45 view: View<'a>,
47 },
48 Unavailable(String),
50}
51
52impl<'a> DecodeContext<'a> {
53 #[must_use]
55 pub fn with_companions(mut self, companions: &'a dyn Companions) -> Self {
56 self.companions = Some(companions);
57 self
58 }
59
60 pub fn open_companion(
64 &self,
65 anchor: Option<&str>,
66 path: &str,
67 ) -> Result<CompanionLoad<'a>, CodecError> {
68 let Some(companions) = self.companions else {
69 return Ok(CompanionLoad::Unavailable(
70 "the decode has no companion file source".to_owned(),
71 ));
72 };
73 let max = self
74 .policy()
75 .limits
76 .max_input_bytes
77 .checked_sub(self.budget.input_bytes())
78 .ok_or_else(|| self.refuse_input_limit(0, "open companion file"))?;
79 match companions.open(anchor, path, max) {
80 Ok(companion) => {
81 self.budget
82 .charge_input(u64_from_index(companion.bytes.len()), "open companion file")?;
83 let bytes = self.arena.alloc(companion.bytes.into_boxed_slice());
84 let space = self.allocate_space()?;
85 Ok(CompanionLoad::Loaded {
86 id: companion.id,
87 view: View::over_space(bytes, space),
88 })
89 }
90 Err(reason) => Ok(CompanionLoad::Unavailable(reason)),
91 }
92 }
93
94 pub fn locate_companion(&self, anchor: Option<&str>, path: &str) -> Result<String, String> {
98 match self.companions {
99 Some(companions) => companions.locate(anchor, path),
100 None => Err("the decode has no companion file source".to_owned()),
101 }
102 }
103}
104
105#[cfg(test)]
106mod tests;