singlefile_formats/data/
base64.rs

1#![cfg_attr(docsrs, doc(cfg(feature = "base64")))]
2#![cfg(feature = "base64")]
3
4//! Defines a [`FileFormat`] that wraps data from another format in Base64.
5
6pub extern crate base64 as original;
7
8use base64::engine::Engine;
9use base64::engine::general_purpose::*;
10use base64::read::DecoderReader;
11use base64::write::{EncoderWriter, EncoderStringWriter};
12use singlefile::{FileFormat, FileFormatUtf8};
13
14use std::io::{Read, Write};
15
16/// Takes a [`FileFormat`], encoding any the contents emitted by the format in Base64 before
17/// writing to disk, and decoding contents emitted by the format from Base64 before parsing.
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub struct Base64<F, E = GeneralPurpose> {
20  /// The [`FileFormat`] to be used.
21  pub format: F,
22  /// The [`Engine`] to be used.
23  pub engine: E
24}
25
26impl<F, E> Base64<F, E> where E: Engine {
27  /// Creates a new [`Base64`], given an engine to encode and decode with.
28  pub const fn new(format: F, engine: E) -> Self {
29    Base64 { format, engine }
30  }
31}
32
33impl<F> Base64<F, GeneralPurpose> {
34  /// Creates a [`Base64`] using the [`STANDARD`] engine.
35  pub const fn with_standard(format: F) -> Self {
36    Self::new(format, STANDARD)
37  }
38
39  /// Creates a [`Base64`] using the [`STANDARD_NO_PAD`] engine.
40  pub const fn with_standard_no_pad(format: F) -> Self {
41    Self::new(format, STANDARD_NO_PAD)
42  }
43
44  /// Creates a [`Base64`] using the [`URL_SAFE`] engine.
45  pub const fn with_url_safe(format: F) -> Self {
46    Self::new(format, URL_SAFE)
47  }
48
49  /// Creates a [`Base64`] using the [`URL_SAFE_NO_PAD`] engine.
50  pub const fn with_url_safe_no_pad(format: F) -> Self {
51    Self::new(format, URL_SAFE_NO_PAD)
52  }
53}
54
55impl<F, E> Default for Base64<F, E> where F: Default, E: Default {
56  fn default() -> Self {
57    Base64 { format: F::default(), engine: E::default() }
58  }
59}
60
61impl<F, E, T> FileFormat<T> for Base64<F, E>
62where F: FileFormat<T>, E: Engine {
63  type FormatError = F::FormatError;
64
65  fn from_reader<R: Read>(&self, reader: R) -> Result<T, Self::FormatError> {
66    self.format.from_reader(DecoderReader::new(reader, &self.engine))
67  }
68
69  fn to_writer<W: Write>(&self, writer: W, value: &T) -> Result<(), Self::FormatError> {
70    self.format.to_writer(EncoderWriter::new(writer, &self.engine), value)
71  }
72}
73
74impl<F, E, T> FileFormatUtf8<T> for Base64<F, E>
75where F: FileFormat<T>, E: Engine {
76  fn from_string_buffer(&self, buf: &str) -> Result<T, Self::FormatError> {
77    self.from_buffer(buf.as_bytes())
78  }
79
80  fn to_string_buffer(&self, value: &T) -> Result<String, Self::FormatError> {
81    let mut writer = EncoderStringWriter::new(&self.engine);
82    self.format.to_writer(&mut writer, value)?;
83    Ok(writer.into_inner())
84  }
85}