1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
use self::super::{HrxEntryData, HrxArchive, HrxError};
use std::io::{Error as IoError, Write};
use self::super::util::boundary_str;
enum CompoundError {
Hrx(HrxError),
Io(IoError),
}
impl From<HrxError> for CompoundError {
fn from(hrx: HrxError) -> CompoundError {
CompoundError::Hrx(hrx)
}
}
impl From<IoError> for CompoundError {
fn from(io: IoError) -> CompoundError {
CompoundError::Io(io)
}
}
impl From<CompoundError> for Result<HrxError, IoError> {
fn from(ce: CompoundError) -> Result<HrxError, IoError> {
match ce {
CompoundError::Hrx(hrx) => Ok(hrx),
CompoundError::Io(io) => Err(io),
}
}
}
pub fn write_archive<W: Write>(ar: &HrxArchive, into: &mut W) -> Result<(), Result<HrxError, IoError>> {
write_archive_impl(ar, into)?;
Ok(())
}
fn write_archive_impl<W: Write>(ar: &HrxArchive, into: &mut W) -> Result<(), CompoundError> {
ar.validate_content()?;
let bound = boundary_str(ar.boundary_length);
let mut first_bound = true;
let mut ending_newline = false;
for (p, e) in &ar.entries {
write_comment(&e.comment, &bound, &mut first_bound, into)?;
write_bound(&bound, &mut first_bound, into)?;
into.write_all(&[b' '])?;
into.write_all(p.0.as_bytes())?;
match e.data {
HrxEntryData::File { body: None } => {
ending_newline = true;
}
HrxEntryData::File { body: Some(ref body) } if body.is_empty() => {
ending_newline = true;
}
HrxEntryData::File { body: Some(ref body) } => {
into.write_all(&[b'\n'])?;
into.write_all(body.as_bytes())?;
ending_newline = false;
}
HrxEntryData::Directory => {
into.write_all(&[b'/'])?;
ending_newline = true;
}
}
}
if !write_comment(&ar.comment, &bound, &mut first_bound, into)? && ending_newline {
into.write_all(&[b'\n'])?;
}
Ok(())
}
fn write_bound<W: Write>(bound: &str, first_bound: &mut bool, into: &mut W) -> Result<(), CompoundError> {
if *first_bound {
into.write_all(bound[1..].as_bytes())?;
*first_bound = false;
} else {
into.write_all(bound.as_bytes())?;
}
Ok(())
}
fn write_comment<W: Write>(comment: &Option<String>, bound: &str, first_bound: &mut bool, into: &mut W) -> Result<bool, CompoundError> {
if let Some(cmt) = comment.as_ref() {
write_bound(bound, first_bound, into)?;
into.write_all(&[b'\n'])?;
into.write_all(cmt.as_bytes())?;
Ok(true)
} else {
Ok(false)
}
}