compression/
aa_field_key.rs1use crate::{ffi, util, CompressionError, Result};
2use std::ffi::{c_void, CStr};
3use std::fmt;
4use std::ptr::NonNull;
5
6#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
8pub struct FieldKey(u32);
9
10fn parse_field_key(value: &str) -> Result<FieldKey> {
11 if value.len() != 3 || !value.bytes().all(|byte| byte.is_ascii() && byte != 0) {
12 return Err(CompressionError::InvalidFieldKey {
13 key: value.to_string(),
14 });
15 }
16
17 let upper = value.to_ascii_uppercase();
18 let bytes = upper.as_bytes();
19 Ok(FieldKey::from_bytes([bytes[0], bytes[1], bytes[2]]))
20}
21
22impl FieldKey {
23 pub const ACL: Self = Self::from_bytes(*b"ACL");
25 pub const BTM: Self = Self::from_bytes(*b"BTM");
27 pub const CKS: Self = Self::from_bytes(*b"CKS");
29 pub const CLC: Self = Self::from_bytes(*b"CLC");
31 pub const CTM: Self = Self::from_bytes(*b"CTM");
33 pub const DAT: Self = Self::from_bytes(*b"DAT");
35 pub const DEV: Self = Self::from_bytes(*b"DEV");
37 pub const DE2: Self = Self::from_bytes(*b"DE2");
39 pub const DUZ: Self = Self::from_bytes(*b"DUZ");
41 pub const FLG: Self = Self::from_bytes(*b"FLG");
43 pub const GID: Self = Self::from_bytes(*b"GID");
45 pub const GIN: Self = Self::from_bytes(*b"GIN");
47 pub const HLC: Self = Self::from_bytes(*b"HLC");
49 pub const IDX: Self = Self::from_bytes(*b"IDX");
51 pub const IDZ: Self = Self::from_bytes(*b"IDZ");
53 pub const INO: Self = Self::from_bytes(*b"INO");
55 pub const LNK: Self = Self::from_bytes(*b"LNK");
57 pub const MOD: Self = Self::from_bytes(*b"MOD");
59 pub const MTM: Self = Self::from_bytes(*b"MTM");
61 pub const NLK: Self = Self::from_bytes(*b"NLK");
63 pub const PAT: Self = Self::from_bytes(*b"PAT");
65 pub const SH1: Self = Self::from_bytes(*b"SH1");
67 pub const SH2: Self = Self::from_bytes(*b"SH2");
69 pub const SH3: Self = Self::from_bytes(*b"SH3");
71 pub const SH5: Self = Self::from_bytes(*b"SH5");
73 pub const SIZ: Self = Self::from_bytes(*b"SIZ");
75 pub const SLC: Self = Self::from_bytes(*b"SLC");
77 pub const TYP: Self = Self::from_bytes(*b"TYP");
79 pub const UID: Self = Self::from_bytes(*b"UID");
81 pub const UIN: Self = Self::from_bytes(*b"UIN");
83 pub const XAT: Self = Self::from_bytes(*b"XAT");
85 pub const YAF: Self = Self::from_bytes(*b"YAF");
87
88 pub const fn from_bytes(bytes: [u8; 3]) -> Self {
90 Self(u32::from_le_bytes([bytes[0], bytes[1], bytes[2], 0]))
91 }
92
93 pub fn parse(value: &str) -> Result<Self> {
95 parse_field_key(value)
96 }
97
98 pub(crate) const fn from_raw(raw: u32) -> Self {
99 Self(raw)
100 }
101
102 pub const fn raw(self) -> u32 {
104 self.0
105 }
106
107 pub const fn as_bytes(self) -> [u8; 3] {
109 let [a, b, c, _] = self.0.to_le_bytes();
110 [a, b, c]
111 }
112
113 pub fn as_string(self) -> String {
115 String::from_utf8_lossy(&self.as_bytes()).into_owned()
116 }
117}
118
119impl fmt::Debug for FieldKey {
120 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121 write!(f, "FieldKey({self})")
122 }
123}
124
125impl std::str::FromStr for FieldKey {
126 type Err = CompressionError;
127
128 fn from_str(value: &str) -> Result<Self> {
129 parse_field_key(value)
130 }
131}
132
133impl fmt::Display for FieldKey {
134 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135 f.write_str(&self.as_string())
136 }
137}
138
139impl TryFrom<&str> for FieldKey {
140 type Error = CompressionError;
141
142 fn try_from(value: &str) -> Result<Self> {
143 parse_field_key(value)
144 }
145}
146
147#[derive(Debug)]
149pub struct FieldKeySet {
150 handle: NonNull<c_void>,
151}
152
153impl FieldKeySet {
154 pub fn new() -> Result<Self> {
156 let handle = unsafe { ffi::aa_field_key::compression_rs_aa_field_key_set_create() };
157 Ok(Self {
158 handle: util::nonnull_handle(handle, "AAFieldKeySetCreate")?,
159 })
160 }
161
162 pub fn from_csv(value: &str) -> Result<Self> {
164 let value = util::cstring("value", value)?;
165 let handle = unsafe {
166 ffi::aa_field_key::compression_rs_aa_field_key_set_create_with_string(value.as_ptr())
167 };
168 Ok(Self {
169 handle: util::nonnull_handle(handle, "AAFieldKeySetCreateWithString")?,
170 })
171 }
172
173 pub(crate) fn as_ptr(&self) -> *mut c_void {
174 self.handle.as_ptr()
175 }
176
177 pub fn clear(&mut self) -> Result<()> {
179 let status =
180 unsafe { ffi::aa_field_key::compression_rs_aa_field_key_set_clear(self.as_ptr()) };
181 util::status_result("AAFieldKeySetClear", status)
182 }
183
184 pub fn contains(&self, key: FieldKey) -> Result<bool> {
186 match unsafe {
187 ffi::aa_field_key::compression_rs_aa_field_key_set_contains_key(
188 self.as_ptr(),
189 key.raw(),
190 )
191 } {
192 value if value < 0 => Err(CompressionError::OperationFailed {
193 operation: "AAFieldKeySetContainsKey",
194 code: value,
195 }),
196 0 => Ok(false),
197 _ => Ok(true),
198 }
199 }
200
201 pub fn insert(&mut self, key: FieldKey) -> Result<()> {
203 let status = unsafe {
204 ffi::aa_field_key::compression_rs_aa_field_key_set_insert_key(self.as_ptr(), key.raw())
205 };
206 util::status_result("AAFieldKeySetInsertKey", status)
207 }
208
209 pub fn remove(&mut self, key: FieldKey) -> Result<()> {
211 let status = unsafe {
212 ffi::aa_field_key::compression_rs_aa_field_key_set_remove_key(self.as_ptr(), key.raw())
213 };
214 util::status_result("AAFieldKeySetRemoveKey", status)
215 }
216
217 pub fn insert_set(&mut self, other: &Self) -> Result<()> {
219 let status = unsafe {
220 ffi::aa_field_key::compression_rs_aa_field_key_set_insert_key_set(
221 self.as_ptr(),
222 other.as_ptr(),
223 )
224 };
225 util::status_result("AAFieldKeySetInsertKeySet", status)
226 }
227
228 pub fn remove_set(&mut self, other: &Self) -> Result<()> {
230 let status = unsafe {
231 ffi::aa_field_key::compression_rs_aa_field_key_set_remove_key_set(
232 self.as_ptr(),
233 other.as_ptr(),
234 )
235 };
236 util::status_result("AAFieldKeySetRemoveKeySet", status)
237 }
238
239 pub fn select_set(&mut self, other: &Self) -> Result<()> {
241 let status = unsafe {
242 ffi::aa_field_key::compression_rs_aa_field_key_set_select_key_set(
243 self.as_ptr(),
244 other.as_ptr(),
245 )
246 };
247 util::status_result("AAFieldKeySetSelectKeySet", status)
248 }
249
250 pub fn len(&self) -> u32 {
252 unsafe { ffi::aa_field_key::compression_rs_aa_field_key_set_get_key_count(self.as_ptr()) }
253 }
254
255 pub fn is_empty(&self) -> bool {
257 self.len() == 0
258 }
259
260 pub fn key(&self, index: u32) -> Result<FieldKey> {
262 if index >= self.len() {
263 return Err(CompressionError::OperationFailed {
264 operation: "AAFieldKeySetGetKey",
265 code: -1,
266 });
267 }
268
269 Ok(FieldKey::from_raw(unsafe {
270 ffi::aa_field_key::compression_rs_aa_field_key_set_get_key(self.as_ptr(), index)
271 }))
272 }
273
274 pub fn serialize(&self) -> Result<String> {
276 let capacity = (self.len() as usize)
277 .saturating_mul(4)
278 .saturating_add(1)
279 .max(1);
280 let mut buffer = vec![0_i8; capacity];
281 let status = unsafe {
282 ffi::aa_field_key::compression_rs_aa_field_key_set_serialize(
283 self.as_ptr(),
284 buffer.len(),
285 buffer.as_mut_ptr(),
286 )
287 };
288 util::status_result("AAFieldKeySetSerialize", status)?;
289
290 let value = unsafe { CStr::from_ptr(buffer.as_ptr()) }
291 .to_str()
292 .map_err(|_| CompressionError::Utf8Error {
293 operation: "AAFieldKeySetSerialize",
294 })?;
295 Ok(value.to_string())
296 }
297}
298
299impl Clone for FieldKeySet {
300 fn clone(&self) -> Self {
301 let handle =
302 unsafe { ffi::aa_field_key::compression_rs_aa_field_key_set_clone(self.as_ptr()) };
303 Self {
304 handle: util::nonnull_handle(handle, "AAFieldKeySetClone")
305 .expect("AAFieldKeySetClone returned null"),
306 }
307 }
308}
309
310impl Drop for FieldKeySet {
311 fn drop(&mut self) {
312 unsafe { ffi::aa_field_key::compression_rs_aa_field_key_set_release(self.as_ptr()) };
313 }
314}