Skip to content

Commit 314de0c

Browse files
committed
der: more progress on clarify writer
1 parent 4c47965 commit 314de0c

File tree

2 files changed

+128
-48
lines changed

2 files changed

+128
-48
lines changed

der/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,9 @@ pub use {
399399
pem_rfc7468 as pem,
400400
};
401401

402+
#[cfg(feature = "clarify")]
403+
pub use writer::clarify::ClarifySliceWriter;
404+
402405
#[cfg(feature = "time")]
403406
pub use time;
404407

der/src/writer/clarify.rs

Lines changed: 125 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,53 @@
11
pub(crate) mod commentwriter;
22
pub(crate) mod hexdisplaylines;
33

4-
use crate::SliceWriter;
54
use crate::std::io::Write;
5+
use crate::{Encode, Error, SliceWriter};
66
use crate::{Length, Result, Tag};
77
use commentwriter::{CommentWriter, JavaCommentWriter, XmlCommentWriter};
8-
use core::cell::RefCell;
9-
use core::ops::DerefMut;
108
use hexdisplaylines::HexDisplayLines;
119
use std::borrow::Cow;
10+
use std::println;
1211
use std::string::String;
13-
use std::{boxed::Box, rc::Rc, vec::Vec};
12+
use std::{boxed::Box, vec::Vec};
1413

1514
use super::Writer;
1615

16+
pub trait EncodeClarifyExt: Encode {
17+
/// Encode this type as pretty-printed hex DER, with comments.
18+
fn to_der_clarify(&self, flavor: ClarifyFlavor) -> Result<String> {
19+
let outputs = self.to_der_clarify_ignorant(flavor);
20+
// Propagate encode and finish errors
21+
outputs.raw?;
22+
Ok(String::from_utf8(outputs.clarify_buf).expect("clarified output to be utf-8"))
23+
}
24+
25+
/// Encode this type as pretty-printed hex DER, with comments.
26+
/// Ignores any errors that occur during [`Encode::encode`].
27+
fn to_der_clarify_ignorant(&self, flavor: ClarifyFlavor) -> ClarifyOutputs<'static> {
28+
let len = match self.encoded_len() {
29+
Ok(len) => len,
30+
Err(err) => return ClarifyOutputs::from_err(err),
31+
};
32+
33+
let mut buf = Vec::with_capacity(u32::from(len) as usize);
34+
let mut writer = ClarifySliceWriter::new(&mut buf, Vec::new(), flavor);
35+
let result = self.encode(&mut writer);
36+
37+
let outputs = writer.finish();
38+
let outputs = ClarifyOutputs {
39+
// prioritize Encode::encode errors
40+
raw: result.and(outputs.raw),
41+
// but use buffer from finish() (even if encode failed)
42+
clarify_buf: outputs.clarify_buf,
43+
};
44+
45+
outputs.into_owned()
46+
}
47+
}
48+
49+
impl<T> EncodeClarifyExt for T where T: Encode {}
50+
1751
static INDENT_STR: &str =
1852
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
1953

@@ -27,7 +61,7 @@ pub struct ClarifySliceWriter<'a> {
2761
/// Clarifier that creates HEX with comments
2862
pub struct Clarifier {
2963
// Buffer into which debug HEX and comments are written
30-
debug_ref: Rc<RefCell<Vec<u8>>>,
64+
clarify_buf: Vec<u8>,
3165

3266
// Position in the buffer is used to track how long is the current sub-message
3367
last_position: u32,
@@ -42,35 +76,65 @@ pub struct Clarifier {
4276
}
4377

4478
/// Returned by .finish()
45-
pub struct FinishOutputs<'a> {
46-
pub raw: Result<&'a [u8]>,
47-
//pub debug_ref: Vec<u8>,
79+
pub struct ClarifyOutputs<'a> {
80+
pub raw: Result<Cow<'a, [u8]>>,
81+
pub clarify_buf: Vec<u8>,
82+
}
83+
84+
impl<'a> ClarifyOutputs<'a> {
85+
pub fn from_err(err: Error) -> ClarifyOutputs<'static> {
86+
ClarifyOutputs {
87+
raw: Err(err),
88+
clarify_buf: Vec::new(),
89+
}
90+
}
91+
92+
pub fn into_owned(self) -> ClarifyOutputs<'static> {
93+
ClarifyOutputs {
94+
raw: self.raw.map(|raw| Cow::Owned(raw.into_owned())),
95+
clarify_buf: self.clarify_buf,
96+
}
97+
}
98+
// pub fn and(result: Result<Cow<'a, [u8]>>) {
99+
// ClarifyOutputs {
100+
// // prioritize Encode::encode errors
101+
// raw: result.and(outputs.raw),
102+
// clarify_buf: outputs.clarify_buf,
103+
// };
104+
// }
105+
}
106+
107+
#[derive(Copy, Clone, Debug)]
108+
pub enum ClarifyFlavor {
109+
XmlComments,
110+
JavaComments,
111+
RustHex,
48112
}
49113

50114
impl Clarifier {
51-
pub fn new(debug_ref: Rc<RefCell<Vec<u8>>>, comment_xml: bool) -> Self {
115+
pub fn new(clarify_buf: Vec<u8>, flavor: ClarifyFlavor) -> Self {
52116
Self {
53-
debug_ref,
117+
clarify_buf,
54118

55119
last_position: 0,
56120
depth: Vec::new(),
57121

58122
indent_enabled: true,
59-
comment_writer: if comment_xml {
60-
Box::new(XmlCommentWriter::default())
61-
} else {
62-
Box::new(JavaCommentWriter::default())
123+
comment_writer: match flavor {
124+
ClarifyFlavor::XmlComments => Box::new(XmlCommentWriter::default()),
125+
ClarifyFlavor::JavaComments => Box::new(JavaCommentWriter::default()),
126+
ClarifyFlavor::RustHex => todo!(),
63127
},
64128
}
65129
}
66130
}
67131

68132
impl<'a> ClarifySliceWriter<'a> {
69133
/// Create a new encoder with the given byte slice as a backing buffer.
70-
pub fn new(bytes: &'a mut [u8], debug_ref: Rc<RefCell<Vec<u8>>>, comment_xml: bool) -> Self {
134+
pub fn new(bytes: &'a mut [u8], clarify_buf: Vec<u8>, flavor: ClarifyFlavor) -> Self {
71135
Self {
72136
writer: SliceWriter::new(bytes),
73-
clarifier: Clarifier::new(debug_ref, comment_xml),
137+
clarifier: Clarifier::new(clarify_buf, flavor),
74138
}
75139
}
76140

@@ -98,10 +162,10 @@ impl<'a> ClarifySliceWriter<'a> {
98162

99163
/// Finish encoding to the buffer, returning a slice containing the data
100164
/// written to the buffer.
101-
pub fn finish(self) -> FinishOutputs<'a> {
102-
FinishOutputs {
103-
raw: self.writer.finish(),
104-
//debug_buf: self.debug.expect("debug buf not taken"),
165+
pub fn finish(self) -> ClarifyOutputs<'a> {
166+
ClarifyOutputs {
167+
raw: self.writer.finish().map(|raw| Cow::Borrowed(raw)),
168+
clarify_buf: self.clarifier.clarify_buf,
105169
}
106170
}
107171

@@ -164,28 +228,24 @@ impl Clarifier {
164228
/// Writes indentation to debug output, for example "\n\t" for depth == 1
165229
pub fn write_clarify_indent(&mut self) {
166230
let indent = self.indent_str();
167-
let mut debugbuf = self.debug_ref.borrow_mut();
168231
{
169-
self.comment_writer
170-
.before_new_line(&mut debugbuf.deref_mut());
171-
write!(debugbuf, "\n{}", indent).unwrap();
232+
self.comment_writer.before_new_line(&mut self.clarify_buf);
233+
write!(&mut self.clarify_buf, "\n{}", indent).unwrap();
172234
}
173235
}
174236

175237
/// Writes hex bytes to debug output, for example "30 04 "
176238
pub fn write_clarify_hex(&mut self, slice: &[u8]) {
177239
let indent = self.indent_str();
178-
let mut debugbuf = self.debug_ref.borrow_mut();
179240
{
180-
write!(debugbuf, "{}", HexDisplayLines(&slice, indent)).unwrap();
241+
write!(&mut self.clarify_buf, "{}", HexDisplayLines(&slice, indent)).unwrap();
181242
}
182243
}
183244

184245
/// Writes string to debug output, for example a comment "// SEQUENCE"
185246
pub fn write_clarify_str(&mut self, s: &str) {
186-
let mut debugbuf = self.debug_ref.borrow_mut();
187247
{
188-
write!(debugbuf, "{}", s).unwrap();
248+
write!(&mut self.clarify_buf, "{}", s).unwrap();
189249
}
190250
}
191251
/// Writes string to debug output, for example a comment: `// SEQUENCE: name`
@@ -299,6 +359,7 @@ impl Clarifier {
299359

300360
impl<'a> Writer for ClarifySliceWriter<'a> {
301361
fn write(&mut self, slice: &[u8]) -> Result<()> {
362+
println!("writing {slice:?}");
302363
self.reserve(slice.len())?.copy_from_slice(slice);
303364
self.clarifier.last_position += slice.len() as u32;
304365

@@ -309,28 +370,44 @@ impl<'a> Writer for ClarifySliceWriter<'a> {
309370
}
310371
}
311372

312-
fn strip_transparent_types(type_name: &str) -> Cow<'_, str> {
313-
// EncodeValueRef is commonly used and it is completely transparent
314-
let type_name = if let Some(stripped) = type_name.strip_prefix("EncodeValueRef<") {
315-
let stripped = stripped.strip_suffix(">").unwrap_or(stripped);
316-
stripped
317-
} else {
318-
type_name
319-
};
373+
/// Strips wrappers, such as `EncodeValueRef`, which is commonly used and is completely transparent
374+
fn strip_transparent_types(mut type_name: &str) -> Cow<'_, str> {
375+
let prefixes = [
376+
"EncodeValueRef<",
377+
"ApplicationRef<",
378+
"ContextSpecificRef<",
379+
"PrivateRef<",
380+
];
381+
382+
for prefix in prefixes {
383+
type_name = if let Some(stripped) = type_name.strip_prefix(prefix) {
384+
let stripped = stripped.strip_suffix(">").unwrap_or(stripped);
385+
stripped
386+
} else {
387+
type_name
388+
};
389+
}
320390

321-
let type_name = if let Some(stripped) = type_name.strip_prefix("ApplicationRef<") {
322-
let stripped = stripped.strip_suffix(">").unwrap_or(stripped);
323-
stripped
324-
} else {
325-
type_name
326-
};
391+
Cow::Borrowed(type_name)
392+
}
393+
394+
#[cfg(test)]
395+
pub mod test {
396+
use std::{println, vec::Vec};
327397

328-
let type_name = if let Some(stripped) = type_name.strip_prefix("ContextSpecificRef<") {
329-
let stripped = stripped.strip_suffix(">").unwrap_or(stripped);
330-
stripped
331-
} else {
332-
type_name
398+
use crate::{
399+
asn1::OctetString,
400+
writer::clarify::{ClarifyFlavor, EncodeClarifyExt},
333401
};
334402

335-
Cow::Borrowed(type_name)
403+
#[test]
404+
fn clarify_simple_octetstring() {
405+
let obj = OctetString::new(&[0xAA, 0xBB, 0xCC]).unwrap();
406+
407+
let clarified = obj
408+
.to_der_clarify(ClarifyFlavor::XmlComments)
409+
.expect("encoded DER");
410+
411+
println!("clarified: {clarified}");
412+
}
336413
}

0 commit comments

Comments
 (0)