diff --git a/Cargo.toml b/Cargo.toml index 7b02d7f..a1bd7ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,4 +18,4 @@ tokio = { version = "1.32", features = ["full"] } bytes = "1.5" futures = "0.3.28" mime = "0.3" -async-trait = "0.1.73" \ No newline at end of file +sequential-test = "0.2" \ No newline at end of file diff --git a/examples/image_thumbs.yaml b/examples/image_thumbs.yaml index 9e2d246..6723b9f 100644 --- a/examples/image_thumbs.yaml +++ b/examples/image_thumbs.yaml @@ -1,10 +1,10 @@ thumbs: - - name: standard - quality: 80 - size: [640, 480] - mode: fit + - name: standard # this name will be added to the thumbnail with an underscore (_) + quality: 80 # PNG ignores this variable as it is always lossless + size: [ 640, 480 ] # Target size of the thumbnail. May not always be exact. + mode: fit # available are: 'fit' and 'crop' - name: mini quality: 80 - size: [40, 40] - mode: crop + size: [ 40, 40 ] + mode: crop \ No newline at end of file diff --git a/src/gcs.rs b/src/gcs.rs index dcfd0a5..acd110c 100644 --- a/src/gcs.rs +++ b/src/gcs.rs @@ -3,15 +3,19 @@ use object_store::gcp::{GoogleCloudStorage, GoogleCloudStorageBuilder}; use crate::{ImageThumbs, ThumbsResult}; impl ImageThumbs { - /// Create new ImageThumbs instance connected to Google Cloud Storage using the environment + /// Creates new ImageThumbs instance connected to Google Cloud Storage using the environment /// variables `GOOGLE_BUCKET` and `GOOGLE_SERVICE_ACCOUNT_KEY` to connect to GCS. + /// The later should be in the JSON format. /// /// Reads the config YAML file to know which thumbnails to create /// - /// TODO document config file structure + /// The config file must look like the example in `examples/image_thumbs.yaml`: + /// ```yaml + #[doc = include_str!("../examples/image_thumbs.yaml")] + /// ``` /// /// # Arguments - /// * config - Path to the config file from the crate root (`.yaml` may be omitted) + /// * `config` - Path to the config file from the crate root (`.yaml` may be omitted) pub async fn new(config: &str) -> ThumbsResult { let client = GoogleCloudStorageBuilder::from_env() .with_client_options(Self::client_options()) diff --git a/src/lib.rs b/src/lib.rs index 4e43ac7..fcae4e6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,7 +16,18 @@ mod model; mod storage; impl ImageThumbs { - /// Get image from object storage, create thumbnails, and put them in the `dest_dir` directory + /// Gets all images from one object storage level, creates thumbnails for each of them, and puts + /// them in the `dest_dir` directory. + /// + /// # Arguments + /// * `directory` - directory to create thumbnails for. + /// It will list all objects on this level and create thumbnails (if they do not already exist). + /// + /// * `dest_dir` - directory to store all created thumbnails. + /// This directory will be checked for already existent thumbnails, if `force_override` is false. + /// + /// * `force_override` - if `true` it will override already existent files with the same name. + /// If false, it will preserve already existent files. pub async fn create_thumbs_dir( &self, directory: Option<&str>, @@ -39,6 +50,17 @@ impl ImageThumbs { Ok(()) } + /// Gets one image from the object storage, creates thumbnails for it, and puts them in the + /// `dest_dir` directory. + /// + /// # Arguments + /// * `file` - image to create thumbnails for. + /// + /// * `dest_dir` - directory to store all created thumbnails. + /// This directory will be checked for already existent thumbnails, if `force_override` is false. + /// + /// * `force_override` - if `true` it will override already existent files with the same name. + /// If false, it will preserve already existent files. pub async fn create_thumbs( &self, file: &str, @@ -56,6 +78,23 @@ impl ImageThumbs { .await } + /// Takes the raw bytes of an image, creates thumbnails for it, and puts them in the `dest_dir` + /// directory. + /// + /// # Arguments + /// * `bytes` - raw image bytes to create thumbnails for. + /// + /// * `dest_dir` - directory to store all created thumbnails. + /// This directory will be checked for already existent thumbnails, if `force_override` is false. + /// + /// * `image_name` - name used for the created thumbnails. Should not include the extension. + /// Final thumbnail names will be of the form `_.` + /// + /// * `format` - format of the input image. The output image will have the same type. + /// Currently supported are JPG and PNG. + /// + /// * `force_override` - if `true` it will override already existent files with the same name. + /// If false, it will preserve already existent files. pub async fn create_thumbs_dest_from_bytes( &self, bytes: Vec, @@ -72,6 +111,15 @@ impl ImageThumbs { self.upload_thumbs(thumbs).await } + /// Extracts the settings from the given configuration file. + /// + /// The config file must look like the example in `examples/image_thumbs.yaml`: + /// ```yaml + #[doc = include_str!("../examples/image_thumbs.yaml")] + /// ``` + /// + /// # Arguments + /// * `config` - Path to the config file from the crate root (`.yaml` may be omitted) fn settings(config: &str) -> ThumbsResult> { Ok(Config::builder() .add_source(config::File::with_name(config)) @@ -82,24 +130,19 @@ impl ImageThumbs { #[cfg(test)] mod tests { - use crate::model::ImageDetails; - use crate::ImageThumbs; use image::ImageFormat; use object_store::path::Path; - use object_store::ObjectStore; + use sequential_test::sequential; use tokio::fs::File; use tokio::io::{AsyncReadExt, BufReader}; + use crate::model::ImageDetails; + use crate::ImageThumbs; + #[tokio::test] - async fn from_cloud() { + #[sequential] + async fn create_thumbs() { let client = ImageThumbs::new("src/test/image_thumbs").await.unwrap(); - create_thumbs(&client).await; - create_thumbs_dir(&client).await; - create_thumbs_from_bytes(&client).await; - override_behaviour(&client).await; - } - - async fn create_thumbs(client: &ImageThumbs) { client .create_thumbs("penguin.jpg", "/test_dir", false) .await @@ -140,7 +183,10 @@ mod tests { client.delete("test_dir/penguin_mini.png").await.unwrap(); } - async fn create_thumbs_dir(client: &ImageThumbs) { + #[tokio::test] + #[sequential] + async fn create_thumbs_dir() { + let client = ImageThumbs::new("src/test/image_thumbs").await.unwrap(); client .create_thumbs_dir(None, "thumbs", false) .await @@ -200,7 +246,10 @@ mod tests { client.delete("thumbs/penguin_mini.png").await.unwrap(); } - async fn create_thumbs_from_bytes(client: &ImageThumbs) { + #[tokio::test] + #[sequential] + async fn create_thumbs_from_bytes() { + let client = ImageThumbs::new("src/test/image_thumbs").await.unwrap(); // create JPG image thumbs { let test_jpg = File::open("src/test/mock_data/testBucket/penguin.jpg") @@ -282,7 +331,10 @@ mod tests { .unwrap(); } - async fn override_behaviour(client: &ImageThumbs) { + #[tokio::test] + #[sequential] + async fn override_behaviour() { + let client = ImageThumbs::new("src/test/image_thumbs").await.unwrap(); let broken_thumb = ImageDetails { stem: "penguin_standard".to_string(), format: ImageFormat::Png,