hxdmp/
lib.rs

1// Copyright (c) 2020 hxdmp developers
2//
3// Licensed under the Apache License, Version 2.0
4// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
5// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. All files in the project carrying such notice may not be copied,
7// modified, or distributed except according to those terms.
8
9//! `hxdmp`
10//!
11//! A small utility to create hexdump output from byte slices on the given
12//! writer.
13//!
14//! # Example
15//!
16//! ```
17//! # use hxdmp::hexdump;
18//! # use std::io::Result;
19//! #
20//! # fn main() -> Result<()> {
21//!     let some_bytes = b"Hello, World! I'm hexy";
22//!     let mut buffer = Vec::new();
23//!     assert!(hexdump(some_bytes, &mut buffer).is_ok());
24//!     assert_eq!(
25//!         r#"0000: 48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 21 20 49 27  Hello,.World!.I'
26//! 0016: 6D 20 68 65 78 79                                m.hexy"#,
27//!         String::from_utf8_lossy(&buffer)
28//!     );
29//! #     Ok(())
30//! # }
31// rustc lints
32#![deny(
33    absolute_paths_not_starting_with_crate,
34    anonymous_parameters,
35    array_into_iter,
36    asm_sub_register,
37    bare_trait_objects,
38    bindings_with_variant_name,
39    box_pointers,
40    break_with_label_and_loop,
41    cenum_impl_drop_cast,
42    clashing_extern_declarations,
43    coherence_leak_check,
44    confusable_idents,
45    const_evaluatable_unchecked,
46    const_item_mutation,
47    dead_code,
48    deprecated,
49    deprecated_in_future,
50    drop_bounds,
51    elided_lifetimes_in_paths,
52    ellipsis_inclusive_range_patterns,
53    explicit_outlives_requirements,
54    exported_private_dependencies,
55    forbidden_lint_groups,
56    function_item_references,
57    illegal_floating_point_literal_pattern,
58    improper_ctypes,
59    improper_ctypes_definitions,
60    incomplete_features,
61    indirect_structural_match,
62    inline_no_sanitize,
63    invalid_doc_attributes,
64    invalid_value,
65    irrefutable_let_patterns,
66    keyword_idents,
67    late_bound_lifetime_arguments,
68    legacy_derive_helpers,
69    macro_use_extern_crate,
70    meta_variable_misuse,
71    missing_abi,
72    missing_copy_implementations,
73    missing_debug_implementations,
74    missing_docs,
75    mixed_script_confusables,
76    mutable_borrow_reservation_conflict,
77    no_mangle_generic_items,
78    non_ascii_idents,
79    non_camel_case_types,
80    non_shorthand_field_patterns,
81    non_snake_case,
82    non_upper_case_globals,
83    nontrivial_structural_match,
84    noop_method_call,
85    overlapping_range_endpoints,
86    path_statements,
87    pointer_structural_match,
88    private_in_public,
89    proc_macro_back_compat,
90    proc_macro_derive_resolution_fallback,
91    redundant_semicolons,
92    renamed_and_removed_lints,
93    semicolon_in_expressions_from_macros,
94    single_use_lifetimes,
95    stable_features,
96    temporary_cstring_as_ptr,
97    trivial_bounds,
98    trivial_casts,
99    trivial_numeric_casts,
100    type_alias_bounds,
101    tyvar_behind_raw_pointer,
102    unaligned_references,
103    uncommon_codepoints,
104    unconditional_recursion,
105    uninhabited_static,
106    unknown_lints,
107    unnameable_test_items,
108    unreachable_code,
109    unreachable_patterns,
110    unreachable_pub,
111    unsafe_code,
112    unsafe_op_in_unsafe_fn,
113    unstable_features,
114    unstable_name_collisions,
115    unsupported_naked_functions,
116    unused_allocation,
117    unused_assignments,
118    unused_attributes,
119    unused_braces,
120    unused_comparisons,
121    unused_crate_dependencies,
122    unused_doc_comments,
123    unused_extern_crates,
124    unused_features,
125    unused_import_braces,
126    unused_imports,
127    unused_labels,
128    unused_lifetimes,
129    unused_macros,
130    unused_must_use,
131    unused_mut,
132    unused_parens,
133    unused_qualifications,
134    unused_results,
135    unused_unsafe,
136    unused_variables,
137    variant_size_differences,
138    where_clauses_object_safety,
139    while_true
140)]
141
142use std::io::{Result, Write};
143
144/// Create a hexdump on the given writer
145///
146/// # Example
147///
148/// ```
149/// # use hxdmp::hexdump;
150/// # use std::io::Result;
151/// #
152/// # fn main() -> Result<()> {
153///     let some_bytes = b"Hello, World! I'm hexy";
154///     let mut buffer = Vec::new();
155///     assert!(hexdump(some_bytes, &mut buffer).is_ok());
156///     assert_eq!(
157///         r#"0000: 48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 21 20 49 27  Hello,.World!.I'
158/// 0016: 6D 20 68 65 78 79                                m.hexy"#,
159///         String::from_utf8_lossy(&buffer)
160///     );
161/// #     Ok(())
162/// # }
163pub fn hexdump<W>(buffer: &[u8], writer: &mut W) -> Result<()>
164where
165    W: Write,
166{
167    hexdumpm(buffer, None, writer)
168}
169
170/// Create a hexdump on the given writer, restricted to an optional maximum number
171/// of lines
172///
173/// # Example
174///
175/// ```
176/// # use hxdmp::hexdumpm;
177/// # use std::io::Result;
178/// #
179/// # fn main() -> Result<()> {
180///     let some_bytes = b"Hello, World! I'm hexy";
181///     let mut buffer = Vec::new();
182///     assert!(hexdumpm(some_bytes, Some(1), &mut buffer).is_ok());
183///     assert_eq!(
184///         r#"0000: 48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 21 20 49 27  Hello,.World!.I'"#,
185///         String::from_utf8_lossy(&buffer)
186///     );
187/// #     Ok(())
188/// # }
189pub fn hexdumpm<W>(buffer: &[u8], max_lines_opt: Option<usize>, writer: &mut W) -> Result<()>
190where
191    W: Write,
192{
193    let sixteen_iter = buffer.chunks(16).enumerate();
194
195    if let Some(max) = max_lines_opt {
196        for (line, parts) in sixteen_iter {
197            if line < max {
198                hex(line, parts, writer)?;
199            } else {
200                break;
201            }
202        }
203    } else {
204        for (line, parts) in sixteen_iter {
205            hex(line, parts, writer)?;
206        }
207    }
208    Ok(())
209}
210
211fn hex<W>(line: usize, parts: &[u8], writer: &mut W) -> Result<()>
212where
213    W: Write,
214{
215    if line > 0 {
216        writeln!(writer)?;
217    }
218    write!(writer, "{:04}: ", line * 16)?;
219    for b in parts {
220        write!(writer, "{:02X} ", b)?;
221    }
222
223    for _ in parts.len()..16 {
224        write!(writer, "   ")?;
225    }
226
227    write!(writer, " ")?;
228
229    for b in parts {
230        let ch = *b as char;
231        if ch.is_ascii_graphic() {
232            write!(writer, "{}", ch)?;
233        } else {
234            write!(writer, ".")?;
235        }
236    }
237    Ok(())
238}
239
240#[cfg(test)]
241mod tests {
242    use super::hexdump;
243    use lazy_static::lazy_static;
244
245    lazy_static! {
246        static ref TUPLE1: (Vec<u8>, &'static str) = {
247            (
248                vec![0, 1, 3, 4, 65],
249                r#"0000: 00 01 03 04 41                                   ....A"#,
250            )
251        };
252        static ref TUPLE2: (Vec<u8>, &'static str) = {
253            (
254                vec![
255                    0x00, 0x00, 0x00, 0x13, 0x53, 0x53, 0x48, 0x2D, 0x32, 0x2E, 0x30, 0x2D, 0x74,
256                    0x75, 0x73, 0x73, 0x68, 0x5F, 0x30, 0x2E, 0x31, 0x2E, 0x30,
257                ],
258                r#"0000: 00 00 00 13 53 53 48 2D 32 2E 30 2D 74 75 73 73  ....SSH-2.0-tuss
2590016: 68 5F 30 2E 31 2E 30                             h_0.1.0"#,
260            )
261        };
262        static ref TUPLE3: (Vec<u8>, &'static str) = {
263            (
264                vec![
265                    0x00, 0x00, 0x00, 0x13, 0x53, 0x53, 0x48, 0x2D, 0x32, 0x2E, 0x30, 0x2D, 0x74,
266                    0x75, 0x73, 0x73, 0x68, 0x5F, 0x30, 0x2E, 0x31, 0x2E, 0x30, 0x00, 0x00, 0x00,
267                    0x13, 0x53, 0x53, 0x48, 0x2D, 0x32, 0x2E, 0x30, 0x2D, 0x4F, 0x70, 0x65, 0x6E,
268                    0x53, 0x53, 0x48, 0x5F, 0x38, 0x2E, 0x32, 0x00, 0x00, 0x01, 0x0D, 0x14, 0xD4,
269                    0x14, 0x01, 0x81, 0x25, 0x28, 0xC2, 0x47, 0xCE, 0xF9, 0x88, 0x6E, 0xE1, 0x46,
270                    0xE7, 0x3E, 0x00, 0x00, 0x00, 0x2E, 0x63, 0x75, 0x72, 0x76, 0x65, 0x32, 0x35,
271                    0x35, 0x31, 0x39, 0x2D, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x2C, 0x63, 0x75,
272                    0x72, 0x76, 0x65, 0x32, 0x35, 0x35, 0x31, 0x39, 0x2D, 0x73, 0x68, 0x61, 0x32,
273                    0x35, 0x36, 0x40, 0x6C, 0x69, 0x62, 0x73, 0x73, 0x68, 0x2E, 0x6F, 0x72, 0x67,
274                    0x00, 0x00, 0x00, 0x25, 0x73, 0x73, 0x68, 0x2D, 0x65, 0x64, 0x32, 0x35, 0x35,
275                    0x31, 0x39, 0x2C, 0x72, 0x73, 0x61, 0x2D, 0x73, 0x68, 0x61, 0x32, 0x2D, 0x35,
276                    0x31, 0x32, 0x2C, 0x72, 0x73, 0x61, 0x2D, 0x73, 0x68, 0x61, 0x32, 0x2D, 0x32,
277                    0x35, 0x36, 0x00, 0x00, 0x00, 0x1D, 0x63, 0x68, 0x61, 0x63, 0x68, 0x61, 0x32,
278                    0x30, 0x2D, 0x70, 0x6F, 0x6C, 0x79, 0x31, 0x33, 0x30, 0x35, 0x40, 0x6F, 0x70,
279                    0x65, 0x6E, 0x73, 0x73, 0x68, 0x2E, 0x63, 0x6F, 0x6D, 0x00, 0x00, 0x00, 0x1D,
280                    0x63, 0x68, 0x61, 0x63, 0x68, 0x61, 0x32, 0x30, 0x2D, 0x70, 0x6F, 0x6C, 0x79,
281                    0x31, 0x33, 0x30, 0x35, 0x40, 0x6F, 0x70, 0x65, 0x6E, 0x73, 0x73, 0x68, 0x2E,
282                    0x63, 0x6F, 0x6D, 0x00, 0x00, 0x00, 0x1D, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x73,
283                    0x68, 0x61, 0x32, 0x2D, 0x35, 0x31, 0x32, 0x2D, 0x65, 0x74, 0x6D, 0x40, 0x6F,
284                    0x70, 0x65, 0x6E, 0x73, 0x73, 0x68, 0x2E, 0x63, 0x6F, 0x6D, 0x00, 0x00, 0x00,
285                    0x1D, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x73, 0x68, 0x61, 0x32, 0x2D, 0x35, 0x31,
286                    0x32, 0x2D, 0x65, 0x74, 0x6D, 0x40, 0x6F, 0x70, 0x65, 0x6E, 0x73, 0x73, 0x68,
287                    0x2E, 0x63, 0x6F, 0x6D, 0x00, 0x00, 0x00, 0x04, 0x6E, 0x6F, 0x6E, 0x65, 0x00,
288                    0x00, 0x00, 0x04, 0x6E, 0x6F, 0x6E, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
289                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xDB, 0x14, 0x66,
290                    0x1C, 0xC5, 0x92, 0xC1, 0x54, 0x57, 0x7D, 0xED, 0x0A, 0xAA, 0x20, 0xB9, 0x17,
291                    0x62, 0x3D, 0x00, 0x00, 0x00, 0xE6, 0x63, 0x75, 0x72, 0x76, 0x65, 0x32, 0x35,
292                    0x35, 0x31, 0x39, 0x2D, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x2C, 0x63, 0x75,
293                    0x72, 0x76, 0x65, 0x32, 0x35, 0x35, 0x31, 0x39, 0x2D, 0x73, 0x68, 0x61, 0x32,
294                    0x35, 0x36, 0x40, 0x6C, 0x69, 0x62, 0x73, 0x73, 0x68, 0x2E, 0x6F, 0x72, 0x67,
295                    0x2C, 0x65, 0x63, 0x64, 0x68, 0x2D, 0x73, 0x68, 0x61, 0x32, 0x2D, 0x6E, 0x69,
296                    0x73, 0x74, 0x70, 0x32, 0x35, 0x36, 0x2C, 0x65, 0x63, 0x64, 0x68, 0x2D, 0x73,
297                    0x68, 0x61, 0x32, 0x2D, 0x6E, 0x69, 0x73, 0x74, 0x70, 0x33, 0x38, 0x34, 0x2C,
298                    0x65, 0x63, 0x64, 0x68, 0x2D, 0x73, 0x68, 0x61, 0x32, 0x2D, 0x6E, 0x69, 0x73,
299                    0x74, 0x70, 0x35, 0x32, 0x31, 0x2C, 0x64, 0x69, 0x66, 0x66, 0x69, 0x65, 0x2D,
300                    0x68, 0x65, 0x6C, 0x6C, 0x6D, 0x61, 0x6E, 0x2D, 0x67, 0x72, 0x6F, 0x75, 0x70,
301                    0x2D, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6E, 0x67, 0x65, 0x2D, 0x73, 0x68, 0x61,
302                    0x32, 0x35, 0x36, 0x2C, 0x64, 0x69, 0x66, 0x66, 0x69, 0x65, 0x2D, 0x68, 0x65,
303                    0x6C, 0x6C, 0x6D, 0x61, 0x6E, 0x2D, 0x67, 0x72, 0x6F, 0x75, 0x70, 0x31, 0x36,
304                    0x2D, 0x73, 0x68, 0x61, 0x35, 0x31, 0x32, 0x2C, 0x64, 0x69, 0x66, 0x66, 0x69,
305                    0x65, 0x2D, 0x68, 0x65, 0x6C, 0x6C, 0x6D, 0x61, 0x6E, 0x2D, 0x67, 0x72, 0x6F,
306                    0x75, 0x70, 0x31, 0x38, 0x2D, 0x73, 0x68, 0x61, 0x35, 0x31, 0x32, 0x2C, 0x64,
307                    0x69, 0x66, 0x66, 0x69, 0x65, 0x2D, 0x68, 0x65, 0x6C, 0x6C, 0x6D, 0x61, 0x6E,
308                    0x2D, 0x67, 0x72, 0x6F, 0x75, 0x70, 0x31, 0x34, 0x2D, 0x73, 0x68, 0x61, 0x32,
309                    0x35, 0x36, 0x00, 0x00, 0x00, 0x0B, 0x73, 0x73, 0x68, 0x2D, 0x65, 0x64, 0x32,
310                    0x35, 0x35, 0x31, 0x39, 0x00, 0x00, 0x00, 0x6C, 0x63, 0x68, 0x61, 0x63, 0x68,
311                    0x61, 0x32, 0x30, 0x2D, 0x70, 0x6F, 0x6C, 0x79, 0x31, 0x33, 0x30, 0x35, 0x40,
312                    0x6F, 0x70, 0x65, 0x6E, 0x73, 0x73, 0x68, 0x2E, 0x63, 0x6F, 0x6D, 0x2C, 0x61,
313                    0x65, 0x73, 0x31, 0x32, 0x38, 0x2D, 0x63, 0x74, 0x72, 0x2C, 0x61, 0x65, 0x73,
314                    0x31, 0x39, 0x32, 0x2D, 0x63, 0x74, 0x72, 0x2C, 0x61, 0x65, 0x73, 0x32, 0x35,
315                    0x36, 0x2D, 0x63, 0x74, 0x72, 0x2C, 0x61, 0x65, 0x73, 0x31, 0x32, 0x38, 0x2D,
316                    0x67, 0x63, 0x6D, 0x40, 0x6F, 0x70, 0x65, 0x6E, 0x73, 0x73, 0x68, 0x2E, 0x63,
317                    0x6F, 0x6D, 0x2C, 0x61, 0x65, 0x73, 0x32, 0x35, 0x36, 0x2D, 0x67, 0x63, 0x6D,
318                    0x40, 0x6F, 0x70, 0x65, 0x6E, 0x73, 0x73, 0x68, 0x2E, 0x63, 0x6F, 0x6D, 0x00,
319                    0x00, 0x00, 0x6C, 0x63, 0x68, 0x61, 0x63, 0x68, 0x61, 0x32, 0x30, 0x2D, 0x70,
320                    0x6F, 0x6C, 0x79, 0x31, 0x33, 0x30, 0x35, 0x40, 0x6F, 0x70, 0x65, 0x6E, 0x73,
321                    0x73, 0x68, 0x2E, 0x63, 0x6F, 0x6D, 0x2C, 0x61, 0x65, 0x73, 0x31, 0x32, 0x38,
322                    0x2D, 0x63, 0x74, 0x72, 0x2C, 0x61, 0x65, 0x73, 0x31, 0x39, 0x32, 0x2D, 0x63,
323                    0x74, 0x72, 0x2C, 0x61, 0x65, 0x73, 0x32, 0x35, 0x36, 0x2D, 0x63, 0x74, 0x72,
324                    0x2C, 0x61, 0x65, 0x73, 0x31, 0x32, 0x38, 0x2D, 0x67, 0x63, 0x6D, 0x40, 0x6F,
325                    0x70, 0x65, 0x6E, 0x73, 0x73, 0x68, 0x2E, 0x63, 0x6F, 0x6D, 0x2C, 0x61, 0x65,
326                    0x73, 0x32, 0x35, 0x36, 0x2D, 0x67, 0x63, 0x6D, 0x40, 0x6F, 0x70, 0x65, 0x6E,
327                    0x73, 0x73, 0x68, 0x2E, 0x63, 0x6F, 0x6D, 0x00, 0x00, 0x00, 0xD5, 0x75, 0x6D,
328                    0x61, 0x63, 0x2D, 0x36, 0x34, 0x2D, 0x65, 0x74, 0x6D, 0x40, 0x6F, 0x70, 0x65,
329                    0x6E, 0x73, 0x73, 0x68, 0x2E, 0x63, 0x6F, 0x6D, 0x2C, 0x75, 0x6D, 0x61, 0x63,
330                    0x2D, 0x31, 0x32, 0x38, 0x2D, 0x65, 0x74, 0x6D, 0x40, 0x6F, 0x70, 0x65, 0x6E,
331                    0x73, 0x73, 0x68, 0x2E, 0x63, 0x6F, 0x6D, 0x2C, 0x68, 0x6D, 0x61, 0x63, 0x2D,
332                    0x73, 0x68, 0x61, 0x32, 0x2D, 0x32, 0x35, 0x36, 0x2D, 0x65, 0x74, 0x6D, 0x40,
333                    0x6F, 0x70, 0x65, 0x6E, 0x73, 0x73, 0x68, 0x2E, 0x63, 0x6F, 0x6D, 0x2C, 0x68,
334                    0x6D, 0x61, 0x63, 0x2D, 0x73, 0x68, 0x61, 0x32, 0x2D, 0x35, 0x31, 0x32, 0x2D,
335                    0x65, 0x74, 0x6D, 0x40, 0x6F, 0x70, 0x65, 0x6E, 0x73, 0x73, 0x68, 0x2E, 0x63,
336                    0x6F, 0x6D, 0x2C, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x73, 0x68, 0x61, 0x31, 0x2D,
337                    0x65, 0x74, 0x6D, 0x40, 0x6F, 0x70, 0x65, 0x6E, 0x73, 0x73, 0x68, 0x2E, 0x63,
338                    0x6F, 0x6D, 0x2C, 0x75, 0x6D, 0x61, 0x63, 0x2D, 0x36, 0x34, 0x40, 0x6F, 0x70,
339                    0x65, 0x6E, 0x73, 0x73, 0x68, 0x2E, 0x63, 0x6F, 0x6D, 0x2C, 0x75, 0x6D, 0x61,
340                    0x63, 0x2D, 0x31, 0x32, 0x38, 0x40, 0x6F, 0x70, 0x65, 0x6E, 0x73, 0x73, 0x68,
341                    0x2E, 0x63, 0x6F, 0x6D, 0x2C, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x73, 0x68, 0x61,
342                    0x32, 0x2D, 0x32, 0x35, 0x36, 0x2C, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x73, 0x68,
343                    0x61, 0x32, 0x2D, 0x35, 0x31, 0x32, 0x2C, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x73,
344                    0x68, 0x61, 0x31, 0x00, 0x00, 0x00, 0xD5, 0x75, 0x6D, 0x61, 0x63, 0x2D, 0x36,
345                    0x34, 0x2D, 0x65, 0x74, 0x6D, 0x40, 0x6F, 0x70, 0x65, 0x6E, 0x73, 0x73, 0x68,
346                    0x2E, 0x63, 0x6F, 0x6D, 0x2C, 0x75, 0x6D, 0x61, 0x63, 0x2D, 0x31, 0x32, 0x38,
347                    0x2D, 0x65, 0x74, 0x6D, 0x40, 0x6F, 0x70, 0x65, 0x6E, 0x73, 0x73, 0x68, 0x2E,
348                    0x63, 0x6F, 0x6D, 0x2C, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x73, 0x68, 0x61, 0x32,
349                    0x2D, 0x32, 0x35, 0x36, 0x2D, 0x65, 0x74, 0x6D, 0x40, 0x6F, 0x70, 0x65, 0x6E,
350                    0x73, 0x73, 0x68, 0x2E, 0x63, 0x6F, 0x6D, 0x2C, 0x68, 0x6D, 0x61, 0x63, 0x2D,
351                    0x73, 0x68, 0x61, 0x32, 0x2D, 0x35, 0x31, 0x32, 0x2D, 0x65, 0x74, 0x6D, 0x40,
352                    0x6F, 0x70, 0x65, 0x6E, 0x73, 0x73, 0x68, 0x2E, 0x63, 0x6F, 0x6D, 0x2C, 0x68,
353                    0x6D, 0x61, 0x63, 0x2D, 0x73, 0x68, 0x61, 0x31, 0x2D, 0x65, 0x74, 0x6D, 0x40,
354                    0x6F, 0x70, 0x65, 0x6E, 0x73, 0x73, 0x68, 0x2E, 0x63, 0x6F, 0x6D, 0x2C, 0x75,
355                    0x6D, 0x61, 0x63, 0x2D, 0x36, 0x34, 0x40, 0x6F, 0x70, 0x65, 0x6E, 0x73, 0x73,
356                    0x68, 0x2E, 0x63, 0x6F, 0x6D, 0x2C, 0x75, 0x6D, 0x61, 0x63, 0x2D, 0x31, 0x32,
357                    0x38, 0x40, 0x6F, 0x70, 0x65, 0x6E, 0x73, 0x73, 0x68, 0x2E, 0x63, 0x6F, 0x6D,
358                    0x2C, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x73, 0x68, 0x61, 0x32, 0x2D, 0x32, 0x35,
359                    0x36, 0x2C, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x73, 0x68, 0x61, 0x32, 0x2D, 0x35,
360                    0x31, 0x32, 0x2C, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x73, 0x68, 0x61, 0x31, 0x00,
361                    0x00, 0x00, 0x15, 0x6E, 0x6F, 0x6E, 0x65, 0x2C, 0x7A, 0x6C, 0x69, 0x62, 0x40,
362                    0x6F, 0x70, 0x65, 0x6E, 0x73, 0x73, 0x68, 0x2E, 0x63, 0x6F, 0x6D, 0x00, 0x00,
363                    0x00, 0x15, 0x6E, 0x6F, 0x6E, 0x65, 0x2C, 0x7A, 0x6C, 0x69, 0x62, 0x40, 0x6F,
364                    0x70, 0x65, 0x6E, 0x73, 0x73, 0x68, 0x2E, 0x63, 0x6F, 0x6D, 0x00, 0x00, 0x00,
365                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
366                    0x33, 0x00, 0x00, 0x00, 0x0B, 0x73, 0x73, 0x68, 0x2D, 0x65, 0x64, 0x32, 0x35,
367                    0x35, 0x31, 0x39, 0x00, 0x00, 0x00, 0x20, 0xCA, 0x09, 0x52, 0x99, 0x4E, 0x66,
368                    0xBE, 0xDD, 0x26, 0xCA, 0x3F, 0xE2, 0xC1, 0x3F, 0xB0, 0xC9, 0xF5, 0x3F, 0x7C,
369                    0xBC, 0xB2, 0xF2, 0x1A, 0x4D, 0x6F, 0xB8, 0xCE, 0xEC, 0xC6, 0x96, 0x29, 0xF0,
370                    0x00, 0x00, 0x00, 0x20, 0x40, 0x26, 0x0F, 0x76, 0x0F, 0x79, 0xB1, 0x90, 0x13,
371                    0xFB, 0x03, 0x5B, 0x8A, 0x41, 0x63, 0xED, 0xBE, 0xBD, 0xB6, 0x1A, 0xD9, 0xC9,
372                    0x23, 0x5E, 0xE9, 0x49, 0x9D, 0xD7, 0xD8, 0x95, 0x4C, 0x66, 0x00, 0x00, 0x00,
373                    0x20, 0x02, 0x14, 0x1D, 0xB2, 0x15, 0xA7, 0x54, 0x67, 0xD2, 0x65, 0x24, 0x50,
374                    0x03, 0xF5, 0x0D, 0x95, 0xAD, 0x1D, 0x97, 0x25, 0x62, 0xD9, 0xBC, 0xFF, 0xED,
375                    0xB3, 0x5E, 0x11, 0x7C, 0x57, 0xC5, 0x08, 0x00, 0x00, 0x00, 0x21, 0x00, 0x86,
376                    0xF8, 0x27, 0x69, 0xCC, 0x94, 0x9B, 0x70, 0x66, 0xB7, 0x50, 0x9F, 0x2A, 0x98,
377                    0x0E, 0x52, 0x6D, 0x3E, 0x34, 0x65, 0x99, 0x43, 0xEA, 0x48, 0xCC, 0xCE, 0xF1,
378                    0xC5, 0x8F, 0xF3, 0x77, 0x7C,
379                ],
380                r#"0000: 00 00 00 13 53 53 48 2D 32 2E 30 2D 74 75 73 73  ....SSH-2.0-tuss
3810016: 68 5F 30 2E 31 2E 30 00 00 00 13 53 53 48 2D 32  h_0.1.0....SSH-2
3820032: 2E 30 2D 4F 70 65 6E 53 53 48 5F 38 2E 32 00 00  .0-OpenSSH_8.2..
3830048: 01 0D 14 D4 14 01 81 25 28 C2 47 CE F9 88 6E E1  .......%(.G...n.
3840064: 46 E7 3E 00 00 00 2E 63 75 72 76 65 32 35 35 31  F.>....curve2551
3850080: 39 2D 73 68 61 32 35 36 2C 63 75 72 76 65 32 35  9-sha256,curve25
3860096: 35 31 39 2D 73 68 61 32 35 36 40 6C 69 62 73 73  519-sha256@libss
3870112: 68 2E 6F 72 67 00 00 00 25 73 73 68 2D 65 64 32  h.org...%ssh-ed2
3880128: 35 35 31 39 2C 72 73 61 2D 73 68 61 32 2D 35 31  5519,rsa-sha2-51
3890144: 32 2C 72 73 61 2D 73 68 61 32 2D 32 35 36 00 00  2,rsa-sha2-256..
3900160: 00 1D 63 68 61 63 68 61 32 30 2D 70 6F 6C 79 31  ..chacha20-poly1
3910176: 33 30 35 40 6F 70 65 6E 73 73 68 2E 63 6F 6D 00  305@openssh.com.
3920192: 00 00 1D 63 68 61 63 68 61 32 30 2D 70 6F 6C 79  ...chacha20-poly
3930208: 31 33 30 35 40 6F 70 65 6E 73 73 68 2E 63 6F 6D  1305@openssh.com
3940224: 00 00 00 1D 68 6D 61 63 2D 73 68 61 32 2D 35 31  ....hmac-sha2-51
3950240: 32 2D 65 74 6D 40 6F 70 65 6E 73 73 68 2E 63 6F  2-etm@openssh.co
3960256: 6D 00 00 00 1D 68 6D 61 63 2D 73 68 61 32 2D 35  m....hmac-sha2-5
3970272: 31 32 2D 65 74 6D 40 6F 70 65 6E 73 73 68 2E 63  12-etm@openssh.c
3980288: 6F 6D 00 00 00 04 6E 6F 6E 65 00 00 00 04 6E 6F  om....none....no
3990304: 6E 65 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ne..............
4000320: 00 03 DB 14 66 1C C5 92 C1 54 57 7D ED 0A AA 20  ....f....TW}....
4010336: B9 17 62 3D 00 00 00 E6 63 75 72 76 65 32 35 35  ..b=....curve255
4020352: 31 39 2D 73 68 61 32 35 36 2C 63 75 72 76 65 32  19-sha256,curve2
4030368: 35 35 31 39 2D 73 68 61 32 35 36 40 6C 69 62 73  5519-sha256@libs
4040384: 73 68 2E 6F 72 67 2C 65 63 64 68 2D 73 68 61 32  sh.org,ecdh-sha2
4050400: 2D 6E 69 73 74 70 32 35 36 2C 65 63 64 68 2D 73  -nistp256,ecdh-s
4060416: 68 61 32 2D 6E 69 73 74 70 33 38 34 2C 65 63 64  ha2-nistp384,ecd
4070432: 68 2D 73 68 61 32 2D 6E 69 73 74 70 35 32 31 2C  h-sha2-nistp521,
4080448: 64 69 66 66 69 65 2D 68 65 6C 6C 6D 61 6E 2D 67  diffie-hellman-g
4090464: 72 6F 75 70 2D 65 78 63 68 61 6E 67 65 2D 73 68  roup-exchange-sh
4100480: 61 32 35 36 2C 64 69 66 66 69 65 2D 68 65 6C 6C  a256,diffie-hell
4110496: 6D 61 6E 2D 67 72 6F 75 70 31 36 2D 73 68 61 35  man-group16-sha5
4120512: 31 32 2C 64 69 66 66 69 65 2D 68 65 6C 6C 6D 61  12,diffie-hellma
4130528: 6E 2D 67 72 6F 75 70 31 38 2D 73 68 61 35 31 32  n-group18-sha512
4140544: 2C 64 69 66 66 69 65 2D 68 65 6C 6C 6D 61 6E 2D  ,diffie-hellman-
4150560: 67 72 6F 75 70 31 34 2D 73 68 61 32 35 36 00 00  group14-sha256..
4160576: 00 0B 73 73 68 2D 65 64 32 35 35 31 39 00 00 00  ..ssh-ed25519...
4170592: 6C 63 68 61 63 68 61 32 30 2D 70 6F 6C 79 31 33  lchacha20-poly13
4180608: 30 35 40 6F 70 65 6E 73 73 68 2E 63 6F 6D 2C 61  05@openssh.com,a
4190624: 65 73 31 32 38 2D 63 74 72 2C 61 65 73 31 39 32  es128-ctr,aes192
4200640: 2D 63 74 72 2C 61 65 73 32 35 36 2D 63 74 72 2C  -ctr,aes256-ctr,
4210656: 61 65 73 31 32 38 2D 67 63 6D 40 6F 70 65 6E 73  aes128-gcm@opens
4220672: 73 68 2E 63 6F 6D 2C 61 65 73 32 35 36 2D 67 63  sh.com,aes256-gc
4230688: 6D 40 6F 70 65 6E 73 73 68 2E 63 6F 6D 00 00 00  m@openssh.com...
4240704: 6C 63 68 61 63 68 61 32 30 2D 70 6F 6C 79 31 33  lchacha20-poly13
4250720: 30 35 40 6F 70 65 6E 73 73 68 2E 63 6F 6D 2C 61  05@openssh.com,a
4260736: 65 73 31 32 38 2D 63 74 72 2C 61 65 73 31 39 32  es128-ctr,aes192
4270752: 2D 63 74 72 2C 61 65 73 32 35 36 2D 63 74 72 2C  -ctr,aes256-ctr,
4280768: 61 65 73 31 32 38 2D 67 63 6D 40 6F 70 65 6E 73  aes128-gcm@opens
4290784: 73 68 2E 63 6F 6D 2C 61 65 73 32 35 36 2D 67 63  sh.com,aes256-gc
4300800: 6D 40 6F 70 65 6E 73 73 68 2E 63 6F 6D 00 00 00  m@openssh.com...
4310816: D5 75 6D 61 63 2D 36 34 2D 65 74 6D 40 6F 70 65  .umac-64-etm@ope
4320832: 6E 73 73 68 2E 63 6F 6D 2C 75 6D 61 63 2D 31 32  nssh.com,umac-12
4330848: 38 2D 65 74 6D 40 6F 70 65 6E 73 73 68 2E 63 6F  8-etm@openssh.co
4340864: 6D 2C 68 6D 61 63 2D 73 68 61 32 2D 32 35 36 2D  m,hmac-sha2-256-
4350880: 65 74 6D 40 6F 70 65 6E 73 73 68 2E 63 6F 6D 2C  etm@openssh.com,
4360896: 68 6D 61 63 2D 73 68 61 32 2D 35 31 32 2D 65 74  hmac-sha2-512-et
4370912: 6D 40 6F 70 65 6E 73 73 68 2E 63 6F 6D 2C 68 6D  m@openssh.com,hm
4380928: 61 63 2D 73 68 61 31 2D 65 74 6D 40 6F 70 65 6E  ac-sha1-etm@open
4390944: 73 73 68 2E 63 6F 6D 2C 75 6D 61 63 2D 36 34 40  ssh.com,umac-64@
4400960: 6F 70 65 6E 73 73 68 2E 63 6F 6D 2C 75 6D 61 63  openssh.com,umac
4410976: 2D 31 32 38 40 6F 70 65 6E 73 73 68 2E 63 6F 6D  -128@openssh.com
4420992: 2C 68 6D 61 63 2D 73 68 61 32 2D 32 35 36 2C 68  ,hmac-sha2-256,h
4431008: 6D 61 63 2D 73 68 61 32 2D 35 31 32 2C 68 6D 61  mac-sha2-512,hma
4441024: 63 2D 73 68 61 31 00 00 00 D5 75 6D 61 63 2D 36  c-sha1....umac-6
4451040: 34 2D 65 74 6D 40 6F 70 65 6E 73 73 68 2E 63 6F  4-etm@openssh.co
4461056: 6D 2C 75 6D 61 63 2D 31 32 38 2D 65 74 6D 40 6F  m,umac-128-etm@o
4471072: 70 65 6E 73 73 68 2E 63 6F 6D 2C 68 6D 61 63 2D  penssh.com,hmac-
4481088: 73 68 61 32 2D 32 35 36 2D 65 74 6D 40 6F 70 65  sha2-256-etm@ope
4491104: 6E 73 73 68 2E 63 6F 6D 2C 68 6D 61 63 2D 73 68  nssh.com,hmac-sh
4501120: 61 32 2D 35 31 32 2D 65 74 6D 40 6F 70 65 6E 73  a2-512-etm@opens
4511136: 73 68 2E 63 6F 6D 2C 68 6D 61 63 2D 73 68 61 31  sh.com,hmac-sha1
4521152: 2D 65 74 6D 40 6F 70 65 6E 73 73 68 2E 63 6F 6D  -etm@openssh.com
4531168: 2C 75 6D 61 63 2D 36 34 40 6F 70 65 6E 73 73 68  ,umac-64@openssh
4541184: 2E 63 6F 6D 2C 75 6D 61 63 2D 31 32 38 40 6F 70  .com,umac-128@op
4551200: 65 6E 73 73 68 2E 63 6F 6D 2C 68 6D 61 63 2D 73  enssh.com,hmac-s
4561216: 68 61 32 2D 32 35 36 2C 68 6D 61 63 2D 73 68 61  ha2-256,hmac-sha
4571232: 32 2D 35 31 32 2C 68 6D 61 63 2D 73 68 61 31 00  2-512,hmac-sha1.
4581248: 00 00 15 6E 6F 6E 65 2C 7A 6C 69 62 40 6F 70 65  ...none,zlib@ope
4591264: 6E 73 73 68 2E 63 6F 6D 00 00 00 15 6E 6F 6E 65  nssh.com....none
4601280: 2C 7A 6C 69 62 40 6F 70 65 6E 73 73 68 2E 63 6F  ,zlib@openssh.co
4611296: 6D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  m...............
4621312: 00 33 00 00 00 0B 73 73 68 2D 65 64 32 35 35 31  .3....ssh-ed2551
4631328: 39 00 00 00 20 CA 09 52 99 4E 66 BE DD 26 CA 3F  9......R.Nf..&.?
4641344: E2 C1 3F B0 C9 F5 3F 7C BC B2 F2 1A 4D 6F B8 CE  ..?...?|....Mo..
4651360: EC C6 96 29 F0 00 00 00 20 40 26 0F 76 0F 79 B1  ...).....@&.v.y.
4661376: 90 13 FB 03 5B 8A 41 63 ED BE BD B6 1A D9 C9 23  ....[.Ac.......#
4671392: 5E E9 49 9D D7 D8 95 4C 66 00 00 00 20 02 14 1D  ^.I....Lf.......
4681408: B2 15 A7 54 67 D2 65 24 50 03 F5 0D 95 AD 1D 97  ...Tg.e$P.......
4691424: 25 62 D9 BC FF ED B3 5E 11 7C 57 C5 08 00 00 00  %b.....^.|W.....
4701440: 21 00 86 F8 27 69 CC 94 9B 70 66 B7 50 9F 2A 98  !...'i...pf.P.*.
4711456: 0E 52 6D 3E 34 65 99 43 EA 48 CC CE F1 C5 8F F3  .Rm>4e.C.H......
4721472: 77 7C                                            w|"#,
473            )
474        };
475        static ref TEST_CASES: Vec<(Vec<u8>, &'static str)> = {
476            let mut test_cases = Vec::new();
477            test_cases.push(TUPLE1.clone());
478            test_cases.push(TUPLE2.clone());
479            test_cases.push(TUPLE3.clone());
480            test_cases
481        };
482    }
483
484    #[test]
485    fn dump_the_hex() {
486        let mut buffer = Vec::new();
487
488        for (actual, expected) in &*TEST_CASES {
489            assert!(hexdump(&actual, &mut buffer).is_ok());
490            assert_eq!(*expected, String::from_utf8_lossy(&buffer));
491            buffer.clear();
492        }
493    }
494}