diff --git a/Cargo.toml b/Cargo.toml index 2120c73..4579d7e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ license = "MIT OR Apache-2.0" version = "0.12.0" edition = "2018" authors = ["kennytm "] -keywords = ["qrcode"] +keywords = ["qrcode", "no_std"] repository = "https://github.com/kennytm/qrcode-rust" readme = "README.md" documentation = "http://docs.rs/qrcode" @@ -22,15 +22,17 @@ maintenance = { status = "passively-maintained" } [dependencies] image = { version = "0.23", default-features = false, optional = true } -checked_int_cast = "1" +checked_int_cast = { version = "1", optional = true } [dev-dependencies] image = "0.23" [features] -default = ["image", "svg"] +default = ["image", "svg", "std"] bench = [] -svg = [] +std = ["dep:checked_int_cast"] +image = ["std", "dep:image"] +svg = ["std"] [[bin]] name = "qrencode" diff --git a/src/bits.rs b/src/bits.rs index 5d1f93f..f78117b 100644 --- a/src/bits.rs +++ b/src/bits.rs @@ -1,6 +1,7 @@ //! The `bits` module encodes binary data into raw bits used in a QR code. -use std::cmp::min; +use alloc::vec::Vec; +use core::cmp::min; #[cfg(feature = "bench")] extern crate test; @@ -855,6 +856,7 @@ impl Bits { mod encode_tests { use crate::bits::Bits; use crate::types::{EcLevel, QrError, QrResult, Version}; + use alloc::vec::Vec; fn encode(data: &[u8], version: Version, ec_level: EcLevel) -> QrResult> { let mut bits = Bits::new(version); diff --git a/src/canvas.rs b/src/canvas.rs index 9d29a67..75833ee 100644 --- a/src/canvas.rs +++ b/src/canvas.rs @@ -9,7 +9,12 @@ //! c.apply_mask(MaskPattern::Checkerboard); //! let bools = c.to_bools(); -use std::cmp::max; +use alloc::boxed::Box; +use alloc::vec::Vec; +use core::cmp::max; + +#[cfg(test)] +use alloc::string::String; use crate::cast::As; use crate::types::{Color, EcLevel, Version}; @@ -1188,6 +1193,7 @@ impl Iterator for DataModuleIter { mod data_iter_tests { use crate::canvas::DataModuleIter; use crate::types::Version; + use alloc::vec::Vec; #[test] fn test_qr() { diff --git a/src/cast.rs b/src/cast.rs index aa21f46..c91d3f6 100644 --- a/src/cast.rs +++ b/src/cast.rs @@ -1,6 +1,6 @@ -use std::fmt::Display; +use core::fmt::Display; -#[cfg(debug_assertions)] +#[cfg(all(debug_assertions, feature = "std"))] use checked_int_cast::CheckedIntCast; pub trait Truncate { @@ -39,7 +39,7 @@ impl ExpectOrOverflow for Option { macro_rules! impl_as { ($ty:ty) => { - #[cfg(debug_assertions)] + #[cfg(all(debug_assertions, feature = "std"))] impl As for $ty { fn as_u16(self) -> u16 { self.as_u16_checked().expect_or_overflow(self, "u16") @@ -62,7 +62,7 @@ macro_rules! impl_as { } } - #[cfg(not(debug_assertions))] + #[cfg(any(not(debug_assertions), not(feature = "std")))] impl As for $ty { fn as_u16(self) -> u16 { self as u16 diff --git a/src/ec.rs b/src/ec.rs index 857de08..477aa0d 100644 --- a/src/ec.rs +++ b/src/ec.rs @@ -1,6 +1,7 @@ //! The `ec` module applies the Reed-Solomon error correction codes. -use std::ops::Deref; +use alloc::vec::Vec; +use core::ops::Deref; use crate::types::{EcLevel, QrResult, Version}; diff --git a/src/lib.rs b/src/lib.rs index b748659..e8bd55e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,16 +26,24 @@ //! println!("{}", string); //! ``` -#![cfg_attr(feature = "bench", feature(test, external_doc))] // Unstable libraries +#![cfg_attr(feature = "bench", feature(test))] // Unstable libraries #![deny(warnings, clippy::pedantic)] #![allow( clippy::must_use_candidate, // This is just annoying. clippy::use_self, // Rust 1.33 doesn't support Self::EnumVariant, let's try again in 1.37. )] -#![cfg_attr(feature = "bench", doc(include = "../README.md"))] +#![cfg_attr(all(feature = "bench", feature = "svg", feature = "image"), doc = include_str!("../README.md"))] // ^ make sure we can test our README.md. -use std::ops::Index; +// Compile without the stdlib unless the std feature is enabled +#![feature(error_in_core)] +#![cfg_attr(not(feature = "std"), no_std)] +#[macro_use] +extern crate alloc; + +use alloc::string::String; +use alloc::vec::Vec; +use core::ops::Index; pub mod bits; pub mod canvas; @@ -49,6 +57,7 @@ pub use crate::types::{Color, EcLevel, QrResult, Version}; use crate::cast::As; use crate::render::{Pixel, Renderer}; +#[cfg(feature = "std")] use checked_int_cast::CheckedIntCast; /// The encoded QR code symbol. @@ -185,6 +194,7 @@ impl QrCode { /// Checks whether a module at coordinate (x, y) is a functional module or /// not. + #[cfg(feature = "std")] pub fn is_functional(&self, x: usize, y: usize) -> bool { let x = x.as_i16_checked().expect("coordinate is too large for QR code"); let y = y.as_i16_checked().expect("coordinate is too large for QR code"); @@ -325,7 +335,7 @@ mod image_tests { fn test_annex_i_qr_as_image() { let code = QrCode::new(b"01234567").unwrap(); let image = code.render::>().build(); - let expected = load_from_memory(include_bytes!("test_annex_i_qr_as_image.png")).unwrap().to_luma(); + let expected = load_from_memory(include_bytes!("test_annex_i_qr_as_image.png")).unwrap().to_luma8(); assert_eq!(image.dimensions(), expected.dimensions()); assert_eq!(image.into_raw(), expected.into_raw()); } @@ -339,7 +349,7 @@ mod image_tests { .dark_color(Rgb([128, 0, 0])) .light_color(Rgb([255, 255, 128])) .build(); - let expected = load_from_memory(include_bytes!("test_annex_i_micro_qr_as_image.png")).unwrap().to_rgb(); + let expected = load_from_memory(include_bytes!("test_annex_i_micro_qr_as_image.png")).unwrap().to_rgb8(); assert_eq!(image.dimensions(), expected.dimensions()); assert_eq!(image.into_raw(), expected.into_raw()); } diff --git a/src/optimize.rs b/src/optimize.rs index 31d0029..d0af878 100644 --- a/src/optimize.rs +++ b/src/optimize.rs @@ -1,6 +1,6 @@ //! Find the optimal data mode sequence to encode a piece of data. use crate::types::{Mode, Version}; -use std::slice::Iter; +use alloc::slice::Iter; #[cfg(feature = "bench")] extern crate test; @@ -155,6 +155,7 @@ impl<'a> Iterator for Parser<'a> { mod parse_tests { use crate::optimize::{Parser, Segment}; use crate::types::Mode; + use alloc::vec::Vec; fn parse(data: &[u8]) -> Vec { Parser::new(data).collect() @@ -338,6 +339,7 @@ pub fn total_encoded_len(segments: &[Segment], version: Version) -> usize { mod optimize_tests { use crate::optimize::{total_encoded_len, Optimizer, Segment}; use crate::types::{Mode, Version}; + use alloc::vec::Vec; fn test_optimization_result(given: Vec, expected: Vec, version: Version) { let prev_len = total_encoded_len(&*given, version); diff --git a/src/render/mod.rs b/src/render/mod.rs index 32fff6e..71f4306 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -2,7 +2,7 @@ use crate::cast::As; use crate::types::Color; -use std::cmp::max; +use core::cmp::max; pub mod image; pub mod string; diff --git a/src/render/string.rs b/src/render/string.rs index 431fa9e..f796675 100644 --- a/src/render/string.rs +++ b/src/render/string.rs @@ -3,6 +3,8 @@ use crate::cast::As; use crate::render::{Canvas as RenderCanvas, Pixel}; use crate::types::Color; +use alloc::string::String; +use alloc::vec::Vec; pub trait Element: Copy { fn default_color(color: Color) -> Self; diff --git a/src/render/unicode.rs b/src/render/unicode.rs index 4ae97b8..a03a192 100644 --- a/src/render/unicode.rs +++ b/src/render/unicode.rs @@ -1,6 +1,8 @@ //! UTF-8 rendering, with 2 pixels per symbol. use crate::render::{Canvas as RenderCanvas, Color, Pixel}; +use alloc::string::String; +use alloc::vec::Vec; const CODEPAGE: [&str; 4] = [" ", "\u{2584}", "\u{2580}", "\u{2588}"]; diff --git a/src/types.rs b/src/types.rs index 95a716c..e7379a5 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,8 +1,8 @@ use crate::cast::As; -use std::cmp::{Ordering, PartialOrd}; -use std::default::Default; -use std::fmt::{Display, Error, Formatter}; -use std::ops::Not; +use core::cmp::{Ordering, PartialOrd}; +use core::default::Default; +use core::fmt::{Display, Error, Formatter}; +use core::ops::Not; //------------------------------------------------------------------------------ //{{{ QrResult @@ -41,7 +41,7 @@ impl Display for QrError { } } -impl ::std::error::Error for QrError {} +impl ::core::error::Error for QrError {} /// `QrResult` is a convenient alias for a QR code generation result. pub type QrResult = Result;