aqc_text_engine_core/requirement/
model.rs1#![allow(
4 clippy::module_name_repetitions,
5 reason = "Public text-engine values use the TextFile prefix."
6)]
7
8use core::any::Any;
9use core::cmp::Ordering;
10use core::fmt;
11
12use aqc_file_engine_core::{
13 ConflictEntry, EngineRequirement, FileItemRequirement, ItemAssertionInput, ItemRequirements,
14 RequiredItemResolution, ResolvedItemRequirements, ResolvedRequirement, ScalarAssertion,
15 ScalarValue,
16};
17
18#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
19pub struct TextFileContents(Vec<u8>);
21
22#[derive(Debug, Clone, PartialEq, Eq)]
23pub enum TextFileValueError {
25 Empty { field: &'static str },
27}
28
29#[derive(Debug, Clone, Default)]
30pub struct TextFileRequirements {
32 pub exact_contents: Option<ScalarAssertion<TextFileContents>>,
34 pub contents: ItemRequirements<TextFileContents>,
36}
37
38#[derive(Debug, Clone, Default)]
39pub struct ResolvedTextFileRequirements {
41 pub exact_contents: Option<
43 ResolvedRequirement<ScalarAssertion<TextFileContents>, ScalarAssertion<TextFileContents>>,
44 >,
45 pub contents: ResolvedItemRequirements<TextFileContents>,
47}
48
49impl EngineRequirement for TextFileRequirements {
50 fn engine_id(&self) -> &'static str {
51 crate::ENGINE_ID
52 }
53
54 fn as_any(&self) -> &dyn Any {
55 self
56 }
57}
58
59impl TextFileContents {
60 pub fn new(value: impl Into<Vec<u8>>) -> Result<Self, TextFileValueError> {
66 let value = value.into();
67 if value.is_empty() {
68 return Err(TextFileValueError::Empty { field: "contents" });
69 }
70 Ok(Self(value))
71 }
72
73 #[must_use]
74 pub fn as_bytes(&self) -> &[u8] {
75 &self.0
76 }
77}
78
79impl fmt::Display for TextFileValueError {
80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81 match self {
82 Self::Empty { field } => write!(f, "{field} must not be empty"),
83 }
84 }
85}
86
87impl fmt::Display for TextFileContents {
88 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89 f.write_str("contents")
90 }
91}
92
93impl ScalarValue for TextFileContents {
94 fn render(&self) -> String {
95 format!("{} bytes", self.0.len())
96 }
97
98 fn compare_for_order(&self, _other: &Self) -> Option<Ordering> {
99 None
100 }
101}
102
103impl FileItemRequirement for TextFileContents {
104 type Identity = Self;
105
106 fn merge_identity(&self) -> Self::Identity {
107 self.clone()
108 }
109
110 fn compose_item(
111 key: &str,
112 items: Vec<ItemAssertionInput<Self>>,
113 conflicts: &mut Vec<ConflictEntry>,
114 ) -> Option<RequiredItemResolution<Self>> {
115 aqc_file_engine_core::compose_item_by(key, items, Clone::clone, conflicts)
116 }
117}