qrcode-generator-4.1.9/.cargo_vcs_info.json0000644000000001360000000000100143100ustar { "git": { "sha1": "72babf605616595a89825f79bd5c88f126e94afe" }, "path_in_vcs": "" }qrcode-generator-4.1.9/Cargo.toml0000644000000025330000000000100123110ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.62" name = "qrcode-generator" version = "4.1.9" authors = ["Magic Len "] include = [ "src/**/*", "Cargo.toml", "README.md", "LICENSE", ] description = "Generate QR Code matrices and images in RAW, PNG and SVG formats." homepage = "https://magiclen.org/qrcode-generator" readme = "README.md" keywords = [ "qrcode", "generate", "png", "svg", "vec", ] categories = [ "encoding", "multimedia::images", ] license = "MIT" repository = "https://github.com/magiclen/qrcode-generator" [package.metadata.docs.rs] all-features = true [dependencies.html-escape] version = "0.2" [dependencies.image] version = "0.24" features = ["png"] optional = true default-features = false [dependencies.qrcodegen] version = "1.8" [dev-dependencies.manifest-dir-macros] version = "0.1" [features] default = ["image"] qrcode-generator-4.1.9/Cargo.toml.orig000064400000000000000000000014261046102023000157720ustar 00000000000000[package] name = "qrcode-generator" version = "4.1.9" authors = ["Magic Len "] edition = "2021" rust-version = "1.62" repository = "https://github.com/magiclen/qrcode-generator" homepage = "https://magiclen.org/qrcode-generator" keywords = ["qrcode", "generate", "png", "svg", "vec"] categories = ["encoding", "multimedia::images"] description = "Generate QR Code matrices and images in RAW, PNG and SVG formats." license = "MIT" include = ["src/**/*", "Cargo.toml", "README.md", "LICENSE"] [dependencies] qrcodegen = "1.8" html-escape = "0.2" [dependencies.image] version = "0.24" optional = true default-features = false features = ["png"] [dev-dependencies] manifest-dir-macros = "0.1" [features] default = ["image"] [package.metadata.docs.rs] all-features = true qrcode-generator-4.1.9/LICENSE000064400000000000000000000020661046102023000141110ustar 00000000000000MIT License Copyright (c) 2018 magiclen.org (Ron Li) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. qrcode-generator-4.1.9/README.md000064400000000000000000000046711046102023000143670ustar 00000000000000QR Code Generator ==================== [![CI](https://github.com/magiclen/qrcode-generator/actions/workflows/ci.yml/badge.svg)](https://github.com/magiclen/qrcode-generator/actions/workflows/ci.yml) This crate provides functions to generate QR Code matrices and images in RAW, PNG and SVG formats. ## Examples #### Encode any data to a QR Code matrix which is `Vec>`. ```rust use qrcode_generator::QrCodeEcc; let result: Vec> = qrcode_generator::to_matrix("Hello world!", QrCodeEcc::Low).unwrap(); println!("{:?}", result); ``` #### Encode any data to a PNG image stored in a Vec instance. ```rust use qrcode_generator::QrCodeEcc; let result: Vec = qrcode_generator::to_png_to_vec("Hello world!", QrCodeEcc::Low, 1024).unwrap(); println!("{:?}", result); ``` #### Encode any data to a PNG image stored in a file. ```rust use qrcode_generator::QrCodeEcc; qrcode_generator::to_png_to_file("Hello world!", QrCodeEcc::Low, 1024, "tests/data/file_output.png").unwrap(); ``` #### Encode any data to a SVG image stored in a String instance. ```rust use qrcode_generator::QrCodeEcc; let result: String = qrcode_generator::to_svg_to_string("Hello world!", QrCodeEcc::Low, 1024, None::<&str>).unwrap(); println!("{:?}", result); ``` #### Encode any data to a SVG image stored in a file. ```rust use qrcode_generator::QrCodeEcc; qrcode_generator::to_svg_to_file("Hello world!", QrCodeEcc::Low, 1024, None::<&str>, "tests/data/file_output.svg").unwrap(); ``` ## Low-level Usage ### Raw Image Data The `to_image` and `to_image_buffer` functions can be used, if you want to modify your image. ### Segments Every `to_*` function has a corresponding `_from_segments` function. You can concatenate segments by using different encoding methods, such as **numeric**, **alphanumeric** or **binary** to reduce the size (level) of your QR code matrix/image. ```rust use qrcode_generator::{QrCodeEcc, QrSegment}; let first = "1234567"; let second = "ABCDEFG"; let segments = [QrSegment::make_numeric(&first), QrSegment::make_alphanumeric(&second)]; let result: Vec> = qrcode_generator::to_matrix_from_segments(&segments, QrCodeEcc::Low).unwrap(); println!("{:?}", result); ``` More segments optimization apporaches: [magiclen/qrcode-segments-optimizer](https://github.com/magiclen/qrcode-segments-optimizer) ## Crates.io https://crates.io/crates/qrcode-generator ## Documentation https://docs.rs/qrcode-generator ## License [MIT](LICENSE) qrcode-generator-4.1.9/src/lib.rs000064400000000000000000000447751046102023000150240ustar 00000000000000/*! # QR Code Generator This crate provides functions to generate QR Code matrices and images in RAW, PNG and SVG formats. ## Examples #### Encode any data to a QR Code matrix which is `Vec>`. ```rust use qrcode_generator::QrCodeEcc; let result: Vec> = qrcode_generator::to_matrix("Hello world!", QrCodeEcc::Low).unwrap(); println!("{:?}", result); ``` #### Encode any data to a PNG image stored in a Vec instance. ```rust use qrcode_generator::QrCodeEcc; # #[cfg(feature = "image")] { let result: Vec = qrcode_generator::to_png_to_vec("Hello world!", QrCodeEcc::Low, 1024).unwrap(); println!("{:?}", result); # } ``` #### Encode any data to a PNG image stored in a file. ```rust use qrcode_generator::QrCodeEcc; # #[cfg(feature = "image")] { qrcode_generator::to_png_to_file("Hello world!", QrCodeEcc::Low, 1024, "tests/data/file_output.png").unwrap(); # } ``` #### Encode any data to a SVG image stored in a String instance. ```rust use qrcode_generator::QrCodeEcc; let result: String = qrcode_generator::to_svg_to_string("Hello world!", QrCodeEcc::Low, 1024, None::<&str>).unwrap(); println!("{:?}", result); ``` #### Encode any data to a SVG image stored in a file. ```rust use qrcode_generator::QrCodeEcc; qrcode_generator::to_svg_to_file("Hello world!", QrCodeEcc::Low, 1024, None::<&str>, "tests/data/file_output.png").unwrap(); ``` ## Low-level Usage ### Raw Image Data The `to_image` and `to_image_buffer` functions can be used, if you want to modify your image. ### Segments Every `to_*` function has a corresponding `_from_segments` function. You can concatenate segments by using different encoding methods, such as **numeric**, **alphanumeric** or **binary** to reduce the size (level) of your QR code matrix/image. ```rust use qrcode_generator::{QrCodeEcc, QrSegment}; let first = "1234567"; let second = "ABCDEFG"; let segments = [QrSegment::make_numeric(&first), QrSegment::make_alphanumeric(&second)]; let result: Vec> = qrcode_generator::to_matrix_from_segments(&segments, QrCodeEcc::Low).unwrap(); println!("{:?}", result); ``` More segments optimization apporaches: [magiclen/qrcode-segments-optimizer](https://github.com/magiclen/qrcode-segments-optimizer) */ pub extern crate qrcodegen; mod qr_code_error; use core::{mem::size_of, str::from_utf8}; use std::{ fs::{self, File}, io::Write, path::Path, }; #[cfg(feature = "image")] use image::codecs::png::{CompressionType, FilterType, PngEncoder}; #[cfg(feature = "image")] use image::{ColorType, ImageBuffer, ImageEncoder, Luma}; pub use qr_code_error::*; use qrcodegen::QrCode; pub use qrcodegen::{QrCodeEcc, QrSegment}; #[inline] fn generate_qrcode>(data: D, ecc: QrCodeEcc) -> Result { match from_utf8(data.as_ref()) { Ok(text) => generate_qrcode_from_str(text, ecc), Err(_) => { let qr = match QrCode::encode_binary(data.as_ref(), ecc) { Ok(qr) => qr, Err(_) => return Err(QRCodeError::DataTooLong), }; Ok(qr) }, } } #[inline] fn generate_qrcode_from_str>(text: S, ecc: QrCodeEcc) -> Result { let qr = match QrCode::encode_text(text.as_ref(), ecc) { Ok(qr) => qr, Err(_) => return Err(QRCodeError::DataTooLong), }; Ok(qr) } #[inline] fn generate_qrcode_from_segments( segments: &[QrSegment], ecc: QrCodeEcc, ) -> Result { let qr = match QrCode::encode_segments(segments, ecc) { Ok(qr) => qr, Err(_) => return Err(QRCodeError::DataTooLong), }; Ok(qr) } #[inline] fn to_matrix_inner(qr: QrCode) -> Vec> { let size = qr.size(); let size_u = size as usize; let mut rows = Vec::with_capacity(size_u); for y in 0..size { let mut row = Vec::with_capacity(size_u); for x in 0..size { row.push(qr.get_module(x, y)); } rows.push(row); } rows } #[inline] fn to_svg_inner, W: Write>( qr: QrCode, size: usize, description: Option, mut writer: W, ) -> Result<(), QRCodeError> { let margin_size = 1; let s = qr.size(); let data_length = s as usize; let data_length_with_margin = data_length + 2 * margin_size; let point_size = size / data_length_with_margin; if point_size == 0 { return Err(QRCodeError::ImageSizeTooSmall); } let margin = (size - (point_size * data_length)) / 2; writer.write_fmt(format_args!("\n\n"))?; match description { Some(description) => { let description = description.as_ref(); if !description.is_empty() { writer.write_all(b"\t")?; html_escape::encode_safe_to_writer(description, &mut writer)?; writer.write_all(b"\n")?; } }, None => { writer.write_fmt(format_args!( "\t{name} {version} by magiclen.org\n", name = env!("CARGO_PKG_NAME"), version = env!("CARGO_PKG_VERSION") ))?; }, } writer.write_fmt(format_args!( "\t\n\t\n")?; writer.flush()?; Ok(()) } #[inline] fn to_svg_to_vec_inner>( qr: QrCode, size: usize, description: Option, ) -> Result, QRCodeError> { let mut svg = Vec::with_capacity(32768); let margin_size = 1; let s = qr.size(); let data_length = s as usize; let data_length_with_margin = data_length + 2 * margin_size; let point_size = size / data_length_with_margin; if point_size == 0 { return Err(QRCodeError::ImageSizeTooSmall); } let margin = (size - (point_size * data_length)) / 2; svg.write_fmt(format_args!("\n\n"))?; match description { Some(description) => { let description = description.as_ref(); if !description.is_empty() { svg.extend_from_slice(b"\t"); html_escape::encode_safe_to_writer(description, &mut svg)?; svg.extend_from_slice(b"\n"); } }, None => { svg.write_fmt(format_args!( "\t{name} {version} by magiclen.org\n", name = env!("CARGO_PKG_NAME"), version = env!("CARGO_PKG_VERSION") ))?; }, } svg.write_fmt(format_args!( "\t\n\t\n")?; Ok(svg) } #[inline] fn to_svg_to_string_inner>( qr: QrCode, size: usize, description: Option, ) -> Result { let svg = to_svg_to_vec_inner(qr, size, description)?; Ok(unsafe { String::from_utf8_unchecked(svg) }) } #[inline] fn to_svg_to_file_inner, P: AsRef>( qr: QrCode, size: usize, description: Option, path: P, ) -> Result<(), QRCodeError> { let path = path.as_ref(); let file = File::create(path)?; to_svg_inner(qr, size, description, file).map_err(|err| { if fs::remove_file(path).is_err() { // do nothing } err }) } fn to_image_inner(qr: QrCode, size: usize) -> Result, QRCodeError> { if size >= 2usize.pow((size_of::() * 4) as u32) { return Err(QRCodeError::ImageSizeTooLarge); } let margin_size = 1; let s = qr.size(); let data_length = s as usize; let data_length_with_margin = data_length + 2 * margin_size; let point_size = size / data_length_with_margin; if point_size == 0 { return Err(QRCodeError::ImageSizeTooSmall); } let margin = (size - (point_size * data_length)) / 2; let length = size * size; let mut img_raw: Vec = vec![255u8; length]; for i in 0..s { for j in 0..s { if qr.get_module(i, j) { let x = i as usize * point_size + margin; let y = j as usize * point_size + margin; for j in y..(y + point_size) { let offset = j * size; for i in x..(x + point_size) { img_raw[offset + i] = 0; } } } } } Ok(img_raw) } #[cfg(feature = "image")] #[inline] fn to_png_inner(qr: QrCode, size: usize, writer: W) -> Result<(), QRCodeError> { let img_raw = to_image_inner(qr, size)?; let encoder = PngEncoder::new_with_quality(writer, CompressionType::Best, FilterType::NoFilter); Ok(encoder.write_image(&img_raw, size as u32, size as u32, ColorType::L8)?) } #[cfg(feature = "image")] #[inline] fn to_png_to_vec_inner(qr: QrCode, size: usize) -> Result, QRCodeError> { let mut png = Vec::with_capacity(4096); to_png_inner(qr, size, &mut png)?; Ok(png) } #[cfg(feature = "image")] #[inline] fn to_png_to_file_inner>( qr: QrCode, size: usize, path: P, ) -> Result<(), QRCodeError> { let path = path.as_ref(); let file = File::create(path)?; to_png_inner(qr, size, file).map_err(|err| { if fs::remove_file(path).is_err() { // do nothing } err }) } #[cfg(feature = "image")] #[inline] fn to_image_buffer_inner( qr: QrCode, size: usize, ) -> Result, Vec>, QRCodeError> { let img_raw = to_image_inner(qr, size)?; let img: ImageBuffer, Vec> = ImageBuffer::from_vec(size as u32, size as u32, img_raw).unwrap(); Ok(img) } // TODO public functions /// Encode data to a QR code matrix. #[inline] pub fn to_matrix>(data: D, ecc: QrCodeEcc) -> Result>, QRCodeError> { Ok(to_matrix_inner(generate_qrcode(data, ecc)?)) } /// Encode text to a QR code matrix. #[inline] pub fn to_matrix_from_str>( text: S, ecc: QrCodeEcc, ) -> Result>, QRCodeError> { Ok(to_matrix_inner(generate_qrcode_from_str(text, ecc)?)) } /// Encode segments to a QR code matrix. #[inline] pub fn to_matrix_from_segments( segments: &[QrSegment], ecc: QrCodeEcc, ) -> Result>, QRCodeError> { Ok(to_matrix_inner(generate_qrcode_from_segments(segments, ecc)?)) } /// Encode data to raw image in memory. pub fn to_image>( data: D, ecc: QrCodeEcc, size: usize, ) -> Result, QRCodeError> { to_image_inner(generate_qrcode(data, ecc)?, size) } /// Encode text to raw image in memory. pub fn to_image_from_str>( text: S, ecc: QrCodeEcc, size: usize, ) -> Result, QRCodeError> { to_image_inner(generate_qrcode_from_str(text, ecc)?, size) } /// Encode segments to raw image in memory. pub fn to_image_from_segments( segments: &[QrSegment], ecc: QrCodeEcc, size: usize, ) -> Result, QRCodeError> { to_image_inner(generate_qrcode_from_segments(segments, ecc)?, size) } /// Encode data to a SVG image in memory. #[inline] pub fn to_svg_to_string, DESC: AsRef>( data: D, ecc: QrCodeEcc, size: usize, description: Option, ) -> Result { to_svg_to_string_inner(generate_qrcode(data, ecc)?, size, description) } /// Encode text to a SVG image in memory. #[inline] pub fn to_svg_to_string_from_str, DESC: AsRef>( text: S, ecc: QrCodeEcc, size: usize, description: Option, ) -> Result { to_svg_to_string_inner(generate_qrcode_from_str(text, ecc)?, size, description) } /// Encode segments to a SVG image in memory. #[inline] pub fn to_svg_to_string_from_segments>( segments: &[QrSegment], ecc: QrCodeEcc, size: usize, description: Option, ) -> Result { to_svg_to_string_inner(generate_qrcode_from_segments(segments, ecc)?, size, description) } /// Encode data to a SVG image via a file path. #[inline] pub fn to_svg_to_file, DESC: AsRef, P: AsRef>( data: D, ecc: QrCodeEcc, size: usize, description: Option, path: P, ) -> Result<(), QRCodeError> { to_svg_to_file_inner(generate_qrcode(data, ecc)?, size, description, path) } /// Encode text to a SVG image via a file path. #[inline] pub fn to_svg_to_file_from_str, DESC: AsRef, P: AsRef>( text: S, ecc: QrCodeEcc, size: usize, description: Option, path: P, ) -> Result<(), QRCodeError> { to_svg_to_file_inner(generate_qrcode_from_str(text, ecc)?, size, description, path) } /// Encode segments to a SVG image via a file path. #[inline] pub fn to_svg_to_file_from_segments, P: AsRef>( segments: &[QrSegment], ecc: QrCodeEcc, size: usize, description: Option, path: P, ) -> Result<(), QRCodeError> { to_svg_to_file_inner(generate_qrcode_from_segments(segments, ecc)?, size, description, path) } /// Encode data to a SVG image via a writer. #[inline] pub fn to_svg_to_writer, DESC: AsRef, W: Write>( data: D, ecc: QrCodeEcc, size: usize, description: Option, writer: &mut W, ) -> Result<(), QRCodeError> { to_svg_inner(generate_qrcode(data, ecc)?, size, description, writer) } /// Encode text to a SVG image via a writer. #[inline] pub fn to_svg_to_writer_from_str, DESC: AsRef, W: Write>( text: S, ecc: QrCodeEcc, size: usize, description: Option, writer: &mut W, ) -> Result<(), QRCodeError> { to_svg_inner(generate_qrcode_from_str(text, ecc)?, size, description, writer) } /// Encode segments to a SVG image via a writer. #[inline] pub fn to_svg_to_writer_from_segments, W: Write>( segments: &[QrSegment], ecc: QrCodeEcc, size: usize, description: Option, writer: &mut W, ) -> Result<(), QRCodeError> { to_svg_inner(generate_qrcode_from_segments(segments, ecc)?, size, description, writer) } #[cfg(feature = "image")] /// Encode data to a PNG image in memory. #[inline] pub fn to_png_to_vec>( data: D, ecc: QrCodeEcc, size: usize, ) -> Result, QRCodeError> { to_png_to_vec_inner(generate_qrcode(data, ecc)?, size) } #[cfg(feature = "image")] /// Encode text to a PNG image in memory. #[inline] pub fn to_png_to_vec_from_str>( text: S, ecc: QrCodeEcc, size: usize, ) -> Result, QRCodeError> { to_png_to_vec_inner(generate_qrcode_from_str(text, ecc)?, size) } #[cfg(feature = "image")] /// Encode segments to a PNG image in memory. #[inline] pub fn to_png_to_vec_from_segments( segments: &[QrSegment], ecc: QrCodeEcc, size: usize, ) -> Result, QRCodeError> { to_png_to_vec_inner(generate_qrcode_from_segments(segments, ecc)?, size) } #[cfg(feature = "image")] /// Encode data to a PNG image via a file path. #[inline] pub fn to_png_to_file, P: AsRef>( data: D, ecc: QrCodeEcc, size: usize, path: P, ) -> Result<(), QRCodeError> { to_png_to_file_inner(generate_qrcode(data, ecc)?, size, path) } #[cfg(feature = "image")] /// Encode text to a PNG image via a file path. #[inline] pub fn to_png_to_file_from_str, P: AsRef>( text: S, ecc: QrCodeEcc, size: usize, path: P, ) -> Result<(), QRCodeError> { to_png_to_file_inner(generate_qrcode_from_str(text, ecc)?, size, path) } #[cfg(feature = "image")] /// Encode text to a PNG image via a file path. #[inline] pub fn to_png_to_file_from_segments>( segments: &[QrSegment], ecc: QrCodeEcc, size: usize, path: P, ) -> Result<(), QRCodeError> { to_png_to_file_inner(generate_qrcode_from_segments(segments, ecc)?, size, path) } #[cfg(feature = "image")] /// Encode data to a PNG image via a writer. #[inline] pub fn to_png_to_writer, W: Write>( data: D, ecc: QrCodeEcc, size: usize, writer: &mut W, ) -> Result<(), QRCodeError> { to_png_inner(generate_qrcode(data, ecc)?, size, writer) } #[cfg(feature = "image")] /// Encode text to a PNG image via a writer. #[inline] pub fn to_png_to_writer_from_str, W: Write>( text: S, ecc: QrCodeEcc, size: usize, writer: &mut W, ) -> Result<(), QRCodeError> { to_png_inner(generate_qrcode_from_str(text, ecc)?, size, writer) } #[cfg(feature = "image")] /// Encode segments to a PNG image via a writer. #[inline] pub fn to_png_to_writer_from_segments( segments: &[QrSegment], ecc: QrCodeEcc, size: usize, writer: &mut W, ) -> Result<(), QRCodeError> { to_png_inner(generate_qrcode_from_segments(segments, ecc)?, size, writer) } #[cfg(feature = "image")] /// Encode data to a image buffer. pub fn to_image_buffer>( data: D, ecc: QrCodeEcc, size: usize, ) -> Result, Vec>, QRCodeError> { to_image_buffer_inner(generate_qrcode(data, ecc)?, size) } #[cfg(feature = "image")] /// Encode text to a image buffer. pub fn to_image_buffer_from_str>( text: S, ecc: QrCodeEcc, size: usize, ) -> Result, Vec>, QRCodeError> { to_image_buffer_inner(generate_qrcode_from_str(text, ecc)?, size) } #[cfg(feature = "image")] /// Encode segments to a image buffer. pub fn to_image_buffer_from_segments>( segments: &[QrSegment], ecc: QrCodeEcc, size: usize, ) -> Result, Vec>, QRCodeError> { to_image_buffer_inner(generate_qrcode_from_segments(segments, ecc)?, size) } qrcode-generator-4.1.9/src/qr_code_error.rs000064400000000000000000000026331046102023000170660ustar 00000000000000use std::{ error::Error, fmt::{self, Display, Formatter}, io, }; #[cfg(feature = "image")] use image::ImageError; #[allow(clippy::upper_case_acronyms)] /// Errors when encoding QR code. #[derive(Debug)] pub enum QRCodeError { DataTooLong, IOError(io::Error), #[cfg(feature = "image")] ImageError(ImageError), ImageSizeTooSmall, ImageSizeTooLarge, } impl From for QRCodeError { #[inline] fn from(error: io::Error) -> Self { QRCodeError::IOError(error) } } #[cfg(feature = "image")] impl From for QRCodeError { #[inline] fn from(error: ImageError) -> Self { QRCodeError::ImageError(error) } } impl Display for QRCodeError { #[inline] fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { match self { QRCodeError::DataTooLong => { f.write_str("the supplied data does not fit any QR Code version") }, QRCodeError::IOError(error) => Display::fmt(error, f), #[cfg(feature = "image")] QRCodeError::ImageError(error) => Display::fmt(error, f), QRCodeError::ImageSizeTooSmall => { f.write_str("image size is too small to draw the whole QR code") }, QRCodeError::ImageSizeTooLarge => f.write_str("image size is too large to generate"), } } } impl Error for QRCodeError {}