nextcloud_users/user/quota.rs
1use serde::{Deserialize, Serialize};
2
3use crate::wire::{lossy_f64, lossy_i64};
4
5/// User storage quota metrics and capacity constraints.
6///
7/// In Nextcloud, when a quota is set to unlimited, negative integer codes
8/// (typically `-3` or `-2`) are returned for `free` and `total`.
9///
10/// Official documentation:
11/// <https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-api-overview.html#user-metadata>
12#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
13pub struct Quota {
14 /// Space remaining in bytes, or negative code when unlimited.
15 #[serde(default, deserialize_with = "lossy_i64")]
16 pub free: i64,
17 /// Space consumed by user files in bytes.
18 #[serde(default, deserialize_with = "lossy_i64")]
19 pub used: i64,
20 /// Total storage capacity allocated in bytes, or negative code when unlimited.
21 #[serde(default, deserialize_with = "lossy_i64")]
22 pub total: i64,
23 /// Storage usage ratio or percentage (e.g. `0.96` or `96.0`).
24 #[serde(default, deserialize_with = "lossy_f64")]
25 pub relative: f64,
26}
27
28impl Quota {
29 /// Creates a quota descriptor with explicit byte measurements.
30 pub const fn new(free: i64, used: i64, total: i64, relative: f64) -> Self {
31 Self {
32 free,
33 used,
34 total,
35 relative,
36 }
37 }
38
39 /// Available free space in bytes, or a negative status code when unlimited.
40 pub const fn free(&self) -> i64 {
41 self.free
42 }
43
44 /// Bytes consumed by user files.
45 pub const fn used(&self) -> i64 {
46 self.used
47 }
48
49 /// Total storage allocation in bytes, or a negative status code when unlimited.
50 pub const fn total(&self) -> i64 {
51 self.total
52 }
53
54 /// Relative storage utilization metric.
55 pub const fn relative(&self) -> f64 {
56 self.relative
57 }
58
59 /// Whether the user has an unlimited storage allocation.
60 pub const fn is_unlimited(&self) -> bool {
61 self.total < 0
62 }
63
64 /// Available free storage in bytes, or `None` if quota is unlimited.
65 pub fn free_bytes(&self) -> Option<u64> {
66 if self.free >= 0 {
67 Some(self.free as u64)
68 } else {
69 None
70 }
71 }
72
73 /// Total allocated storage capacity in bytes, or `None` if quota is unlimited.
74 pub fn total_bytes(&self) -> Option<u64> {
75 if self.total >= 0 {
76 Some(self.total as u64)
77 } else {
78 None
79 }
80 }
81
82 /// Bytes currently consumed by user files.
83 pub fn used_bytes(&self) -> u64 {
84 self.used.max(0) as u64
85 }
86
87 /// Percentage of storage utilized (0.0 to 100.0).
88 pub fn relative_percentage(&self) -> f64 {
89 if self.relative > 0.0 && self.relative <= 1.0 {
90 self.relative * 100.0
91 } else {
92 self.relative
93 }
94 }
95}