More readable Debug::fmt for Value::{Ascii, Undefined}.
This commit is contained in:
parent
04e2cf568c
commit
79cc94f615
2 changed files with 94 additions and 20 deletions
|
|
@ -27,7 +27,6 @@
|
|||
extern crate exif;
|
||||
|
||||
use std::env;
|
||||
use std::fmt::Write;
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
|
@ -50,24 +49,7 @@ fn dump_file(path: &Path) -> Result<(), exif::Error> {
|
|||
println!(" {}/{}: {}",
|
||||
f.ifd_num.index(), f.tag,
|
||||
f.display_value().with_unit(&exif));
|
||||
if let exif::Value::Ascii(ref v) = f.value {
|
||||
println!(" Ascii({:?})",
|
||||
v.iter().map(|x| escape(x)).collect::<Vec<_>>());
|
||||
} else {
|
||||
println!(" {:?}", f.value);
|
||||
}
|
||||
println!(" {:?}", f.value);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn escape(bytes: &[u8]) -> String {
|
||||
let mut buf = String::new();
|
||||
for &c in bytes {
|
||||
match c {
|
||||
b'\\' | b'"' => write!(buf, "\\{}", c as char).unwrap(),
|
||||
0x20..=0x7e => buf.write_char(c as char).unwrap(),
|
||||
_ => write!(buf, "\\x{:02x}", c).unwrap(),
|
||||
}
|
||||
}
|
||||
buf
|
||||
}
|
||||
|
|
|
|||
94
src/value.rs
94
src/value.rs
|
|
@ -25,11 +25,12 @@
|
|||
//
|
||||
|
||||
use std::fmt;
|
||||
use std::fmt::Write as _;
|
||||
|
||||
use crate::endian::Endian;
|
||||
|
||||
/// Types and values of TIFF fields (for Exif attributes).
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Clone)]
|
||||
pub enum Value {
|
||||
/// Vector of 8-bit unsigned integers.
|
||||
Byte(Vec<u8>),
|
||||
|
|
@ -159,6 +160,65 @@ impl<'a> fmt::Display for Display<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Value {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Self::Byte(v) => f.debug_tuple("Byte").field(v).finish(),
|
||||
Self::Ascii(v) => f.debug_tuple("Ascii")
|
||||
.field(&IterDebugAdapter(
|
||||
|| v.iter().map(|x| AsciiDebugAdapter(x)))).finish(),
|
||||
Self::Short(v) => f.debug_tuple("Short").field(v).finish(),
|
||||
Self::Long(v) => f.debug_tuple("Long").field(v).finish(),
|
||||
Self::Rational(v) => f.debug_tuple("Rational").field(v).finish(),
|
||||
Self::SByte(v) => f.debug_tuple("SByte").field(v).finish(),
|
||||
Self::Undefined(v, o) => f.debug_tuple("Undefined")
|
||||
.field(&HexDebugAdapter(v))
|
||||
.field(&format_args!("ofs={:#x}", o)).finish(),
|
||||
Self::SShort(v) => f.debug_tuple("SShort").field(v).finish(),
|
||||
Self::SLong(v) => f.debug_tuple("SLong").field(v).finish(),
|
||||
Self::SRational(v) => f.debug_tuple("SRational").field(v).finish(),
|
||||
Self::Float(v) => f.debug_tuple("Float").field(v).finish(),
|
||||
Self::Double(v) => f.debug_tuple("Double").field(v).finish(),
|
||||
Self::Unknown(t, c, oo) => f.debug_tuple("Unknown")
|
||||
.field(&format_args!("typ={}", t))
|
||||
.field(&format_args!("cnt={}", c))
|
||||
.field(&format_args!("ofs={:#x}", oo)).finish(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct IterDebugAdapter<F>(F);
|
||||
|
||||
impl<F, T, I> fmt::Debug for IterDebugAdapter<F>
|
||||
where F: Fn() -> T, T: Iterator<Item = I>, I: fmt::Debug {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_list().entries(self.0()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
struct AsciiDebugAdapter<'a>(&'a [u8]);
|
||||
|
||||
impl<'a> fmt::Debug for AsciiDebugAdapter<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.write_char('"')?;
|
||||
self.0.iter().try_for_each(|&c| match c {
|
||||
b'\\' | b'"' => write!(f, "\\{}", c as char),
|
||||
0x20..=0x7e => f.write_char(c as char),
|
||||
_ => write!(f, "\\x{:02x}", c),
|
||||
})?;
|
||||
f.write_char('"')
|
||||
}
|
||||
}
|
||||
|
||||
struct HexDebugAdapter<'a>(&'a [u8]);
|
||||
|
||||
impl<'a> fmt::Debug for HexDebugAdapter<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.write_str("0x")?;
|
||||
self.0.iter().try_for_each(|x| write!(f, "{:02x}", x))
|
||||
}
|
||||
}
|
||||
|
||||
// Static default values.
|
||||
pub enum DefaultValue {
|
||||
None,
|
||||
|
|
@ -717,6 +777,38 @@ mod tests {
|
|||
assert_eq!(it.len(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn value_fmt_debug() {
|
||||
let v = Value::Byte(b"b\0y".to_vec());
|
||||
assert_eq!(format!("{:?}", v), "Byte([98, 0, 121])");
|
||||
let v = Value::Ascii(vec![]);
|
||||
assert_eq!(format!("{:?}", v), "Ascii([])");
|
||||
let v = Value::Ascii(vec![b"abc\"\\\n\x7f".to_vec(), b"".to_vec()]);
|
||||
assert_eq!(format!("{:?}", v), r#"Ascii(["abc\"\\\x0a\x7f", ""])"#);
|
||||
let v = Value::Short(vec![]);
|
||||
assert_eq!(format!("{:?}", v), "Short([])");
|
||||
let v = Value::Long(vec![1, 2]);
|
||||
assert_eq!(format!("{:?}", v), "Long([1, 2])");
|
||||
let v = Value::Rational(vec![(0, 0).into()]);
|
||||
assert_eq!(format!("{:?}", v), "Rational([Rational(0/0)])");
|
||||
let v = Value::SByte(vec![-3, 4, 5]);
|
||||
assert_eq!(format!("{:?}", v), "SByte([-3, 4, 5])");
|
||||
let v = Value::Undefined(vec![0, 0xff], 0);
|
||||
assert_eq!(format!("{:?}", v), "Undefined(0x00ff, ofs=0x0)");
|
||||
let v = Value::SShort(vec![6, -7]);
|
||||
assert_eq!(format!("{:?}", v), "SShort([6, -7])");
|
||||
let v = Value::SLong(vec![-9]);
|
||||
assert_eq!(format!("{:?}", v), "SLong([-9])");
|
||||
let v = Value::SRational(vec![(-2, -1).into()]);
|
||||
assert_eq!(format!("{:?}", v), "SRational([SRational(-2/-1)])");
|
||||
let v = Value::Float(vec![1.5, 0.0]);
|
||||
assert_eq!(format!("{:?}", v), "Float([1.5, 0.0])");
|
||||
let v = Value::Double(vec![-0.5, 1.0]);
|
||||
assert_eq!(format!("{:?}", v), "Double([-0.5, 1.0])");
|
||||
let v = Value::Unknown(1, 2, 10);
|
||||
assert_eq!(format!("{:?}", v), "Unknown(typ=1, cnt=2, ofs=0xa)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rational_fmt_display() {
|
||||
let r = Rational::from((u32::max_value(), u32::max_value()));
|
||||
|
|
|
|||
Reference in a new issue