#![deny(unsafe_code)]
use super::rlim_type::Rlim;
use std::error::Error;
use std::fmt;
use std::io;
use std::str::FromStr;
#[cfg(all(target_os = "linux", target_env = "gnu"))]
use libc::__rlimit_resource_t as resource_t;
#[cfg(not(all(target_os = "linux", target_env = "gnu")))]
use libc::c_int as resource_t;
pub type RawResource = resource_t;
#[allow(clippy::doc_markdown)]
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct Resource {
tag: u16,
value: u16,
}
impl fmt::Debug for Resource {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let idx = Self::VALUE_TABLE.iter().position(|v| v == self).unwrap();
write!(f, "Resource::{}", Self::IDENT_TABLE[idx])
}
}
impl FromStr for Resource {
type Err = ParseResourceError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let pos = Self::NAME_TABLE.iter().position(|&name| s == name);
match pos {
Some(idx) => Ok(Self::VALUE_TABLE[idx]),
None => Err(ParseResourceError { _priv: () }),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParseResourceError {
_priv: (),
}
impl fmt::Display for ParseResourceError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "failed to parse Resource")
}
}
impl Error for ParseResourceError {}
macro_rules! declare_resource {
{$($(#[$attr:meta])* $id:ident = $tag:expr => $c_enum:ident,)+} => {
impl Resource{
$(
$(#[$attr])*
pub const $id: Self = Self{ tag: $tag, value: libc::$c_enum as u16 };
)+
}
#[allow(unused_doc_comments)]
impl Resource{
const NAME_TABLE: &'static [&'static str] = &[
$(
$(#[$attr])*
{
stringify!($c_enum)
},
)+
];
const VALUE_TABLE: &'static [Self] = &[
$(
$(#[$attr])*
{
Self::$id
},
)+
];
const IDENT_TABLE: &'static [&'static str] = &[
$(
$(#[$attr])*
{
stringify!($id)
},
)+
];
}
#[cfg(test)]
mod tests{
use super::*;
#[allow(unused_comparisons)]
#[allow(unused_doc_comments)]
#[test]
fn name_value(){
$(
$(#[$attr])*
{
assert_eq!(Resource::$id.as_name(), stringify!($c_enum));
assert_eq!(Resource::from_str(stringify!($c_enum)).unwrap(), Resource::$id);
assert!(libc::$c_enum >= 0 && libc::$c_enum <= 128);
}
)+
}
#[allow(unused_doc_comments)]
#[test]
fn unique_tag(){
use std::collections::HashSet;
let tags = [
$(
$(#[$attr])*
{ $tag },
)+
];
let s: HashSet<u16> = tags.iter().copied().collect();
assert_eq!(s.len(), Resource::NAME_TABLE.len());
}
#[allow(unused_doc_comments)]
#[test]
fn raw_eq(){
$(
$(#[$attr])*
{
assert_eq!(Resource::$id.as_raw(), libc::$c_enum);
}
)+
}
#[allow(unused_doc_comments)]
#[test]
fn from_str(){
$(
$(#[$attr])*
{
assert_eq!(Resource::from_str(stringify!($c_enum)), Ok(Resource::$id));
}
)+
assert!(Resource::from_str("asdqwe").is_err());
}
#[test]
fn available(){
assert_eq!(
Resource::available_names().len(),
Resource::available_resources().len()
);
}
}
};
}
declare_resource! {
#[cfg(any(
target_os = "fuchsia",
any(target_os = "macos", target_os = "ios"),
any(target_os = "freebsd", target_os = "dragonfly"),
target_os = "haiku",
target_os = "android",
target_os = "emscripten",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl", any(target_arch = "x86", target_arch = "mips", target_arch = "powerpc", target_arch = "hexagon", target_arch = "arm")),
all(target_os = "linux", target_env = "musl", any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "mips64", target_arch = "powerpc64")),
target_os = "solarish",
all(target_env = "uclibc",any(target_arch = "mips", target_arch = "mips64"))
))]
AS = 1 => RLIMIT_AS,
#[cfg(any(
target_os = "fuchsia",
any(target_os = "macos", target_os = "ios"),
any(target_os = "freebsd", target_os = "dragonfly"),
any(target_os = "openbsd", target_os = "netbsd"),
target_os = "haiku",
target_os = "android",
target_os = "emscripten",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl"),
target_os = "solarish",
target_env = "uclibc"
))]
CORE = 2 => RLIMIT_CORE,
#[cfg(any(
target_os = "fuchsia",
any(target_os = "macos", target_os = "ios"),
any(target_os = "freebsd", target_os = "dragonfly"),
any(target_os = "openbsd", target_os = "netbsd"),
target_os = "haiku",
target_os = "android",
target_os = "emscripten",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl"),
target_os = "solarish",
target_env = "uclibc"
))]
CPU = 3 => RLIMIT_CPU,
#[cfg(any(
target_os = "fuchsia",
any(target_os = "macos", target_os = "ios"),
any(target_os = "freebsd", target_os = "dragonfly"),
any(target_os = "openbsd", target_os = "netbsd"),
target_os = "haiku",
target_os = "android",
target_os = "emscripten",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl"),
target_os = "solarish",
target_env = "uclibc"
))]
DATA = 4 => RLIMIT_DATA,
#[cfg(any(
target_os = "fuchsia",
any(target_os = "macos", target_os = "ios"),
any(target_os = "freebsd", target_os = "dragonfly"),
any(target_os = "openbsd", target_os = "netbsd"),
target_os = "haiku",
target_os = "android",
target_os = "emscripten",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl"),
target_os = "solarish",
target_env = "uclibc"
))]
FSIZE = 5 => RLIMIT_FSIZE,
#[cfg(any(
target_os = "freebsd"
))]
KQUEUES = 6 => RLIMIT_KQUEUES,
#[cfg(any(
target_os = "fuchsia",
target_os = "android",
target_os = "emscripten",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl"),
target_env = "uclibc"
))]
LOCKS = 7 => RLIMIT_LOCKS,
#[cfg(any(
target_os = "fuchsia",
any(target_os = "macos", target_os = "ios"),
any(target_os = "freebsd", target_os = "dragonfly"),
any(target_os = "openbsd", target_os = "netbsd"),
target_os = "android",
target_os = "emscripten",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl", any(target_arch = "x86", target_arch = "mips", target_arch = "powerpc", target_arch = "hexagon", target_arch = "arm")),
all(target_os = "linux", target_env = "musl", any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "mips64", target_arch = "powerpc64")),
all(target_env = "uclibc",any(target_arch = "mips", target_arch = "mips64"))
))]
MEMLOCK = 8 => RLIMIT_MEMLOCK,
#[cfg(any(
target_os = "fuchsia",
target_os = "android",
target_os = "emscripten",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl"),
target_env = "uclibc"
))]
MSGQUEUE = 9 => RLIMIT_MSGQUEUE,
#[cfg(any(
target_os = "fuchsia",
target_os = "android",
target_os = "emscripten",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl"),
target_env = "uclibc"
))]
NICE = 10 => RLIMIT_NICE,
#[cfg(any(
target_os = "fuchsia",
any(target_os = "macos", target_os = "ios"),
any(target_os = "freebsd", target_os = "dragonfly"),
any(target_os = "openbsd", target_os = "netbsd"),
target_os = "haiku",
target_os = "android",
target_os = "emscripten",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl", any(target_arch = "x86", target_arch = "mips", target_arch = "powerpc", target_arch = "hexagon", target_arch = "arm")),
all(target_os = "linux", target_env = "musl", any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "mips64", target_arch = "powerpc64")),
target_os = "solarish",
all(target_env = "uclibc",any(target_arch = "mips", target_arch = "mips64"))
))]
NOFILE = 11 => RLIMIT_NOFILE,
#[cfg(any(
target_os = "haiku"
))]
NOVMON = 12 => RLIMIT_NOVMON,
#[cfg(any(
target_os = "fuchsia",
any(target_os = "macos", target_os = "ios"),
any(target_os = "freebsd", target_os = "dragonfly"),
any(target_os = "openbsd", target_os = "netbsd"),
target_os = "android",
target_os = "emscripten",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl", any(target_arch = "x86", target_arch = "mips", target_arch = "powerpc", target_arch = "hexagon", target_arch = "arm")),
all(target_os = "linux", target_env = "musl", any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "mips64", target_arch = "powerpc64")),
all(target_env = "uclibc",any(target_arch = "mips", target_arch = "mips64"))
))]
NPROC = 13 => RLIMIT_NPROC,
#[cfg(any(
target_os = "freebsd"
))]
NPTS = 14 => RLIMIT_NPTS,
#[cfg(any(
target_os = "dragonfly"
))]
POSIXLOCKS = 15 => RLIMIT_POSIXLOCKS,
#[cfg(any(
target_os = "fuchsia",
any(target_os = "macos", target_os = "ios"),
any(target_os = "freebsd", target_os = "dragonfly"),
any(target_os = "openbsd", target_os = "netbsd"),
target_os = "android",
target_os = "emscripten",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl", any(target_arch = "x86", target_arch = "mips", target_arch = "powerpc", target_arch = "hexagon", target_arch = "arm")),
all(target_os = "linux", target_env = "musl", any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "mips64", target_arch = "powerpc64")),
all(target_env = "uclibc",any(target_arch = "mips", target_arch = "mips64"))
))]
RSS = 16 => RLIMIT_RSS,
#[cfg(any(
target_os = "fuchsia",
target_os = "android",
target_os = "emscripten",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl"),
target_env = "uclibc"
))]
RTPRIO = 17 => RLIMIT_RTPRIO,
#[cfg(any(
target_os = "fuchsia",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl")
))]
RTTIME = 18 => RLIMIT_RTTIME,
#[cfg(any(
any(target_os = "freebsd", target_os = "dragonfly")
))]
SBSIZE = 19 => RLIMIT_SBSIZE,
#[cfg(any(
target_os = "fuchsia",
target_os = "android",
target_os = "emscripten",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl"),
target_env = "uclibc"
))]
SIGPENDING = 20 => RLIMIT_SIGPENDING,
#[cfg(any(
target_os = "fuchsia",
any(target_os = "macos", target_os = "ios"),
any(target_os = "freebsd", target_os = "dragonfly"),
any(target_os = "openbsd", target_os = "netbsd"),
target_os = "haiku",
target_os = "android",
target_os = "emscripten",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl"),
target_os = "solarish",
target_env = "uclibc"
))]
STACK = 21 => RLIMIT_STACK,
#[cfg(any(
target_os = "freebsd"
))]
SWAP = 22 => RLIMIT_SWAP,
#[cfg(any(
target_os = "freebsd"
))]
UMTXP = 23 => RLIMIT_UMTXP,
#[cfg(any(
any(target_os = "freebsd", target_os = "dragonfly"),
target_os = "solarish"
))]
VMEM = 24 => RLIMIT_VMEM,
}
impl Resource {
#[inline]
pub fn set(self, soft: Rlim, hard: Rlim) -> io::Result<()> {
super::setrlimit(self, soft, hard)
}
#[inline]
pub fn get(self) -> io::Result<(Rlim, Rlim)> {
super::getrlimit(self)
}
#[must_use]
pub fn as_name(self) -> &'static str {
let idx = Self::VALUE_TABLE.iter().position(|&v| v == self).unwrap();
Self::NAME_TABLE[idx]
}
#[must_use]
pub const fn available_names() -> &'static [&'static str] {
Self::NAME_TABLE
}
#[must_use]
pub const fn available_resources() -> &'static [Self] {
Self::VALUE_TABLE
}
#[inline]
#[must_use]
pub const fn as_raw(self) -> RawResource {
self.value as _
}
}