// Adapted from datamatrix-rs symbol_size.rs; see THIRD_PARTY_NOTICES.md.
///|
priv struct Size {
width : Int
height : Int
capacity : Int
blocks : Int
ecc : Int
regions_x : Int
regions_y : Int
}
///|
let sizes : Array[Size] = [
{
width: 10,
height: 10,
capacity: 3,
blocks: 1,
ecc: 5,
regions_x: 1,
regions_y: 1,
},
{
width: 12,
height: 12,
capacity: 5,
blocks: 1,
ecc: 7,
regions_x: 1,
regions_y: 1,
},
{
width: 14,
height: 14,
capacity: 8,
blocks: 1,
ecc: 10,
regions_x: 1,
regions_y: 1,
},
{
width: 16,
height: 16,
capacity: 12,
blocks: 1,
ecc: 12,
regions_x: 1,
regions_y: 1,
},
{
width: 18,
height: 18,
capacity: 18,
blocks: 1,
ecc: 14,
regions_x: 1,
regions_y: 1,
},
{
width: 20,
height: 20,
capacity: 22,
blocks: 1,
ecc: 18,
regions_x: 1,
regions_y: 1,
},
{
width: 22,
height: 22,
capacity: 30,
blocks: 1,
ecc: 20,
regions_x: 1,
regions_y: 1,
},
{
width: 24,
height: 24,
capacity: 36,
blocks: 1,
ecc: 24,
regions_x: 1,
regions_y: 1,
},
{
width: 26,
height: 26,
capacity: 44,
blocks: 1,
ecc: 28,
regions_x: 1,
regions_y: 1,
},
{
width: 32,
height: 32,
capacity: 62,
blocks: 1,
ecc: 36,
regions_x: 2,
regions_y: 2,
},
{
width: 36,
height: 36,
capacity: 86,
blocks: 1,
ecc: 42,
regions_x: 2,
regions_y: 2,
},
{
width: 40,
height: 40,
capacity: 114,
blocks: 1,
ecc: 48,
regions_x: 2,
regions_y: 2,
},
{
width: 44,
height: 44,
capacity: 144,
blocks: 1,
ecc: 56,
regions_x: 2,
regions_y: 2,
},
{
width: 48,
height: 48,
capacity: 174,
blocks: 1,
ecc: 68,
regions_x: 2,
regions_y: 2,
},
{
width: 52,
height: 52,
capacity: 204,
blocks: 2,
ecc: 42,
regions_x: 2,
regions_y: 2,
},
{
width: 64,
height: 64,
capacity: 280,
blocks: 2,
ecc: 56,
regions_x: 4,
regions_y: 4,
},
{
width: 72,
height: 72,
capacity: 368,
blocks: 4,
ecc: 36,
regions_x: 4,
regions_y: 4,
},
{
width: 80,
height: 80,
capacity: 456,
blocks: 4,
ecc: 48,
regions_x: 4,
regions_y: 4,
},
{
width: 88,
height: 88,
capacity: 576,
blocks: 4,
ecc: 56,
regions_x: 4,
regions_y: 4,
},
{
width: 96,
height: 96,
capacity: 696,
blocks: 4,
ecc: 68,
regions_x: 4,
regions_y: 4,
},
{
width: 104,
height: 104,
capacity: 816,
blocks: 6,
ecc: 56,
regions_x: 4,
regions_y: 4,
},
{
width: 120,
height: 120,
capacity: 1050,
blocks: 6,
ecc: 68,
regions_x: 6,
regions_y: 6,
},
{
width: 132,
height: 132,
capacity: 1304,
blocks: 8,
ecc: 62,
regions_x: 6,
regions_y: 6,
},
{
width: 144,
height: 144,
capacity: 1558,
blocks: 10,
ecc: 62,
regions_x: 6,
regions_y: 6,
},
{
width: 18,
height: 8,
capacity: 5,
blocks: 1,
ecc: 7,
regions_x: 1,
regions_y: 1,
},
{
width: 32,
height: 8,
capacity: 10,
blocks: 1,
ecc: 11,
regions_x: 2,
regions_y: 1,
},
{
width: 26,
height: 12,
capacity: 16,
blocks: 1,
ecc: 14,
regions_x: 1,
regions_y: 1,
},
{
width: 36,
height: 12,
capacity: 22,
blocks: 1,
ecc: 18,
regions_x: 2,
regions_y: 1,
},
{
width: 36,
height: 16,
capacity: 32,
blocks: 1,
ecc: 24,
regions_x: 2,
regions_y: 1,
},
{
width: 48,
height: 16,
capacity: 49,
blocks: 1,
ecc: 28,
regions_x: 2,
regions_y: 1,
},
]
///|
let dmre_sizes : Array[Size] = [
{
width: 48,
height: 8,
capacity: 18,
blocks: 1,
ecc: 15,
regions_x: 2,
regions_y: 1,
},
{
width: 64,
height: 8,
capacity: 24,
blocks: 1,
ecc: 18,
regions_x: 4,
regions_y: 1,
},
{
width: 80,
height: 8,
capacity: 32,
blocks: 1,
ecc: 22,
regions_x: 4,
regions_y: 1,
},
{
width: 96,
height: 8,
capacity: 38,
blocks: 1,
ecc: 28,
regions_x: 4,
regions_y: 1,
},
{
width: 120,
height: 8,
capacity: 49,
blocks: 1,
ecc: 32,
regions_x: 6,
regions_y: 1,
},
{
width: 144,
height: 8,
capacity: 63,
blocks: 1,
ecc: 36,
regions_x: 6,
regions_y: 1,
},
{
width: 64,
height: 12,
capacity: 43,
blocks: 1,
ecc: 27,
regions_x: 4,
regions_y: 1,
},
{
width: 88,
height: 12,
capacity: 64,
blocks: 1,
ecc: 36,
regions_x: 4,
regions_y: 1,
},
{
width: 64,
height: 16,
capacity: 62,
blocks: 1,
ecc: 36,
regions_x: 4,
regions_y: 1,
},
{
width: 36,
height: 20,
capacity: 44,
blocks: 1,
ecc: 28,
regions_x: 2,
regions_y: 1,
},
{
width: 44,
height: 20,
capacity: 56,
blocks: 1,
ecc: 34,
regions_x: 2,
regions_y: 1,
},
{
width: 64,
height: 20,
capacity: 84,
blocks: 1,
ecc: 42,
regions_x: 4,
regions_y: 1,
},
{
width: 48,
height: 22,
capacity: 72,
blocks: 1,
ecc: 38,
regions_x: 2,
regions_y: 1,
},
{
width: 48,
height: 24,
capacity: 80,
blocks: 1,
ecc: 41,
regions_x: 2,
regions_y: 1,
},
{
width: 64,
height: 24,
capacity: 108,
blocks: 1,
ecc: 46,
regions_x: 4,
regions_y: 1,
},
{
width: 40,
height: 26,
capacity: 70,
blocks: 1,
ecc: 38,
regions_x: 2,
regions_y: 1,
},
{
width: 48,
height: 26,
capacity: 90,
blocks: 1,
ecc: 42,
regions_x: 2,
regions_y: 1,
},
{
width: 64,
height: 26,
capacity: 118,
blocks: 1,
ecc: 50,
regions_x: 4,
regions_y: 1,
},
]
///|
fn select_size(needed : Int, options : EncodeOptions) -> Size raise EncodeError {
if needed < 0 {
raise CapacityExceeded
}
let pool = match options.shape {
WithDmre | Dmre | Fixed(_, _) => sizes + dmre_sizes
_ => sizes
}
let candidates = pool.filter(fn(s) {
match options.shape {
Square => s.width == s.height
Rectangle => s.width != s.height
Any | WithDmre => true
Dmre =>
dmre_sizes
.iter()
.any(fn(d) { d.width == s.width && d.height == s.height })
Fixed(w, h) => s.width == w && s.height == h
}
})
if candidates.is_empty() {
raise UnsupportedSize
}
let mut best : Size? = None
for s in candidates {
if s.capacity >= needed {
match best {
None => best = Some(s)
Some(b) => if s.capacity < b.capacity { best = Some(s) }
}
}
}
match best {
Some(s) => s
None => raise CapacityExceeded
}
}