proc_getter/
lib.rs

1#![cfg(target_os = "linux")]
2#![doc(html_playground_url = "https://play.rust-lang.org/")]
3
4//! ## how to use
5//!
6//! The layout of this crate is very like the /proc/ directory layout.
7//!
8//! Each file correspond to a module which contains everything to interoperate with the file.
9//! Majority modules has a function which has the same name as the file.
10//!
11//! However, function reside in process directories is a little different.
12//! They receive an u32 argument to specify the target process, and the function name has a "_of" suffix.
13//!
14//! ```
15//! use proc_getter::cmdline::*;
16//! use proc_getter::pid::cmdline::*;
17//!
18//! fn main() {
19//!     //  /proc/cmdline
20//!     println!("{:?}", cmdline());
21//!     
22//!     //  /proc/1/cmdline
23//!     println!("{:?}", cmdline_of(1));
24//! }
25//! ```
26//!
27//! Everything under proc mod is re-export, so `crate::proc::cmdline` equals to `crate::cmdline`.
28//!
29//! ## Returning value
30//!
31//! The returning value has different type depends on the files.
32//! Some function simply return the content of the file, including ending `\n`.
33//! Some function parse the content and return the wrapping type.
34//!
35//! There are tow possbile cases where return an Err:
36//!
37//! 1. there is a bug because we parse the file content incorrectlly.
38//! 2. the file corresponding to the function is not exist in your computer.
39//!
40//! Otherwise all the function should success in theory,
41//! since files under proc file system are not real file.
42//!
43//! ## which files is supported
44//!
45//! It's very depends on th system.
46//! Here is a list from [red hat], every file in this list should be supported.
47//!
48//![red hat]: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/ch-proc
49
50/// all kind of error may occurs in the crate.
51///
52/// IO often occurs when the file is not exists in your system, it wrap an std::io::Error::NotFound.
53/// others should be consider as an error and should be fix.
54#[derive(Debug)]
55pub enum Error {
56    /// contains a std::io::Error, which should be `NotFound`.
57    IO(std::io::Error),
58    /// this error should appear.
59    /// Otherwise it's a situation where unexpected input appears.
60    /// That is a bug.default_read!
61    BadFormat,
62    ParseInt(std::num::ParseIntError),
63    ParseFloat(std::num::ParseFloatError),
64    ParseAddr(std::net::AddrParseError),
65}
66
67impl From<std::net::AddrParseError> for Error {
68    fn from(err: std::net::AddrParseError) -> Self {
69        Error::ParseAddr(err)
70    }
71}
72
73impl From<std::io::Error> for Error {
74    fn from(err: std::io::Error) -> Self {
75        Error::IO(err)
76    }
77}
78
79impl From<std::num::ParseIntError> for Error {
80    fn from(err: std::num::ParseIntError) -> Self {
81        Error::ParseInt(err)
82    }
83}
84
85impl From<std::num::ParseFloatError> for Error {
86    fn from(err: std::num::ParseFloatError) -> Self {
87        Error::ParseFloat(err)
88    }
89}
90
91type Result<T> = std::result::Result<T, Error>;
92
93macro_rules! default_read {
94    ($fn_name: ident, $path: expr) => {
95        /// Read the whole file content and return it.
96        /// Ending line break is included.
97        pub fn $fn_name() -> $crate::Result<String> {
98            Ok(std::fs::read_to_string($path)?)
99        }
100    };
101}
102
103macro_rules! default_list {
104    ($fn_name: ident, $path: expr, $return_type: ty, $parse_code: ident, $sep: expr, $skip: expr) => {
105        pub fn $fn_name() -> $crate::Result<Vec<$return_type>> {
106            let content = std::fs::read_to_string($path)?;
107            let mut ret = vec![];
108            let mut block_iter = content.trim().split($sep);
109            for _ in 0..$skip {
110                let _ = block_iter.next();
111            }
112            for block in block_iter {
113                ret.push($parse_code(block)?);
114            }
115            Ok(ret)
116        }
117    };
118    ($fn_name: ident, $path: expr, $return_type: ty, $parse_code: ident, $sep: expr) => {
119        default_list! {$fn_name, $path, $return_type, $parse_code, $sep, 0}
120    };
121    ($fn_name: ident, $path: expr, $return_type: ty, $parse_code: ident) => {
122        default_list! {$fn_name, $path, $return_type, $parse_code, '\n', 0}
123    };
124}
125
126macro_rules! getter_gen {
127    (
128        $(
129            $filed: ident : $type: ty
130        ), *
131    ) => {
132        $(
133            #[inline(always)]
134            pub fn $filed(&self) -> &$type {
135                &self.$filed
136            }
137        ) *
138    };
139}
140
141pub mod proc;
142#[doc(inline)]
143pub use proc::*;