pyoxidizerlib/starlark/
file.rs1use {
6 super::python_resource::ResourceCollectionContext,
7 python_packaging::{
8 resource::PythonResource, resource_collection::PythonResourceAddCollectionContext,
9 },
10 simple_file_manifest::File,
11 starlark::values::{
12 error::{RuntimeError, UnsupportedOperation, ValueError},
13 {Mutable, TypedValue, Value, ValueResult},
14 },
15 std::sync::{Arc, Mutex, MutexGuard},
16};
17
18#[derive(Debug)]
19pub struct FileWrapper {
20 pub file: File,
21 pub add_context: Option<PythonResourceAddCollectionContext>,
22}
23
24#[derive(Clone, Debug)]
26pub struct FileValue {
27 inner: Arc<Mutex<FileWrapper>>,
28 path: String,
29}
30
31impl FileValue {
32 pub fn new(file: File) -> Self {
33 let path = file.path_string();
34
35 Self {
36 inner: Arc::new(Mutex::new(FileWrapper {
37 file,
38 add_context: None,
39 })),
40 path,
41 }
42 }
43
44 pub fn inner(&self, label: &str) -> Result<MutexGuard<FileWrapper>, ValueError> {
45 self.inner.try_lock().map_err(|e| {
46 ValueError::Runtime(RuntimeError {
47 code: "FILE",
48 message: format!("failed to acquire lock: {}", e),
49 label: label.to_string(),
50 })
51 })
52 }
53}
54
55impl ResourceCollectionContext for FileValue {
56 fn add_collection_context(
57 &self,
58 ) -> Result<Option<PythonResourceAddCollectionContext>, ValueError> {
59 Ok(self
60 .inner("File.add_collection_context()")?
61 .add_context
62 .clone())
63 }
64
65 fn replace_add_collection_context(
66 &mut self,
67 context: PythonResourceAddCollectionContext,
68 ) -> Result<Option<PythonResourceAddCollectionContext>, ValueError> {
69 Ok(self
70 .inner("File.replace_add_collection_context()")?
71 .add_context
72 .replace(context))
73 }
74
75 fn as_python_resource(&self) -> Result<PythonResource<'_>, ValueError> {
76 Ok(PythonResource::from(
77 self.inner("File.as_python_resource()")?.file.clone(),
78 ))
79 }
80}
81
82impl TypedValue for FileValue {
83 type Holder = Mutable<FileValue>;
84 const TYPE: &'static str = "File";
85
86 fn values_for_descendant_check_and_freeze(&self) -> Box<dyn Iterator<Item = Value>> {
87 Box::new(std::iter::empty())
88 }
89
90 fn to_str(&self) -> String {
91 format!("{}<path={}>", Self::TYPE, self.path,)
92 }
93
94 fn to_repr(&self) -> String {
95 self.to_str()
96 }
97
98 fn get_attr(&self, attribute: &str) -> ValueResult {
99 let inner = self.inner(&format!("File.{}", attribute))?;
100
101 let v = match attribute {
102 "path" => Value::from(inner.file.path_string()),
103 "is_executable" => Value::from(inner.file.entry().is_executable()),
104 attr => {
105 drop(inner);
106
107 return if self.add_collection_context_attrs().contains(&attr) {
108 self.get_attr_add_collection_context(attr)
109 } else {
110 Err(ValueError::OperationNotSupported {
111 op: UnsupportedOperation::GetAttr(attr.to_string()),
112 left: Self::TYPE.to_string(),
113 right: None,
114 })
115 };
116 }
117 };
118
119 Ok(v)
120 }
121
122 fn has_attr(&self, attribute: &str) -> Result<bool, ValueError> {
123 Ok(match attribute {
124 "path" => true,
125 "is_executable" => true,
126 attr => self.add_collection_context_attrs().contains(&attr),
127 })
128 }
129
130 fn set_attr(&mut self, attribute: &str, value: Value) -> Result<(), ValueError> {
131 self.set_attr_add_collection_context(attribute, value)
132 }
133}