[−][src]Struct hrx::HrxArchive
A Human-Readable Archive, consisting of an optional comment and some entries, all separated by the boundary.
The archive boundary consists of a particular-length sequence of =
s bounded with <
and >
on either side;
that sequence must be consistent across the entirety of the archive, which means that no body
(be it a comment or file contents) can contain a newline followed by the boundary.
However, there is no way to enforce that on the typesystem level, meaning that the entries and comments can be modified at will, so instead the archive will automatically check for boundary validity when
- changing the global boundary length (via
set_boundary_length()
) and - serialising to an output stream (usually via
serialise()
)
and return the paths to the erroneous (i.e. boundary-containing) body
s.
Fields
comment: Option<String>
Some optional metadata.
Cannot contain a newline followed by a boundary.
entries: LinkedHashMap<HrxPath, HrxEntry>
Some optional archive entries with their paths.
Methods
impl HrxArchive
[src]
pub fn new(boundary_length: NonZeroUsize) -> HrxArchive
[src]
Create an empty archive with the specified boundary length.
pub fn boundary_length(&self) -> NonZeroUsize
[src]
Get the current boundary length, i.e. the amount of =
characters in the boundary.
Examples
let arch_str = r#"<===> input.scss ul { margin-left: 1em; li { list-style-type: none; } } <===> output.css ul { margin-left: 1em; } ul li { list-style-type: none; }"#; let arch = HrxArchive::from_str(arch_str).unwrap(); assert_eq!(arch.boundary_length().get(), 3);
pub fn set_boundary_length(
&mut self,
new_len: NonZeroUsize
) -> Result<(), HrxError>
[src]
&mut self,
new_len: NonZeroUsize
) -> Result<(), HrxError>
Set new boundary length, if valid.
Checks, whether any body
s within the archive contain the new boundary;
if so – errors out with their paths,
otherwise sets the boundary length to the specified value.
Examples
let arch_str = r#"<===> boundary-5.txt This file contains a 5-length boundary: <=====> ^ right there <===> This is a comment, <=======> which contains a 7-length boundary. <===> fine.txt This file consists of multiple lines, but none of them starts with any sort of boundary-like string"#; let mut arch = HrxArchive::from_str(arch_str).unwrap(); assert_eq!(arch.boundary_length().get(), 3); assert_eq!(arch.set_boundary_length(NonZeroUsize::new(4).unwrap()), Ok(())); assert_eq!(arch.boundary_length().get(), 4); assert_eq!(arch.set_boundary_length(NonZeroUsize::new(5).unwrap()), Err(ErroneousBodyPath::EntryData("boundary-5.txt".to_string()).into())); assert_eq!(arch.boundary_length().get(), 4); assert_eq!(arch.set_boundary_length(NonZeroUsize::new(6).unwrap()), Ok(())); assert_eq!(arch.boundary_length().get(), 6); assert_eq!(arch.set_boundary_length(NonZeroUsize::new(7).unwrap()), Err(ErroneousBodyPath::EntryComment("fine.txt".to_string()).into())); assert_eq!(arch.boundary_length().get(), 6); assert_eq!(arch.set_boundary_length(NonZeroUsize::new(8).unwrap()), Ok(())); assert_eq!(arch.boundary_length().get(), 8);
pub fn validate_content(&self) -> Result<(), HrxError>
[src]
Validate that no body
s contain a boundary
or error out with the paths to the ones that do,
Examples
let mut arch = HrxArchive::new(NonZeroUsize::new(3).unwrap()); arch.comment = Some("Yeehaw! the comment\n<===>\n contains the boundary!".to_string()); arch.entries.insert("directory/dsc.txt".parse().unwrap(), HrxEntry { comment: None, data: HrxEntryData::File { body: Some("As does this file\n<===>, whew!".to_string()), }, }); assert_eq!(arch.validate_content(), Err(vec![ErroneousBodyPath::RootComment, ErroneousBodyPath::EntryData("directory/dsc.txt".to_string())].into()));
pub fn serialise<W: Write>(
&self,
into: &mut W
) -> Result<(), Result<HrxError, IoError>>
[src]
&self,
into: &mut W
) -> Result<(), Result<HrxError, IoError>>
Write the archive out to the specified output stream, after verification.
The compound result type is due to the fact that std::io::Error
doesn't play well with having it in an enum variant.
Examples
Failed validation:
let mut arch = HrxArchive::new(NonZeroUsize::new(3).unwrap()); arch.comment = Some("Yeehaw! the comment\n<===>\n contains the boundary!".to_string()); let mut out = vec![]; assert_eq!(arch.serialise(&mut out).unwrap_err().unwrap(), ErroneousBodyPath::RootComment.into()); // Note how the returned result cannot be directly compared to, // as a byproduct of `std::io::Error` being contained therein.
Generation:
let mut arch = HrxArchive::new(NonZeroUsize::new(5).unwrap()); arch.comment = Some("This is the archive comment, forthlaying its contents' description".to_string()); arch.entries.insert("directory".parse().unwrap(), HrxEntry { comment: Some("This directory contains files!".to_string()), data: HrxEntryData::Directory, }); arch.entries.insert("directory/dsc.txt".parse().unwrap(), HrxEntry { comment: Some("This file forthlays the building blocks of any stable society".to_string()), data: HrxEntryData::File { body: Some("Коммунизм!\n".to_string()), }, }); let mut out = vec![]; arch.serialise(&mut out).unwrap(); assert_eq!(String::from_utf8(out).unwrap(), r#"<=====> This directory contains files! <=====> directory/ <=====> This file forthlays the building blocks of any stable society <=====> directory/dsc.txt Коммунизм! <=====> This is the archive comment, forthlaying its contents' description"#);
Transserialisation:
let arch_str = r#"<===> input.scss ul { margin-left: 1em; li { list-style-type: none; } } <===> output.css ul { margin-left: 1em; } ul li { list-style-type: none; }"#; let arch = HrxArchive::from_str(arch_str).unwrap(); let mut out = vec![]; arch.serialise(&mut out).unwrap(); assert_eq!(String::from_utf8(out).unwrap(), arch_str);
Trait Implementations
impl Clone for HrxArchive
[src]
fn clone(&self) -> HrxArchive
[src]
fn clone_from(&mut self, source: &Self)
1.0.0[src]
impl Debug for HrxArchive
[src]
impl Eq for HrxArchive
[src]
impl FromStr for HrxArchive
[src]
type Err = HrxError
The associated error which can be returned from parsing.
fn from_str(s: &str) -> Result<Self, Self::Err>
[src]
impl Hash for HrxArchive
[src]
fn hash<__H: Hasher>(&self, state: &mut __H)
[src]
fn hash_slice<H>(data: &[Self], state: &mut H) where
H: Hasher,
1.3.0[src]
H: Hasher,
impl Ord for HrxArchive
[src]
fn cmp(&self, other: &HrxArchive) -> Ordering
[src]
#[must_use]fn max(self, other: Self) -> Self
1.21.0[src]
#[must_use]fn min(self, other: Self) -> Self
1.21.0[src]
#[must_use]fn clamp(self, min: Self, max: Self) -> Self
[src]
impl PartialEq<HrxArchive> for HrxArchive
[src]
fn eq(&self, other: &HrxArchive) -> bool
[src]
fn ne(&self, other: &HrxArchive) -> bool
[src]
impl PartialOrd<HrxArchive> for HrxArchive
[src]
fn partial_cmp(&self, other: &HrxArchive) -> Option<Ordering>
[src]
fn lt(&self, other: &HrxArchive) -> bool
[src]
fn le(&self, other: &HrxArchive) -> bool
[src]
fn gt(&self, other: &HrxArchive) -> bool
[src]
fn ge(&self, other: &HrxArchive) -> bool
[src]
impl StructuralEq for HrxArchive
[src]
impl StructuralPartialEq for HrxArchive
[src]
Auto Trait Implementations
impl RefUnwindSafe for HrxArchive
impl Send for HrxArchive
impl Sync for HrxArchive
impl Unpin for HrxArchive
impl UnwindSafe for HrxArchive
Blanket Implementations
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> From<T> for T
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T> ToOwned for T where
T: Clone,
[src]
T: Clone,
type Owned = T
The resulting type after obtaining ownership.
fn to_owned(&self) -> T
[src]
fn clone_into(&self, target: &mut T)
[src]
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,