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

Brand new API! #36

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
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
1 change: 0 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

root = true


[*]
end_of_line = lf
charset = utf-8
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ Possible log types:
- `[fixed]` for any bug fixes.
- `[security]` to invite users to upgrade in case of vulnerabilities.

### v3.0.0 (2024-06-11)

- [added] the `Barcode` trait to allow for a more generic interface to all barcode types.
- [fixed] [#37](https://github.com/buntine/barcoders/issues/37)
- [changed] all barcode types now implement the `Barcode` trait.
- [changed] Barcodes accept a `&[u8]` slice instead of a `&str` for data.

### v2.0.0 (2024-04-04)

- [changed] Updated image dependency from 0.22.0 to 0.25.0.
Expand Down
11 changes: 8 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "barcoders"
version = "2.0.0"
version = "3.0.0"
edition = "2021"
authors = ["Andrew Buntine <[email protected]>"]
description = "A barcode-encoding library"
Expand All @@ -17,11 +17,16 @@ exclude = [

[features]
default = ["ascii", "json", "svg", "std"]

ascii = []
json = []
svg = []
image = ["dep:image"]
std = []
image = ["std", "dep:image"] # Uses std::io

# blitz = [] # For faster (unsafe) implementations
nightly = [] # for error_in_core feature
alloc = [] # For vec and string
std = ["alloc"] # std is a superset of alloc

[dependencies.image]
version = "0.25"
Expand Down
101 changes: 52 additions & 49 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ For encode-only functionality (e.g if you just want to translate a `String` into

```toml
[dependencies]
barcoders = "2.0.0"
barcoders = "3.0"
```

If you want to generate barcodes into a particular format, turn on the appropriate feature(s):

```toml
[dependencies]
barcoders = {version = "2.0.0", features = ["image", "ascii", "svg", "json"]}
barcoders = {version = "3.0", features = ["image", "ascii", "svg", "json"]}
```

Each generator is an optional feature so you only need to compile what you want to use.
Expand All @@ -40,21 +40,21 @@ The ultimate goal of Barcoders is to provide encoding support for all major (and
### Symbologies

* EAN-13
* UPC-A
* JAN
* Bookland
* UPC-A
* JAN
* Bookland
* EAN-8
* EAN Supplementals
* EAN-2
* EAN-5
* EAN-2
* EAN-5
* Code11
* USD-8
* USD-8
* Code39
* Code93
* Code128 (A, B, C)
* Two-Of-Five
* Interleaved (ITF)
* Standard (STF)
* Interleaved (ITF)
* Standard (STF)
* Codabar
* More coming!

Expand All @@ -72,82 +72,83 @@ The ultimate goal of Barcoders is to provide encoding support for all major (and
## Examples

### Encoding
```rust
extern crate barcoders;

use barcoders::sym::ean13::*;
```rust
use barcoders::*;

// Each encoder accepts a String to be encoded. Valid data is barcode-specific
// and thus constructors return an Result<T, barcoders::error::Error>.
let barcode = EAN13::new("593456661897").unwrap();
let barcode = EAN13::new(b"593456661897").unwrap();

// The `encode` method returns a Vec<u8> of the binary representation of the
// generated barcode. This is useful if you want to add your own generator.
let encoded: Vec<u8> = barcode.encode();
```

### Image (GIF, WEBP, PNG) generation
```rust
extern crate barcoders;

```rust
use barcoders::sym::code39::*;
use barcoders::generators::image::*;
use std::io::prelude::*;
use std::io::BufWriter;
use std::fs::File;
use std::path::Path;

let barcode = Code39::new("1ISTHELONELIESTNUMBER").unwrap();
let barcode = Code39::new(b"1ISTHELONELIESTNUMBER").unwrap();
let png = Image::png(80); // You must specify the height in pixels.
let encoded = barcode.encode();

// Image generators return a Result<Vec<u8>, barcoders::error::Error) of encoded bytes.
let bytes = png.generate(&encoded[..]).unwrap();
let bytes = png.generate(&encoded).unwrap();

// Which you can then save to disk.
let file = File::create(&Path::new("my_barcode.png")).unwrap();
let mut writer = BufWriter::new(file);
writer.write(&bytes[..]).unwrap();
writer.write(&bytes).unwrap();

// Generated file ↓ ↓ ↓
```

![Code 39: 1ISTHELONELIESTNUMBER](/media/code39_1istheloneliestnumber.png?raw=true "Code 39: 1ISTHELONELIESTNUMBER")

You can also request an [image::RgbaImage](http://www.piston.rs/image/image/type.RgbaImage.html), which you can manipulate yourself:

```rust
let barcode = Code39::new("BEELZEBUB").unwrap();
let barcode = Code39::new(b"BEELZEBUB").unwrap();
let buffer = Image::image_buffer(100);
let encoded = barcode.encode();
let img = buffer.generate_buffer(&encoded[..]).unwrap();
let img = buffer.generate_buffer(&encoded).unwrap();

// Manipulate and save the image here...
```

You may also specify the barcode x-dimension, rotation, background/foreground colors and opacity by specifying the struct fields:

```rust
let gif = Image::GIF{height: 80,
xdim: 1,
rotation: Rotation::Zero,
// Using non black/white colors is generally not recommended by most vendors, but barcoders makes it possible.
foreground: Color::new([255, 0, 0, 255]),
background: Color::new([0, 255, 20, 255])};
let gif = Image::GIF{
height: 80,
xdim: 1,
rotation: Rotation::Zero,
// Using non black/white colors is generally not recommended by most vendors, but barcoders makes it possible.
foreground: Color::new([255, 0, 0, 255]),
background: Color::new([0, 255, 20, 255])
};
```

### SVG generation

SVG is similar to the other image types, but I've supplied it as a separate feature as it doesn't require third-party dependencies.

```rust
extern crate barcoders;

use barcoders::sym::code39::*;
use barcoders::generators::svg::*;
use std::io::prelude::*;
use std::io::BufWriter;
use std::fs::File;
use std::path::Path;

let barcode = Code39::new("56DFU4A777H").unwrap();
let barcode = Code39::new(b"56DFU4A777H").unwrap();
let svg = SVG::new(200); // You must specify the height in pixels.
let encoded = barcode.encode();
let data: String = svg.generate(&encoded).unwrap();
Expand All @@ -158,25 +159,26 @@ writer.write(data.as_bytes()).unwrap();
```

You may also specify the barcode x-dimension, background/foreground colors and opacity by specifying the struct fields:

```rust
let svg = SVG{height: 80,
xdim: 1,
// Using non black/white colors is generally not recommended by most vendors, but barcoders makes it possible.
foreground: Color::black(),
background: Color::new([0, 255, 20, 255])};
let svg = SVG{
height: 80,
xdim: 1,
// Using non black/white colors is generally not recommended by most vendors, but barcoders makes it possible.
foreground: Color::black(),
background: Color::new([0, 255, 20, 255])
};
```

### ASCII generation

The ASCII generator is useful for testing purposes.

```rust
extern crate barcoders;

use barcoders::sym::ean13::*;
use barcoders::generators::ascii::*;

let barcode = EAN13::new("750103131130").unwrap();
let barcode = EAN13::new(b"750103131130").unwrap();
let encoded = barcode.encode();

let ascii = ASCII::new();
Expand All @@ -197,7 +199,6 @@ assert_eq!(ascii.unwrap(),
".trim());
```


### JSON generation

This may be useful for passing encoded data to third-party systems in a conventional format.
Expand All @@ -208,18 +209,18 @@ extern crate barcoders;
use barcoders::sym::codabar::*;
use barcoders::generators::json::*;

let codabar = Codabar::new("A98B").unwrap();
let codabar = Codabar::new(b"A98B").unwrap();
let json = JSON::new();
let generated = json.generate(&codabar.encode()[..]);
let generated = json.generate(&codabar.encode());

assert_eq!(generated.unwrap(),
"
{
\"height\": 10,
\"xdim\": 1,
\"encoding\": [1,0,1,1,0,0,1,0,0,1,0,1,1,0,1,0,0,1,0,1,0,1,0,0,1,1,0,1,0,1,0,1,0,1,0,0,1,0,0,1,1]
\"height\": 10,
\"xdim\": 1,
\"encoding\": [1,0,1,1,0,0,1,0,0,1,0,1,1,0,1,0,0,1,0,1,0,1,0,0,1,1,0,1,0,1,0,1,0,1,0,0,1,0,0,1,1]
}
"
")
```

## Tests
Expand All @@ -228,21 +229,23 @@ Note, if you want to output actual image/svg files to the filesystem for visual
the `WRITE_TO_FILE` variable in the appropriate test modules.

Full suite:
```

```shell
$ cargo test --features="image svg ascii json"
```

Encoding only:
```

```shell
$ cargo test
```

## License

Licensed under either of

* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)

at your option.

Expand Down
7 changes: 1 addition & 6 deletions TODO
Original file line number Diff line number Diff line change
@@ -1,7 +1,2 @@
*- REFACTOR: Remove qualifiers from namespaced constants: CODE39_CHARS -> CHARS.
*- FEATURE: Code11 symbology
*.- PERFORMANCE: If checksum_char functions were private, it would allow for them to return the encoding instead of the char and thus the extra lookup to char_encoding would be able to be skipped (see Code39, etc)
* - REFACTOR: Perhaps make them all private and behave the same? (code128 returns u8, code39 returns char. wtf?)
*- REFACTOR: Fix monstrosity in place_pixels in image generator. (Potentially write a simple macro?)
- REFACTOR: Fix monstrosity in place_pixels in image generator. (Potentially write a simple macro?)
- PERFORMANCE: If user doesn't set image color, default to Luma8 instead of Rgba8 to save bytes.
- REFACTOR: Implement simple regex into Parse and remove valid_chars, valid_length, etc.
16 changes: 11 additions & 5 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
//! Custom error types.

use core::fmt;
#[cfg(all(not(feature = "std"), feature = "nightly"))]
use core::error::Error as ErrorTrait;
#[cfg(feature = "std")]
use std::error::Error as StdError;
use std::error::Error as ErrorTrait;

use core::fmt;

/// The possible errors that can occur during barcode encoding and generation.
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Error {
/// An invalid character found during encoding.
Character,
Expand All @@ -31,5 +34,8 @@ impl fmt::Display for Error {
}
}

#[cfg(feature = "std")]
impl StdError for Error {}
#[cfg(any(
feature = "std",
feature = "nightly"
))]
impl ErrorTrait for Error {}
2 changes: 1 addition & 1 deletion src/generators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub mod ascii;
#[cfg(feature = "json")]
pub mod json;

#[cfg(all(feature = "image", feature = "std"))]
#[cfg(feature = "image")]
pub mod image;

#[cfg(feature = "svg")]
Expand Down
Loading