feat: fixed delimiter differences between overlay and fuse-overlay

This commit is contained in:
Rowan 2025-03-05 19:05:36 -06:00
parent 7b8f351b21
commit 489cbcc824
4 changed files with 33 additions and 136 deletions

View file

@ -379,6 +379,26 @@ impl From<UntypedIdRange> for GidRange {
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct DelimitedList<const D: char, T>(Vec<T>);
impl<const D: char, T> Deref for DelimitedList<D, T> {
type Target = Vec<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<const D: char, T> Default for DelimitedList<D, T> {
fn default() -> Self {
Self(Default::default())
}
}
impl<const D: char, T> DerefMut for DelimitedList<D, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<const D: char, T: FromStr> FromStr for DelimitedList<D, T> {
type Err = T::Err;
@ -431,129 +451,6 @@ impl<const D: char, T: Display> Display for DelimitedList<D, T> {
}
}
#[derive(Debug)]
pub struct Options<T> {
options: Vec<T>,
delimiter: char,
}
impl<T> Options<T> {
pub fn new(options: Vec<T>, delimiter: char) -> Self {
Self { options, delimiter }
}
}
impl<T> Deref for Options<T> {
type Target = Vec<T>;
fn deref(&self) -> &Self::Target {
&self.options
}
}
impl<T> DerefMut for Options<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.options
}
}
impl<T> Default for Options<T> {
fn default() -> Self {
Self {
options: Default::default(),
delimiter: ' ',
}
}
}
impl<T> AsRef<Vec<T>> for Options<T> {
fn as_ref(&self) -> &Vec<T> {
&self.options
}
}
impl<T: Clone> Clone for Options<T> {
fn clone(&self) -> Self {
Self {
options: self.options.clone(),
delimiter: self.delimiter,
}
}
}
impl<T: PartialEq> PartialEq for Options<T> {
fn eq(&self, other: &Self) -> bool {
self.options.eq(&other.options) && self.delimiter.eq(&other.delimiter)
}
}
impl<T: Eq> Eq for Options<T> {}
impl<T: FromStr> FromStr for Options<T> {
type Err = T::Err;
fn from_str(s: &str) -> Result<Self, Self::Err> {
s.split(',')
.map(T::from_str)
.process_results(|iter| Options::from(iter.collect::<Vec<_>>()))
}
}
impl<T: Display> Display for Options<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut iter = self.options.iter();
if let Some(head) = iter.next() {
write!(f, "{head}")?;
for item in iter {
write!(f, "{}{item}", self.delimiter)?;
}
}
Ok(())
}
}
impl<T> FromIterator<T> for Options<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
Self {
options: iter.into_iter().collect(),
..Default::default()
}
}
}
impl<T> IntoIterator for Options<T> {
type Item = T;
type IntoIter = IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
self.options.into_iter()
}
}
impl<'a, T> IntoIterator for &'a Options<T> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.options.as_slice().iter()
}
}
impl<T> From<Vec<T>> for Options<T> {
fn from(value: Vec<T>) -> Self {
Self::from_iter(value)
}
}
impl<T> From<T> for Options<T> {
fn from(value: T) -> Self {
Self::from_iter([value])
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Sources(DelimitedList<',', OptionsSource>);
@ -1015,8 +912,8 @@ mod tests {
};
use super::{
Access, DeviceId, KeyValuePair, MapUsers, MountOperation, MountOption, Options,
OptionsMode, OptionsSource, ParseMountOptionError, Subtree, UncheckedOptions,
Access, DeviceId, KeyValuePair, MapUsers, MountOperation, MountOption, OptionsMode,
OptionsSource, ParseMountOptionError, Subtree, UncheckedOptions,
};
#[test]

View file

@ -272,10 +272,10 @@ impl Display for FuseOverlayOption {
}
#[derive(Debug)]
pub struct FuseOverlay(StackFs<FuseOverlayOption>);
pub struct FuseOverlay(StackFs<' ', FuseOverlayOption>);
impl_deref!(FuseOverlay(StackFs<FuseOverlayOption>));
impl_deref_mut!(FuseOverlay(StackFs<FuseOverlayOption>));
impl_deref!(FuseOverlay(StackFs<' ', FuseOverlayOption>));
impl_deref_mut!(FuseOverlay(StackFs<' ', FuseOverlayOption>));
impl FuseOverlay {
pub fn new(target: impl Into<PathBuf>) -> Self {

View file

@ -9,7 +9,7 @@ use std::str::FromStr;
use crate::macros::impl_deref;
use super::mount::Options;
use super::mount::DelimitedList;
use super::Mountpoint;
#[derive(Clone, Debug, Default)]
@ -76,12 +76,12 @@ impl FromStr for LowerDirs {
}
#[derive(Debug)]
pub struct StackFs<T> {
pub struct StackFs<const D: char, T> {
mountpoint: PathBuf,
options: Options<T>,
options: DelimitedList<D, T>,
}
impl<T> StackFs<T> {
impl<const D: char, T> StackFs<D, T> {
pub fn new(target: impl Into<PathBuf>) -> Self {
Self {
mountpoint: target.into(),
@ -105,7 +105,7 @@ impl<T> StackFs<T> {
}
}
impl<T: Display> Mountpoint for StackFs<T> {
impl<const D: char, T: Display> Mountpoint for StackFs<D, T> {
fn options(&self) -> impl Iterator<Item = impl Display> {
self.options.iter()
}

View file

@ -247,10 +247,10 @@ impl Display for OverlayOption {
}
#[derive(Debug)]
pub struct Overlay(StackFs<OverlayOption>);
pub struct Overlay(StackFs<',', OverlayOption>);
impl_deref!(Overlay(StackFs<OverlayOption>));
impl_deref_mut!(Overlay(StackFs<OverlayOption>));
impl_deref!(Overlay(StackFs<',', OverlayOption>));
impl_deref_mut!(Overlay(StackFs<',', OverlayOption>));
impl Stack for Overlay {
fn lower_dirs(&self) -> impl Iterator<Item = &std::path::Path> {