use std::fmt;
use util::int_to_usize;
use info::Info;
use quirc_sys::{ quirc_point, quirc_code, quirc_data };
use quirc_sys::{ quirc_decode, quirc_decode_error_t };
use error::{ Error, Result };
use self::quirc_decode_error_t::QUIRC_SUCCESS;
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
pub struct Vec2D {
pub x: usize,
pub y: usize,
}
impl Vec2D {
pub fn from_raw(p: quirc_point) -> Result<Self> {
let (x, y) = (int_to_usize(p.x)?, int_to_usize(p.y)?);
Ok(Vec2D { x, y })
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Image<'a> {
data: &'a [u8],
size: Vec2D,
}
impl<'a> Image<'a> {
pub fn new(data: &'a [u8], size: Vec2D) -> Result<Self> {
if data.len() == size.x * size.y {
Ok(Image { data, size })
} else {
Err(Error::SizeMismatch)
}
}
pub fn data(&self) -> &[u8] {
self.data
}
pub fn width(&self) -> usize {
self.size.x
}
pub fn height(&self) -> usize {
self.size.y
}
}
#[derive(Clone, Copy)]
pub struct QrCode(quirc_code);
impl QrCode {
#[doc(hidden)]
pub fn from_raw(raw: quirc_code) -> Result<Self> {
let _ = int_to_usize(raw.size)?;
for i in 0..4 {
let _ = Vec2D::from_raw(raw.corners[i])?;
}
Ok(QrCode(raw))
}
fn corner_at(&self, i: usize) -> Vec2D {
Vec2D::from_raw(self.0.corners[i]).expect("invalid corner coordinates")
}
pub fn top_left_corner(&self) -> Vec2D {
self.corner_at(0)
}
pub fn top_right_corner(&self) -> Vec2D {
self.corner_at(1)
}
pub fn bottom_right_corner(&self) -> Vec2D {
self.corner_at(2)
}
pub fn bottom_left_corner(&self) -> Vec2D {
self.corner_at(3)
}
pub fn size(&self) -> usize {
int_to_usize(self.0.size).expect("code size under- or overflows usize")
}
pub fn bitmap(&self) -> &[u8] {
let size = self.size();
let num_bits = size * size;
let num_bytes = (num_bits + 7) / 8;
&self.0.cell_bitmap[..num_bytes]
}
pub fn get(&self, coord: Vec2D) -> Option<bool> {
let size = self.size();
let Vec2D { x, y } = coord;
if x < size && y < size {
let i = y * size + x;
let bit = self.0.cell_bitmap[i / 8] >> (i % 8) & 1;
Some(bit != 0)
} else {
None
}
}
pub fn bit_at(&self, coord: Vec2D) -> bool {
self.get(coord).unwrap_or_else(
|| panic!("{:?} out of bounds for bitmap of size {}", coord, self.size())
)
}
pub fn decode(&self) -> Result<Info> {
let mut raw = quirc_data::default();
let error_code = unsafe {
quirc_decode(&self.0, &mut raw)
};
if error_code == QUIRC_SUCCESS {
Ok(Info::from_raw(raw))
} else {
Err(error_code.into())
}
}
}
impl fmt::Debug for QrCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("QrCode")
.field("top_left_corner", &self.top_left_corner())
.field("top_right_corner", &self.top_right_corner())
.field("bottom_right_corner", &self.bottom_right_corner())
.field("bottom_left_corner", &self.bottom_left_corner())
.field("size", &self.size())
.field("bitmap", &self.bitmap())
.finish()
}
}