mirror of
https://git.proxmox.com/git/proxmox
synced 2025-07-06 08:58:35 +00:00
add Uuid replacement
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
db83a675f0
commit
b53b621cd8
@ -9,8 +9,12 @@ pub mod fd;
|
||||
pub mod fs;
|
||||
pub mod io;
|
||||
pub mod serde;
|
||||
pub mod uuid;
|
||||
pub mod vec;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use uuid::Uuid;
|
||||
|
||||
/// Evaluates to the offset (in bytes) of a given member within a struct
|
||||
#[macro_export]
|
||||
macro_rules! offsetof {
|
||||
|
160
proxmox-tools/src/uuid.rs
Normal file
160
proxmox-tools/src/uuid.rs
Normal file
@ -0,0 +1,160 @@
|
||||
//! Simple bindings to libuuid's `uuid_generate`.
|
||||
|
||||
use std::borrow::{Borrow, BorrowMut};
|
||||
use std::fmt;
|
||||
use std::os::raw::c_int;
|
||||
|
||||
use failure::{bail, Error};
|
||||
|
||||
#[link(name = "uuid")]
|
||||
extern "C" {
|
||||
fn uuid_generate(out: *mut [u8; 16]);
|
||||
fn uuid_unparse_lower(input: *const [u8; 16], out: *mut u8);
|
||||
fn uuid_unparse_upper(input: *const [u8; 16], out: *mut u8);
|
||||
fn uuid_parse(input: *const u8, out: *mut [u8; 16]) -> c_int;
|
||||
}
|
||||
|
||||
/// Uuid generated with the system's native libuuid.
|
||||
///
|
||||
/// ```
|
||||
/// use proxmox_tools::uuid::Uuid;
|
||||
///
|
||||
/// let uuid = Uuid::generate();
|
||||
/// println!("Generated uuid: {}", uuid);
|
||||
/// // prints somethign like:
|
||||
/// // Generated uuid: d79191c-724-415f-a1bf-2256b8ea76e
|
||||
///
|
||||
/// let bytes: &[u8] = uuid.as_ref();
|
||||
/// println!("raw byte string: {:?}", bytes);
|
||||
/// // raw byte string: [215, 9, 25, 28, 114, 4, 65, 95, 161, 191, 34, 86, 184, 234, 118, 14]
|
||||
///
|
||||
/// let text = format!("{}", uuid);
|
||||
/// let parsed: Uuid = text.parse().unwrap();
|
||||
/// assert_eq!(uuid, parsed);
|
||||
/// ```
|
||||
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
pub struct Uuid(Box<[u8; 16]>);
|
||||
|
||||
impl Uuid {
|
||||
/// Generate a uuid with `uuid_generate(3)`.
|
||||
pub fn generate() -> Self {
|
||||
use std::alloc::{alloc, Layout};
|
||||
let uuid = unsafe { alloc(Layout::new::<[u8; 16]>()) as *mut [u8; 16] };
|
||||
unsafe { uuid_generate(uuid) };
|
||||
Self(unsafe { Box::from_raw(uuid) })
|
||||
}
|
||||
|
||||
/// Get a reference to the internal 16 byte array.
|
||||
pub fn as_bytes(&self) -> &[u8; 16] {
|
||||
&*self.0
|
||||
}
|
||||
|
||||
/// Take out the inner boxed 16 byte array.
|
||||
pub fn into_inner(self) -> Box<[u8; 16]> {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Parse a uuid in optionally-hyphenated format.
|
||||
///
|
||||
/// ```
|
||||
/// use proxmox_tools::uuid::Uuid;
|
||||
///
|
||||
/// let gen = Uuid::generate();
|
||||
/// let text = format!("{}", gen);
|
||||
/// let parsed: Uuid = text.parse().unwrap();
|
||||
/// assert_eq!(gen, parsed);
|
||||
/// ```
|
||||
pub fn parse_str(src: &str) -> Result<Self, Error> {
|
||||
use std::alloc::{alloc, Layout};
|
||||
let uuid = unsafe { alloc(Layout::new::<[u8; 16]>()) as *mut [u8; 16] };
|
||||
let rc = unsafe { uuid_parse(src.as_bytes().as_ptr(), uuid) };
|
||||
if rc != 0 {
|
||||
bail!("failed to parse uuid");
|
||||
}
|
||||
Ok(Self(unsafe { Box::from_raw(uuid) }))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for Uuid {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.as_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsMut<[u8]> for Uuid {
|
||||
#[inline]
|
||||
fn as_mut(&mut self) -> &mut [u8] {
|
||||
&mut (self.0)[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl Borrow<[u8]> for Uuid {
|
||||
#[inline]
|
||||
fn borrow(&self) -> &[u8] {
|
||||
&(self.0)[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl BorrowMut<[u8]> for Uuid {
|
||||
#[inline]
|
||||
fn borrow_mut(&mut self) -> &mut [u8] {
|
||||
&mut (self.0)[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; 16]> for Uuid {
|
||||
fn from(data: [u8; 16]) -> Self {
|
||||
Self(Box::new(data))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Box<[u8; 16]>> for Uuid {
|
||||
fn from(data: Box<[u8; 16]>) -> Self {
|
||||
Self(data)
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<[u8; 16]> for Uuid {
|
||||
fn into(self) -> [u8; 16] {
|
||||
*self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Uuid {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::LowerHex::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::LowerHex for Uuid {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let mut buf = [0u8; 37];
|
||||
unsafe {
|
||||
uuid_unparse_lower(self.as_bytes(), buf.as_mut_ptr());
|
||||
}
|
||||
write!(f, "{}", unsafe {
|
||||
std::str::from_utf8_unchecked(&buf[..36])
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::UpperHex for Uuid {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let mut buf = [0u8; 37];
|
||||
unsafe {
|
||||
uuid_unparse_upper(self.as_bytes(), buf.as_mut_ptr());
|
||||
}
|
||||
write!(f, "{}", unsafe {
|
||||
std::str::from_utf8_unchecked(&buf[..36])
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for Uuid {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(src: &str) -> Result<Self, Error> {
|
||||
Self::parse_str(src)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user