Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add #![no_std] compatibility #60

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ license = "MIT OR Apache-2.0"
version = "0.12.0"
edition = "2018"
authors = ["kennytm <kennytm@gmail.com>"]
keywords = ["qrcode"]
keywords = ["qrcode", "no_std"]
repository = "https://github.com/kennytm/qrcode-rust"
readme = "README.md"
documentation = "http://docs.rs/qrcode"
Expand All @@ -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"
Expand Down
4 changes: 3 additions & 1 deletion src/bits.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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<Vec<u8>> {
let mut bits = Bits::new(version);
Expand Down
8 changes: 7 additions & 1 deletion src/canvas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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() {
Expand Down
8 changes: 4 additions & 4 deletions src/cast.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down Expand Up @@ -39,7 +39,7 @@ impl<T> ExpectOrOverflow for Option<T> {

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")
Expand All @@ -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
Expand Down
3 changes: 2 additions & 1 deletion src/ec.rs
Original file line number Diff line number Diff line change
@@ -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};

Expand Down
20 changes: 15 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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.
Expand Down Expand Up @@ -185,6 +194,7 @@ impl QrCode {

/// Checks whether a module at coordinate (x, y) is a functional module or
/// not.
#[cfg(feature = "std")]
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this is the only function actually enabled with std. All other std usage is already behind svg and image flags.

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");
Expand Down Expand Up @@ -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::<Luma<u8>>().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());
}
Expand All @@ -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());
}
Expand Down
4 changes: 3 additions & 1 deletion src/optimize.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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<Segment> {
Parser::new(data).collect()
Expand Down Expand Up @@ -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<Segment>, expected: Vec<Segment>, version: Version) {
let prev_len = total_encoded_len(&*given, version);
Expand Down
2 changes: 1 addition & 1 deletion src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions src/render/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions src/render/unicode.rs
Original file line number Diff line number Diff line change
@@ -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}"];

Expand Down
10 changes: 5 additions & 5 deletions src/types.rs
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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<T> = Result<T, QrError>;
Expand Down