diff options
author | Lars Wirzenius <liw@liw.fi> | 2022-09-03 09:03:13 +0300 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2022-09-03 09:08:20 +0300 |
commit | ba31a2ad25fa0ae3f3fd49eaa5174f9520248b90 (patch) | |
tree | 72335bc6156243c300b387a025a3a3ad96603930 /src/diagrams.rs | |
parent | 404006dfb651687713b7b8aa3183ed5c2fbe8acb (diff) | |
download | subplot-ba31a2ad25fa0ae3f3fd49eaa5174f9520248b90.tar.gz |
refactor: add a type for SVG images
This allows us to not use a generic byte vector, and slightly lessens
the chance of mistakes. Also, it strongly encodes what we need to know
about and do with SVG images.
Sponsored-by: author
Diffstat (limited to 'src/diagrams.rs')
-rw-r--r-- | src/diagrams.rs | 40 |
1 files changed, 33 insertions, 7 deletions
diff --git a/src/diagrams.rs b/src/diagrams.rs index 6e0b875..a62553f 100644 --- a/src/diagrams.rs +++ b/src/diagrams.rs @@ -59,6 +59,32 @@ lazy_static! { static ref JAVA_PATH: Mutex<PathBuf> = Mutex::new(env!("BUILTIN_JAVA_PATH").into()); } +/// An SVG image. +/// +/// SVG images are vector images, but we only need to treat them as +/// opaque blobs of bytes, so we don't try to represent them in any +/// other way. +pub struct Svg { + data: Vec<u8>, +} + +impl Svg { + fn new(data: Vec<u8>) -> Self { + Self { data } + } + + /// Return slice of the bytes of the image. + pub fn data(&self) -> &[u8] { + &self.data + } + + /// Number of bytes in the binary representation of the image. + #[allow(clippy::len_without_is_empty)] // is-empty doesn't make sense + pub fn len(&self) -> usize { + self.data.len() + } +} + /// A code block with markup for a diagram. /// /// The code block will be converted to an SVG image using an external @@ -71,7 +97,7 @@ lazy_static! { /// for the trait. pub trait DiagramMarkup { /// Convert the markup into an SVG. - fn as_svg(&self) -> Result<Vec<u8>, SubplotError>; + fn as_svg(&self) -> Result<Svg, SubplotError>; } /// A code block with pikchr markup. @@ -98,12 +124,12 @@ impl PikchrMarkup { } impl DiagramMarkup for PikchrMarkup { - fn as_svg(&self) -> Result<Vec<u8>, SubplotError> { + fn as_svg(&self) -> Result<Svg, SubplotError> { let mut flags = pikchr::PikchrFlags::default(); flags.generate_plain_errors(); let image = pikchr::Pikchr::render(&self.markup, self.class.as_deref(), flags) .map_err(SubplotError::PikchrRenderError)?; - Ok(image.as_bytes().to_vec()) + Ok(Svg::new(image.as_bytes().to_vec())) } } @@ -129,7 +155,7 @@ impl DotMarkup { } impl DiagramMarkup for DotMarkup { - fn as_svg(&self) -> Result<Vec<u8>, SubplotError> { + fn as_svg(&self) -> Result<Svg, SubplotError> { let path = DOT_PATH.lock().unwrap().clone(); let mut child = Command::new(&path) .arg("-Tsvg") @@ -146,7 +172,7 @@ impl DiagramMarkup for DotMarkup { .wait_with_output() .map_err(SubplotError::WaitForChild)?; if output.status.success() { - Ok(output.stdout) + Ok(Svg::new(output.stdout)) } else { Err(SubplotError::child_failed("dot", &output)) } @@ -196,7 +222,7 @@ impl PlantumlMarkup { } impl DiagramMarkup for PlantumlMarkup { - fn as_svg(&self) -> Result<Vec<u8>, SubplotError> { + fn as_svg(&self) -> Result<Svg, SubplotError> { let path = JAVA_PATH.lock().unwrap().clone(); let mut cmd = Command::new(&path); cmd.arg("-Djava.awt.headless=true") @@ -225,7 +251,7 @@ impl DiagramMarkup for PlantumlMarkup { .wait_with_output() .map_err(SubplotError::WaitForChild)?; if output.status.success() { - Ok(output.stdout) + Ok(Svg::new(output.stdout)) } else { Err(SubplotError::child_failed("plantuml", &output)) } |