1use starnix_uapi::open_flags::OpenFlags;
6use {fidl_fuchsia_io as fio, fidl_fuchsia_starnix_binder as fbinder};
7
8pub trait FromFidl<T>: Sized {
9 fn from_fidl(value: T) -> Self;
10}
11
12pub trait IntoFidl<T>: Sized {
13 fn into_fidl(self) -> T;
15}
16
17impl<T, U> IntoFidl<U> for T
18where
19 U: FromFidl<T>,
20{
21 fn into_fidl(self) -> U {
22 U::from_fidl(self)
23 }
24}
25
26impl FromFidl<fio::OpenFlags> for OpenFlags {
27 fn from_fidl(fio_flags: fio::OpenFlags) -> Self {
28 let mut result = if fio_flags.contains(fio::OpenFlags::RIGHT_WRITABLE) {
29 if fio_flags.contains(fio::OpenFlags::RIGHT_READABLE) {
30 OpenFlags::RDWR
31 } else {
32 OpenFlags::WRONLY
33 }
34 } else {
35 OpenFlags::RDONLY
36 };
37 if fio_flags.contains(fio::OpenFlags::CREATE) {
38 result |= OpenFlags::CREAT;
39 }
40 if fio_flags.contains(fio::OpenFlags::CREATE_IF_ABSENT) {
41 result |= OpenFlags::EXCL;
42 }
43 if fio_flags.contains(fio::OpenFlags::TRUNCATE) {
44 result |= OpenFlags::TRUNC;
45 }
46 if fio_flags.contains(fio::OpenFlags::APPEND) {
47 result |= OpenFlags::APPEND;
48 }
49 if fio_flags.contains(fio::OpenFlags::DIRECTORY) {
50 result |= OpenFlags::DIRECTORY;
51 }
52 result
53 }
54}
55
56impl FromFidl<OpenFlags> for fio::OpenFlags {
57 fn from_fidl(flags: OpenFlags) -> fio::OpenFlags {
58 let mut result = fio::OpenFlags::empty();
59 if flags.can_read() {
60 result |= fio::OpenFlags::RIGHT_READABLE | fio::OpenFlags::POSIX_WRITABLE;
61 }
62 if flags.can_write() {
63 result |= fio::OpenFlags::RIGHT_WRITABLE;
64 }
65 if flags.contains(OpenFlags::CREAT) {
66 result |= fio::OpenFlags::CREATE;
67 }
68 if flags.contains(OpenFlags::EXCL) {
69 result |= fio::OpenFlags::CREATE_IF_ABSENT;
70 }
71 if flags.contains(OpenFlags::TRUNC) {
72 result |= fio::OpenFlags::TRUNCATE;
73 }
74 if flags.contains(OpenFlags::APPEND) {
75 result |= fio::OpenFlags::APPEND;
76 }
77 if flags.contains(OpenFlags::DIRECTORY) {
78 result |= fio::OpenFlags::DIRECTORY;
79 }
80 result
81 }
82}
83
84impl FromFidl<OpenFlags> for fbinder::FileFlags {
85 fn from_fidl(flags: OpenFlags) -> Self {
86 let mut result = Self::empty();
87 if flags.can_read() {
88 result |= Self::RIGHT_READABLE;
89 }
90 if flags.can_write() {
91 result |= Self::RIGHT_WRITABLE;
92 }
93 if flags.contains(OpenFlags::DIRECTORY) {
94 result |= Self::DIRECTORY;
95 }
96
97 result
98 }
99}
100
101impl FromFidl<fbinder::FileFlags> for OpenFlags {
102 fn from_fidl(flags: fbinder::FileFlags) -> Self {
103 let readable = flags.contains(fbinder::FileFlags::RIGHT_READABLE);
104 let writable = flags.contains(fbinder::FileFlags::RIGHT_WRITABLE);
105 let mut result = Self::empty();
106 if readable && writable {
107 result = Self::RDWR;
108 } else if writable {
109 result = Self::WRONLY;
110 } else if readable {
111 result = Self::RDONLY;
112 }
113 if flags.contains(fbinder::FileFlags::DIRECTORY) {
114 result |= Self::DIRECTORY;
115 }
116 result
117 }
118}
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123 use starnix_uapi::uapi;
124
125 fn assert_flags_equals(flags: OpenFlags, fio_flags: fio::OpenFlags) {
126 assert_eq!(flags, fio_flags.into_fidl());
127 assert_eq!(fio_flags, flags.into_fidl());
128 }
129
130 #[::fuchsia::test]
131 fn test_access() {
132 let read_only = OpenFlags::from_bits_truncate(uapi::O_RDONLY);
133 assert!(read_only.can_read());
134 assert!(!read_only.can_write());
135
136 let write_only = OpenFlags::from_bits_truncate(uapi::O_WRONLY);
137 assert!(!write_only.can_read());
138 assert!(write_only.can_write());
139
140 let read_write = OpenFlags::from_bits_truncate(uapi::O_RDWR);
141 assert!(read_write.can_read());
142 assert!(read_write.can_write());
143 }
144
145 #[::fuchsia::test]
146 fn test_conversion() {
147 assert_flags_equals(
148 OpenFlags::RDONLY,
149 fio::OpenFlags::RIGHT_READABLE | fio::OpenFlags::POSIX_WRITABLE,
150 );
151 assert_flags_equals(OpenFlags::WRONLY, fio::OpenFlags::RIGHT_WRITABLE);
152 assert_flags_equals(
153 OpenFlags::RDWR,
154 fio::OpenFlags::RIGHT_READABLE
155 | fio::OpenFlags::RIGHT_WRITABLE
156 | fio::OpenFlags::POSIX_WRITABLE,
157 );
158 }
159}