What is correct way to import rust dependencies?

I am implementing image-occlusion for Anki ecosystem (more in this branch GitHub - krmanik/anki at image-occlusion).

I need to get base64, width and height of image. I have added this Cargo.toml file in rslib

base64 = "0.13.0"
imagesize = "0.9"

Imported the dependencies

use base64::{encode};
use imagesize::size;

anki/metadata.rs at 72a251e2b34e1669da9cc08d043c81b4cd77a15d · krmanik/anki · GitHub

but getting errors.

error[E0432]: unresolved import `base64`
 --> rslib/src/image_occlusion/metadata.rs:4:5
  |
4 | use base64::{encode};
  |     ^^^^^^ use of undeclared crate or module `base64`

error[E0432]: unresolved import `imagesize`
 --> rslib/src/image_occlusion/metadata.rs:5:5
  |
5 | use imagesize::size;
  |     ^^^^^^^^^ use of undeclared crate or module `imagesize`

I have tested by creating a new cargo project where I get the result without errors. So, what is correct way to import the dependencies in above code?

use std::{fs, fs::File, io::Read, path::Path};

use base64::encode;
use imagesize::size;

fn main() {
    let img = "image.png";
    let data = get_base64(img);
    fs::write("base64.txt", data).expect("Unable to write file");

    let (width, height) = match size(img) {
        Ok(dim) => {(dim.width, dim.height)},
        Err(why) => {panic!("Error! {}", why)}
    };
    println!("{}, {}", width.to_string(), height.to_string());
}

fn get_base64(path: &str) -> String {
    let ext = Path::new(&path).extension().unwrap().to_str().unwrap();
    let mut file = File::open(path).unwrap();
    let mut vec = Vec::new();
    let _ = file.read_to_end(&mut vec);
    let base64 = encode(vec);
    return format!("data:image/{};base64,{}", ext, base64.replace("\r\n", ""));
}
3 Likes

It needs to add in rslib/BUILD.bazel

rust_library(
  deps = [
  ..
  ..
        "//rslib/cargo:base64",
]

I have generated the file using cargo raze which generated 340 files, so I think it is not the next step.

See cargo/README.md. I think rslib/BUILD.bazel is not mentioned there, but is still required to be updated before running update.py.

1 Like

Thanks, According the Readme, I need to create a issues for adding base64 = "0.13.0". I have removed imagesize and used js to get width and height, so that only one dependencies need to add now.

Is it necessary? Perhaps it would be possible to have the endpoint return raw bytes, and then convert them to base64 on the js end, using something like javascript - ArrayBuffer to base64 encoded string - Stack Overflow?

Looking forward to seeing what you come up with here :slight_smile:

1 Like

Thanks it works.

I have changed the rust code to this

    pub fn get_image_bytes(&mut self, path: &str) -> Result<ImageBytes> {
        let mut image_bytes = ImageBytes {
            ..Default::default()
        };

        let bytes = std::fs::read(path)?;
        image_bytes.data = bytes;

        Ok(image_bytes)
    }

and get base64 data in ts

    let b64encoded = protobuf.util.base64.encode(bytes.data, 0, bytes.data.length);
    let bs64 = "data:image/png;base64," + b64encoded;

As an aside, you can write that more succinctly as:

pub fn get_image_bytes(&self, path: &str) -> Result<ImageBytes> {
  Ok(ImageBytes {
    data: std::fs::read(path)?
   })
}
2 Likes