Skip to content

Commit 4c47965

Browse files
committed
der: simplify Writer trait
1 parent 6a5e9b9 commit 4c47965

File tree

3 files changed

+84
-90
lines changed

3 files changed

+84
-90
lines changed

der/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ hex-literal = "1"
3333
proptest = "1"
3434

3535
[features]
36-
default = []
36+
default = ["clarify"]
3737
alloc = ["zeroize?/alloc"]
3838
std = ["alloc"]
3939

der/src/writer.rs

Lines changed: 4 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Writer trait.
22
33
#[cfg(feature = "clarify")]
4-
pub(crate) mod clarify;
4+
pub mod clarify;
55
#[cfg(feature = "pem")]
66
pub(crate) mod pem;
77
pub(crate) mod slice;
@@ -11,9 +11,6 @@ use crate::Result;
1111
#[cfg(feature = "std")]
1212
use std::io;
1313

14-
#[cfg(feature = "clarify")]
15-
use crate::Tag;
16-
1714
/// Writer trait which outputs encoded DER.
1815
pub trait Writer {
1916
/// Write the given DER-encoded bytes as output.
@@ -25,45 +22,9 @@ pub trait Writer {
2522
}
2623

2724
#[cfg(feature = "clarify")]
28-
/// Should return true for clarify writers
29-
fn is_clarify(&self) -> bool {
30-
false
31-
}
32-
33-
#[cfg(feature = "clarify")]
34-
/// Called when starting next TLV value
35-
fn clarify_start_value_type<T>(&mut self) {
36-
// can be overrided
37-
}
38-
39-
#[cfg(feature = "clarify")]
40-
/// Called when ending next TLV value
41-
fn clarify_end_value_type<T>(&mut self) {
42-
// can be overrided
43-
}
44-
45-
#[cfg(feature = "clarify")]
46-
/// Called when starting next TLV tag
47-
fn clarify_start_tag(&mut self, _tag: &Tag) {
48-
// can be overrided
49-
}
50-
51-
#[cfg(feature = "clarify")]
52-
/// Called when ending next TLV tag
53-
fn clarify_end_tag(&mut self, _tag: &Tag) {
54-
// can be overrided
55-
}
56-
57-
#[cfg(feature = "clarify")]
58-
/// Called when writing field with name
59-
fn clarify_field_name(&mut self, _field_name: &str) {
60-
// can be overrided
61-
}
62-
63-
#[cfg(feature = "clarify")]
64-
// Called when writing choice, e.g. enum name: "DnsName"
65-
fn clarify_choice(&mut self, _choice_name: &[u8]) {
66-
// can be overrided
25+
/// Should return Some(clarifier) for clarify writers
26+
fn clarifier(&mut self) -> Option<&mut clarify::Clarifier> {
27+
None
6728
}
6829
}
6930

der/src/writer/clarify.rs

Lines changed: 79 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,21 @@ static INDENT_STR: &str =
2121
pub struct ClarifySliceWriter<'a> {
2222
writer: SliceWriter<'a>,
2323

24+
clarifier: Clarifier,
25+
}
26+
27+
/// Clarifier that creates HEX with comments
28+
pub struct Clarifier {
2429
// Buffer into which debug HEX and comments are written
2530
debug_ref: Rc<RefCell<Vec<u8>>>,
2631

32+
// Position in the buffer is used to track how long is the current sub-message
33+
last_position: u32,
34+
2735
/// Used for debug indentation
28-
depth: Vec<u32>,
36+
///
37+
/// Pushes writer positions on the stack
38+
depth: Vec<Option<u32>>,
2939

3040
indent_enabled: bool,
3141
comment_writer: Box<dyn CommentWriter>,
@@ -37,13 +47,14 @@ pub struct FinishOutputs<'a> {
3747
//pub debug_ref: Vec<u8>,
3848
}
3949

40-
impl<'a> ClarifySliceWriter<'a> {
41-
/// Create a new encoder with the given byte slice as a backing buffer.
42-
pub fn new(bytes: &'a mut [u8], debug_ref: Rc<RefCell<Vec<u8>>>, comment_xml: bool) -> Self {
50+
impl Clarifier {
51+
pub fn new(debug_ref: Rc<RefCell<Vec<u8>>>, comment_xml: bool) -> Self {
4352
Self {
44-
writer: SliceWriter::new(bytes),
4553
debug_ref,
54+
55+
last_position: 0,
4656
depth: Vec::new(),
57+
4758
indent_enabled: true,
4859
comment_writer: if comment_xml {
4960
Box::new(XmlCommentWriter::default())
@@ -52,6 +63,16 @@ impl<'a> ClarifySliceWriter<'a> {
5263
},
5364
}
5465
}
66+
}
67+
68+
impl<'a> ClarifySliceWriter<'a> {
69+
/// 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 {
71+
Self {
72+
writer: SliceWriter::new(bytes),
73+
clarifier: Clarifier::new(debug_ref, comment_xml),
74+
}
75+
}
5576

5677
// /// Encode a value which impls the [`Encode`] trait.
5778
// pub fn encode<T: Encode>(&mut self, encodable: &T) -> Result<()> {
@@ -118,13 +139,28 @@ impl<'a> ClarifySliceWriter<'a> {
118139
// self.error(ErrorKind::Length { tag: Tag::Sequence })
119140
// }
120141
// }
142+
143+
/// Reserve a portion of the internal buffer, updating the internal cursor
144+
/// position and returning a mutable slice.
145+
fn reserve(&mut self, len: impl TryInto<Length>) -> Result<&mut [u8]> {
146+
self.writer.reserve(len)
147+
}
148+
}
149+
150+
impl Clarifier {
121151
/// Returns indentation, for example "\n\t" for depth == 1
122152
pub fn indent_str(&self) -> &'static str {
123153
let ilen = self.depth.len() * 1;
124154
let ilen = ilen.min(INDENT_STR.len());
125155
&INDENT_STR[..ilen]
126156
}
127157

158+
pub fn write_clarify_indent_if_enabled(&mut self) {
159+
if self.indent_enabled {
160+
self.write_clarify_indent();
161+
}
162+
}
163+
128164
/// Writes indentation to debug output, for example "\n\t" for depth == 1
129165
pub fn write_clarify_indent(&mut self) {
130166
let indent = self.indent_str();
@@ -180,54 +216,36 @@ impl<'a> ClarifySliceWriter<'a> {
180216
}
181217
}
182218

183-
/// Reserve a portion of the internal buffer, updating the internal cursor
184-
/// position and returning a mutable slice.
185-
fn reserve(&mut self, len: impl TryInto<Length>) -> Result<&mut [u8]> {
186-
self.writer.reserve(len)
187-
}
188-
189-
fn clarify_start_value_type_str(&mut self, type_name: &str) {
219+
/// input: u32::from(self.writer.position())
220+
pub fn clarify_start_value_type_str(&mut self, writer_pos: Option<u32>, type_name: &str) {
190221
self.indent_enabled = true;
191-
self.depth.push(u32::from(self.writer.position()));
222+
self.depth.push(writer_pos);
192223

193224
let type_name = strip_transparent_types(type_name);
194225
self.write_clarify_type_str("type", &type_name);
195226
}
196227

197-
fn clarify_end_value_type_str(&mut self, type_name: &str) {
198-
let current = u32::from(self.writer.position());
199-
let last_pos = self.depth.pop().unwrap_or(current);
200-
let diff = current - last_pos;
201-
202-
if diff > 16 {
203-
let type_name = strip_transparent_types(type_name);
204-
self.write_clarify_indent();
205-
self.write_clarify_type_str("end", type_name.as_ref());
206-
}
207-
}
208-
}
209-
210-
impl<'a> Writer for ClarifySliceWriter<'a> {
211-
fn write(&mut self, slice: &[u8]) -> Result<()> {
212-
self.reserve(slice.len())?.copy_from_slice(slice);
213-
214-
if self.indent_enabled {
215-
self.write_clarify_indent();
228+
fn clarify_end_value_type_str(&mut self, writer_pos: Option<u32>, type_name: &str) {
229+
let last_pos = self.depth.pop().unwrap_or(writer_pos);
230+
231+
match (writer_pos, last_pos) {
232+
(Some(writer_pos), Some(last_pos)) => {
233+
let diff = writer_pos - last_pos;
234+
if diff < 16 {
235+
// ignore short runs
236+
return;
237+
}
238+
}
239+
_ => {}
216240
}
217241

218-
self.write_clarify_hex(slice);
219-
Ok(())
220-
}
221-
222-
fn clarify_start_value_type<T>(&mut self) {
223-
self.clarify_start_value_type_str(&tynm::type_name::<T>());
224-
}
225-
fn clarify_end_value_type<T>(&mut self) {
226-
self.clarify_end_value_type_str(&tynm::type_name::<T>());
242+
let type_name = strip_transparent_types(type_name);
243+
self.write_clarify_indent();
244+
self.write_clarify_type_str("end", type_name.as_ref());
227245
}
228246

229247
/// for better tag-length pretty-printing inline
230-
fn clarify_end_tag(&mut self, _tag: &Tag) {
248+
pub fn clarify_end_tag(&mut self, _tag: &Tag) {
231249
// just to print a single length byte without indent
232250
self.indent_enabled = false;
233251
}
@@ -240,11 +258,18 @@ impl<'a> Writer for ClarifySliceWriter<'a> {
240258
// self.indent_enabled = enabled;
241259
// }
242260

243-
fn clarify_field_name(&mut self, field_name: &str) {
261+
pub fn clarify_field_name(&mut self, field_name: &str) {
244262
self.write_clarify_indent();
245263
self.write_clarify_type_str("field", field_name);
246264
}
247265

266+
pub fn clarify_start_value_type<T>(&mut self) {
267+
self.clarify_start_value_type_str(Some(self.last_position), &tynm::type_name::<T>());
268+
}
269+
pub fn clarify_end_value_type<T>(&mut self) {
270+
self.clarify_end_value_type_str(Some(self.last_position), &tynm::type_name::<T>());
271+
}
272+
248273
// fn clarify_end_length(&mut self, tag: Option<&Tag>, length: Length) {
249274
// self.indent_enabled = true;
250275
// if let Some(tag) = tag {
@@ -264,15 +289,23 @@ impl<'a> Writer for ClarifySliceWriter<'a> {
264289
// self.write_debug_int(value);
265290
// }
266291

267-
fn clarify_choice(&mut self, choice_name: &[u8]) {
292+
pub fn clarify_choice(&mut self, choice_name: &[u8]) {
268293
self.write_clarify_indent();
269294
if let Ok(choice_name) = std::str::from_utf8(choice_name) {
270295
self.write_clarify_type_str("CHOICE", choice_name);
271296
}
272297
}
298+
}
299+
300+
impl<'a> Writer for ClarifySliceWriter<'a> {
301+
fn write(&mut self, slice: &[u8]) -> Result<()> {
302+
self.reserve(slice.len())?.copy_from_slice(slice);
303+
self.clarifier.last_position += slice.len() as u32;
273304

274-
fn is_clarify(&self) -> bool {
275-
true
305+
self.clarifier.write_clarify_indent_if_enabled();
306+
self.clarifier.write_clarify_hex(slice);
307+
308+
Ok(())
276309
}
277310
}
278311

0 commit comments

Comments
 (0)