fakejpeg 0.2.0

Rust port of Alun Jones' fakejpeg library
Documentation
// SPDX-FileCopyrightText: Alun Jones
// SPDX-FileCopyrightText: Gergely Nagy
// SPDX-FileContributor: Gergely Nagy
//
// SPDX-License-Identifier: MIT

use rand::{Rng, rngs::SmallRng};

/// Configuration for [`ImageGenerator`](crate::ImageGenerator).
///
/// It's built via [`ConfigBuilder::build`], using a builder pattern. This
/// configuration influences how images are generated: whether to have a
/// [comment](ConfigBuilder::comment), or what the [size
/// variance](ConfigBuilder::size_variance) is, etc.
///
/// A simple configuration can be instantiated from a random number generator
/// with [`Config::from`], or you can choose to use the
/// [defaults](Config::default), too.
///
/// # Examples
///
/// For the most simplest case, where you do not wish to set any options, nor a
/// custom random number generator, use [`Config::default`]:
///
/// ```rust
/// # use fakejpeg::Config;
/// # fn main() {
/// let config = Config::default();
/// # }
/// ```
///
/// If you do not wish to set a comment, nor any other options, but want to
/// provide your own random number generator:
///
/// ```rust
/// # use fakejpeg::Config;
/// # use rand::rngs::SmallRng;
/// # fn main() {
/// let mut rng: SmallRng = rand::make_rng();
/// let config = Config::from(&mut rng);
/// # }
/// ```
///
/// To configure other aspects of image generation, use [`ConfigBuilder`]:
///
/// ```rust
/// # use fakejpeg::ConfigBuilder;
/// # use rand::rngs::SmallRng;
/// # fn main() {
/// let mut rng: SmallRng = rand::make_rng();
/// let config = ConfigBuilder::default()
///   .comment("Hello from fakejpeg-rs!")
///   .size_variance(1.2)
///   .build(&mut rng);
/// # }
/// ```
///
/// Of course, if you still want to use the default random number generator,
/// while setting other options, that's also possible:
///
/// ```rust
/// # use fakejpeg::ConfigBuilder;
/// # fn main() {
/// let config = ConfigBuilder::default()
///   .comment("Hello from fakejpeg-rs!")
///   .size_variance(1.2)
///   .build_with_default_rng();
/// # }
/// ```
pub struct Config<R: Rng> {
    pub(crate) rng: R,

    pub(crate) options: Options,
}

impl<R: Rng> From<R> for Config<R> {
    /// Constructs a new [`Config`] from a [random number generator](Rng),
    /// using the [default options](ConfigBuilder::default).
    fn from(rng: R) -> Self {
        Self {
            rng,
            options: Options::default(),
        }
    }
}

impl Default for Config<SmallRng> {
    /// Returns a [`Config`] with the random number generator set to
    /// [`rand::make_rng()`] (using [`SmallRng`]), the [default
    /// options](ConfigBuilder::default).
    fn default() -> Self {
        Self {
            rng: rand::make_rng(),
            options: Options::default(),
        }
    }
}

/// Configuration option builder for the [`ImageGenerator`](crate::ImageGenerator).
///
/// See [`Config`] for examples and descriptions!
pub struct ConfigBuilder {
    options: Options,
}

impl Default for ConfigBuilder {
    /// Instantiate the default [`ConfigBuilder`]: no comment, and size variance
    /// set to 1.1.
    fn default() -> Self {
        Self {
            options: Options::default(),
        }
    }
}

impl ConfigBuilder {
    /// Set a comment to be embedded into the generated image.
    ///
    /// The comment will be embedded at the end, right before the End Of Image
    /// (EOI) marker.
    pub fn comment<S: AsRef<str>>(&mut self, comment: S) -> &mut Self {
        self.options.comment = Some(comment.as_ref().to_owned());
        self
    }

    /// Set the size variance of the generated image.
    ///
    /// The size variance controls how large the Start Of Scan (SOS) sections of
    /// the generated image will be. They will be at least as large as in the
    /// original image the template was made from, but the variance can make it
    /// slightly bigger.
    ///
    /// The [generator](crate::ImageGenerator) will choose a random value
    /// between the original size, and original size * variance.
    pub fn size_variance(&mut self, variance: f64) -> &mut Self {
        self.options.size_variance = variance;
        self
    }

    /// Build a [configuration](Config) out of the options, using the supplied
    /// random number generator.
    pub fn build<R: Rng>(&self, rng: R) -> Config<R> {
        Config {
            rng,
            options: Options {
                comment: self.options.comment.clone(),
                size_variance: self.options.size_variance,
            },
        }
    }

    /// Build a [configuration](Config) out of the options, using the default
    /// random number generator.
    #[must_use]
    pub fn build_with_default_rng(&self) -> Config<SmallRng> {
        self.build(rand::make_rng())
    }
}

pub struct Options {
    pub(crate) comment: Option<String>,
    pub(crate) size_variance: f64,
}

impl Default for Options {
    fn default() -> Self {
        Self {
            comment: None,
            size_variance: 1.1,
        }
    }
}