Skip to content

Commit b5f93cb

Browse files
authored
Merge pull request #1713 from fbrouille/g_file_set_attribute
Implement gio::File::set_attribute
2 parents 7717d25 + ed44365 commit b5f93cb

File tree

4 files changed

+174
-2
lines changed

4 files changed

+174
-2
lines changed

gio/src/file.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ use glib::{prelude::*, translate::*};
66

77
#[cfg(feature = "v2_74")]
88
use crate::FileIOStream;
9-
use crate::{ffi, Cancellable, File, FileCreateFlags, FileEnumerator, FileQueryInfoFlags};
9+
use crate::{
10+
ffi, Cancellable, File, FileAttributeValue, FileCreateFlags, FileEnumerator, FileQueryInfoFlags,
11+
};
1012

1113
impl File {
1214
#[cfg(feature = "v2_74")]
@@ -1111,6 +1113,35 @@ pub trait FileExtManual: IsA<File> + Sized {
11111113

11121114
(fut, Box::pin(receiver))
11131115
}
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+
}
11141145
}
11151146

11161147
impl<O: IsA<File>> FileExtManual for O {}

gio/src/file_attribute_value.rs

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// Take a look at the license at the top of the repository in the LICENSE file.
2+
3+
use glib::{
4+
object::ObjectType,
5+
translate::{IntoGlib, ToGlibPtr},
6+
};
7+
8+
use crate::FileAttributeType;
9+
10+
use std::ffi::CStr;
11+
12+
#[derive(Debug)]
13+
pub struct FileAttributeValue<'a>(FileAttributeValueInner<'a>);
14+
15+
impl From<&str> for FileAttributeValue<'_> {
16+
fn from(value: &str) -> Self {
17+
Self(FileAttributeValueInner::String(
18+
ToGlibPtr::<*mut libc::c_char>::to_glib_none(value).1,
19+
))
20+
}
21+
}
22+
23+
impl<'a> From<&'a CStr> for FileAttributeValue<'a> {
24+
fn from(value: &'a CStr) -> Self {
25+
Self(FileAttributeValueInner::ByteString(value))
26+
}
27+
}
28+
29+
impl From<bool> for FileAttributeValue<'_> {
30+
fn from(value: bool) -> Self {
31+
Self(FileAttributeValueInner::Boolean(value.into_glib()))
32+
}
33+
}
34+
35+
impl From<u32> for FileAttributeValue<'_> {
36+
fn from(value: u32) -> Self {
37+
Self(FileAttributeValueInner::Uint32(value))
38+
}
39+
}
40+
41+
impl From<i32> for FileAttributeValue<'_> {
42+
fn from(value: i32) -> Self {
43+
Self(FileAttributeValueInner::Int32(value))
44+
}
45+
}
46+
47+
impl From<u64> for FileAttributeValue<'_> {
48+
fn from(value: u64) -> Self {
49+
Self(FileAttributeValueInner::Uint64(value))
50+
}
51+
}
52+
53+
impl From<i64> for FileAttributeValue<'_> {
54+
fn from(value: i64) -> Self {
55+
Self(FileAttributeValueInner::Int64(value))
56+
}
57+
}
58+
59+
impl<'a, T: AsRef<glib::Object>> From<&'a T> for FileAttributeValue<'a> {
60+
fn from(value: &'a T) -> Self {
61+
Self(FileAttributeValueInner::Object(value.as_ref()))
62+
}
63+
}
64+
65+
impl<'a> From<&'a [&str]> for FileAttributeValue<'a> {
66+
fn from(value: &'a [&str]) -> Self {
67+
Self(FileAttributeValueInner::Stringv(value.into()))
68+
}
69+
}
70+
71+
impl FileAttributeValue<'_> {
72+
pub(crate) fn type_(&self) -> FileAttributeType {
73+
self.0.type_()
74+
}
75+
76+
pub(crate) fn as_ptr(&self) -> glib::ffi::gpointer {
77+
self.0.as_ptr()
78+
}
79+
}
80+
81+
#[derive(Debug)]
82+
pub(crate) enum FileAttributeValueInner<'a> {
83+
#[allow(dead_code)] // TODO remove this allow attribute when Pointer will be used by this crate
84+
Pointer(FileAttributeType, glib::ffi::gpointer),
85+
String(<&'a str as ToGlibPtr<'a, *mut libc::c_char>>::Storage),
86+
ByteString(&'a CStr),
87+
Boolean(glib::ffi::gboolean),
88+
Uint32(u32),
89+
Int32(i32),
90+
Uint64(u64),
91+
Int64(i64),
92+
Object(&'a glib::Object),
93+
Stringv(glib::StrV),
94+
}
95+
96+
impl FileAttributeValueInner<'_> {
97+
pub(crate) fn type_(&self) -> FileAttributeType {
98+
match self {
99+
Self::Pointer(type_, _) => *type_,
100+
Self::String(_) => FileAttributeType::String,
101+
Self::ByteString(_) => FileAttributeType::ByteString,
102+
Self::Boolean(_) => FileAttributeType::Boolean,
103+
Self::Uint32(_) => FileAttributeType::Uint32,
104+
Self::Int32(_) => FileAttributeType::Int32,
105+
Self::Uint64(_) => FileAttributeType::Uint64,
106+
Self::Int64(_) => FileAttributeType::Int64,
107+
Self::Object(_) => FileAttributeType::Object,
108+
Self::Stringv(_) => FileAttributeType::Stringv,
109+
}
110+
}
111+
112+
pub(crate) fn as_ptr(&self) -> glib::ffi::gpointer {
113+
match self {
114+
Self::Pointer(_, s) => *s,
115+
Self::String(s) => s.as_ptr() as _,
116+
Self::ByteString(s) => s.as_ptr() as _,
117+
Self::Boolean(s) => s as *const i32 as _,
118+
Self::Uint32(s) => s as *const u32 as _,
119+
Self::Int32(s) => s as *const i32 as _,
120+
Self::Uint64(s) => s as *const u64 as _,
121+
Self::Int64(s) => s as *const i64 as _,
122+
Self::Object(s) => s.as_ptr() as _,
123+
Self::Stringv(s) => s.as_ptr() as _,
124+
}
125+
}
126+
}

gio/src/file_info.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::{
77

88
use glib::{translate::*, StrV};
99

10-
use crate::{ffi, FileInfo};
10+
use crate::{ffi, FileAttributeValue, FileInfo};
1111

1212
impl FileInfo {
1313
#[cfg_attr(feature = "v2_62", deprecated)]
@@ -71,4 +71,17 @@ impl FileInfo {
7171
});
7272
}
7373
}
74+
75+
#[doc(alias = "g_file_info_set_attribute")]
76+
pub fn set_attribute<'a>(&self, attribute: &str, value: impl Into<FileAttributeValue<'a>>) {
77+
unsafe {
78+
let value: FileAttributeValue<'a> = value.into();
79+
ffi::g_file_info_set_attribute(
80+
self.to_glib_none().0,
81+
attribute.to_glib_none().0,
82+
value.type_().into_glib(),
83+
value.as_ptr(),
84+
);
85+
}
86+
}
7487
}

gio/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ pub use crate::file_attribute_info::FileAttributeInfo;
4949
mod file_attribute_info_list;
5050
mod file_attribute_matcher;
5151
pub use crate::file_attribute_matcher::FileAttributematcherIter;
52+
mod file_attribute_value;
53+
pub use file_attribute_value::FileAttributeValue;
5254
#[cfg(unix)]
5355
mod file_descriptor_based;
5456
#[cfg(unix)]

0 commit comments

Comments
 (0)