|
1 | 1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | 2 |
|
3 | | -use std::{cell::RefCell, mem, pin::Pin, ptr}; |
| 3 | +use std::{cell::RefCell, ffi::CStr, mem, pin::Pin, ptr}; |
4 | 4 |
|
5 | 5 | use glib::{prelude::*, translate::*}; |
6 | 6 |
|
7 | 7 | #[cfg(feature = "v2_74")] |
8 | 8 | use crate::FileIOStream; |
9 | | -use crate::{ffi, Cancellable, File, FileCreateFlags, FileEnumerator, FileQueryInfoFlags}; |
| 9 | +use crate::{ |
| 10 | + ffi, Cancellable, File, FileAttributeType, FileCreateFlags, FileEnumerator, FileQueryInfoFlags, |
| 11 | +}; |
10 | 12 |
|
11 | 13 | impl File { |
12 | 14 | #[cfg(feature = "v2_74")] |
@@ -1111,6 +1113,151 @@ pub trait FileExtManual: IsA<File> + Sized { |
1111 | 1113 |
|
1112 | 1114 | (fut, Box::pin(receiver)) |
1113 | 1115 | } |
| 1116 | + |
| 1117 | + #[doc(alias = "g_file_set_attribute")] |
| 1118 | + fn set_attribute<'a>( |
| 1119 | + &self, |
| 1120 | + attribute: &str, |
| 1121 | + value: impl Into<FileAttributeValue<'a>>, |
| 1122 | + flags: FileQueryInfoFlags, |
| 1123 | + cancellable: Option<&impl IsA<Cancellable>>, |
| 1124 | + ) -> Result<(), glib::Error> { |
| 1125 | + unsafe { |
| 1126 | + let mut error = std::ptr::null_mut(); |
| 1127 | + let value: FileAttributeValue<'a> = value.into(); |
| 1128 | + let is_ok = ffi::g_file_set_attribute( |
| 1129 | + self.as_ref().to_glib_none().0, |
| 1130 | + attribute.to_glib_none().0, |
| 1131 | + value.type_().into_glib(), |
| 1132 | + value.as_ptr(), |
| 1133 | + flags.into_glib(), |
| 1134 | + cancellable.map(|p| p.as_ref()).to_glib_none().0, |
| 1135 | + &mut error, |
| 1136 | + ); |
| 1137 | + debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null()); |
| 1138 | + if error.is_null() { |
| 1139 | + Ok(()) |
| 1140 | + } else { |
| 1141 | + Err(from_glib_full(error)) |
| 1142 | + } |
| 1143 | + } |
| 1144 | + } |
1114 | 1145 | } |
1115 | 1146 |
|
1116 | 1147 | impl<O: IsA<File>> FileExtManual for O {} |
| 1148 | + |
| 1149 | +#[derive(Debug)] |
| 1150 | +pub struct FileAttributeValue<'a>(FileAttributeValueInner<'a>); |
| 1151 | + |
| 1152 | +impl From<&str> for FileAttributeValue<'_> { |
| 1153 | + fn from(value: &str) -> Self { |
| 1154 | + Self(FileAttributeValueInner::String( |
| 1155 | + ToGlibPtr::<*mut libc::c_char>::to_glib_none(value).1, |
| 1156 | + )) |
| 1157 | + } |
| 1158 | +} |
| 1159 | + |
| 1160 | +impl<'a> From<&'a CStr> for FileAttributeValue<'a> { |
| 1161 | + fn from(value: &'a CStr) -> Self { |
| 1162 | + Self(FileAttributeValueInner::ByteString(value)) |
| 1163 | + } |
| 1164 | +} |
| 1165 | + |
| 1166 | +impl From<bool> for FileAttributeValue<'_> { |
| 1167 | + fn from(value: bool) -> Self { |
| 1168 | + Self(FileAttributeValueInner::Boolean(value.into_glib())) |
| 1169 | + } |
| 1170 | +} |
| 1171 | + |
| 1172 | +impl From<u32> for FileAttributeValue<'_> { |
| 1173 | + fn from(value: u32) -> Self { |
| 1174 | + Self(FileAttributeValueInner::Uint32(value)) |
| 1175 | + } |
| 1176 | +} |
| 1177 | + |
| 1178 | +impl From<i32> for FileAttributeValue<'_> { |
| 1179 | + fn from(value: i32) -> Self { |
| 1180 | + Self(FileAttributeValueInner::Int32(value)) |
| 1181 | + } |
| 1182 | +} |
| 1183 | + |
| 1184 | +impl From<u64> for FileAttributeValue<'_> { |
| 1185 | + fn from(value: u64) -> Self { |
| 1186 | + Self(FileAttributeValueInner::Uint64(value)) |
| 1187 | + } |
| 1188 | +} |
| 1189 | + |
| 1190 | +impl From<i64> for FileAttributeValue<'_> { |
| 1191 | + fn from(value: i64) -> Self { |
| 1192 | + Self(FileAttributeValueInner::Int64(value)) |
| 1193 | + } |
| 1194 | +} |
| 1195 | + |
| 1196 | +impl<'a, T: AsRef<glib::Object>> From<&'a T> for FileAttributeValue<'a> { |
| 1197 | + fn from(value: &'a T) -> Self { |
| 1198 | + Self(FileAttributeValueInner::Object(value.as_ref())) |
| 1199 | + } |
| 1200 | +} |
| 1201 | + |
| 1202 | +impl<'a> From<&'a [&str]> for FileAttributeValue<'a> { |
| 1203 | + fn from(value: &'a [&str]) -> Self { |
| 1204 | + Self(FileAttributeValueInner::Stringv(value.into())) |
| 1205 | + } |
| 1206 | +} |
| 1207 | + |
| 1208 | +impl FileAttributeValue<'_> { |
| 1209 | + pub(crate) fn type_(&self) -> FileAttributeType { |
| 1210 | + self.0.type_() |
| 1211 | + } |
| 1212 | + |
| 1213 | + pub(crate) fn as_ptr(&self) -> glib::ffi::gpointer { |
| 1214 | + self.0.as_ptr() |
| 1215 | + } |
| 1216 | +} |
| 1217 | + |
| 1218 | +#[derive(Debug)] |
| 1219 | +enum FileAttributeValueInner<'a> { |
| 1220 | + #[allow(dead_code)] // TODO remove this allow attribute when Pointer will be used by this crate |
| 1221 | + Pointer(FileAttributeType, glib::ffi::gpointer), |
| 1222 | + String(<&'a str as ToGlibPtr<'a, *mut libc::c_char>>::Storage), |
| 1223 | + ByteString(&'a CStr), |
| 1224 | + Boolean(glib::ffi::gboolean), |
| 1225 | + Uint32(u32), |
| 1226 | + Int32(i32), |
| 1227 | + Uint64(u64), |
| 1228 | + Int64(i64), |
| 1229 | + Object(&'a glib::Object), |
| 1230 | + Stringv(glib::StrV), |
| 1231 | +} |
| 1232 | + |
| 1233 | +impl FileAttributeValueInner<'_> { |
| 1234 | + fn type_(&self) -> FileAttributeType { |
| 1235 | + match self { |
| 1236 | + Self::Pointer(type_, _) => *type_, |
| 1237 | + Self::String(_) => FileAttributeType::String, |
| 1238 | + Self::ByteString(_) => FileAttributeType::ByteString, |
| 1239 | + Self::Boolean(_) => FileAttributeType::Boolean, |
| 1240 | + Self::Uint32(_) => FileAttributeType::Uint32, |
| 1241 | + Self::Int32(_) => FileAttributeType::Int32, |
| 1242 | + Self::Uint64(_) => FileAttributeType::Uint64, |
| 1243 | + Self::Int64(_) => FileAttributeType::Int64, |
| 1244 | + Self::Object(_) => FileAttributeType::Object, |
| 1245 | + Self::Stringv(_) => FileAttributeType::Stringv, |
| 1246 | + } |
| 1247 | + } |
| 1248 | + |
| 1249 | + fn as_ptr(&self) -> glib::ffi::gpointer { |
| 1250 | + match self { |
| 1251 | + Self::Pointer(_, s) => *s, |
| 1252 | + Self::String(s) => s.as_ptr() as _, |
| 1253 | + Self::ByteString(s) => s.as_ptr() as _, |
| 1254 | + Self::Boolean(s) => s as *const i32 as _, |
| 1255 | + Self::Uint32(s) => s as *const u32 as _, |
| 1256 | + Self::Int32(s) => s as *const i32 as _, |
| 1257 | + Self::Uint64(s) => s as *const u64 as _, |
| 1258 | + Self::Int64(s) => s as *const i64 as _, |
| 1259 | + Self::Object(s) => s.as_ptr() as _, |
| 1260 | + Self::Stringv(s) => s.as_ptr() as _, |
| 1261 | + } |
| 1262 | + } |
| 1263 | +} |
0 commit comments