use crate::dev::Dev;
use blkid_sys::*;
use std::{ffi::CStr, ptr, str::FromStr};
use strum_macros::{Display, EnumString};
pub struct Tags {
pub(crate) iter: blkid_tag_iterate,
}
impl Tags {
pub fn new(dev: &Dev) -> Tags {
let iter = unsafe { blkid_tag_iterate_begin(dev.0) };
assert_ne!(iter, ptr::null_mut());
Tags { iter }
}
}
impl Drop for Tags {
fn drop(&mut self) {
unsafe { blkid_tag_iterate_end(self.iter) }
}
}
impl Iterator for Tags {
type Item = Tag;
fn next(&mut self) -> Option<Self::Item> {
let mut k = ptr::null();
let mut v = ptr::null();
unsafe {
match blkid_tag_next(self.iter, &mut k, &mut v) {
0 => {
let name = TagType::from(CStr::from_ptr(k).to_string_lossy().as_ref());
let value = CStr::from_ptr(v).to_string_lossy().to_string();
Some(Tag { name, value })
}
_ => None,
}
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Tag {
name: TagType,
value: String,
}
impl Tag {
pub fn new(name: impl Into<TagType>, value: &str) -> Self {
Self {
name: name.into(),
value: value.to_owned(),
}
}
pub fn typ(&self) -> TagType {
self.name.clone()
}
pub fn name(&self) -> String {
self.name.to_string()
}
pub fn value(&self) -> &str {
&self.value
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum TagType {
Superblock(SuperblockTag),
Partition(PartitionTag),
Topoligy(TopologyTag),
Unknown(String),
}
impl std::fmt::Display for TagType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let name = match &self {
Self::Superblock(tag) => tag.to_string(),
Self::Partition(tag) => tag.to_string(),
Self::Topoligy(tag) => tag.to_string(),
Self::Unknown(tag) => tag.clone(),
};
write!(f, "{}", name)
}
}
impl From<&str> for TagType {
fn from(name: &str) -> Self {
if let Ok(tag) = SuperblockTag::from_str(name) {
TagType::Superblock(tag)
} else if let Ok(tag) = PartitionTag::from_str(name) {
TagType::Partition(tag)
} else if let Ok(tag) = TopologyTag::from_str(name) {
TagType::Topoligy(tag)
} else {
TagType::Unknown(name.to_owned())
}
}
}
#[derive(Clone, Debug, Display, Eq, PartialEq, EnumString)]
#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
pub enum SuperblockTag {
Type,
SecType,
Label,
LabelRaw,
Uuid,
UuidSub,
Loguuid,
UuidRaw,
ExtJournal,
Usage,
Version,
Mount,
Sbmagic,
SbmagicOffset,
Fssize,
SystemId,
PublisherId,
ApplicationId,
BootSystemId,
BlockSize,
}
impl From<SuperblockTag> for TagType {
fn from(tag: SuperblockTag) -> Self {
Self::Superblock(tag)
}
}
#[derive(Clone, Debug, Display, Eq, PartialEq, EnumString)]
#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
pub enum PartitionTag {
Pttype,
Ptuuid,
PartEntrySchema,
PartEntryName,
PartEntryUuid,
PartEntryType,
PartEntryFlags,
PartEntryNumber,
PartEntryOffset,
PartEntrySize,
PartEntryDisk,
}
impl From<PartitionTag> for TagType {
fn from(tag: PartitionTag) -> Self {
Self::Partition(tag)
}
}
#[derive(Clone, Debug, Display, Eq, PartialEq, EnumString)]
#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
pub enum TopologyTag {
LogicalSectorSize,
PhysicalSectorSize,
MinimumIoSize,
OptiomalIoSize,
AlignmentOffset,
}
impl From<TopologyTag> for TagType {
fn from(tag: TopologyTag) -> Self {
Self::Topoligy(tag)
}
}