use crate::util::{b2s};
use std::io;
use std::io::Write;
use std::ops::{Index, IndexMut};
use std::str;
pub struct FuseArray {
v: Vec<bool>,
w: usize,
pub dev_name_str: Option<String>,
}
impl FuseArray {
pub fn get(&self, x: usize, y: usize) -> bool {
self.v[y * self.w + x]
}
pub fn set(&mut self, x: usize, y: usize, val: bool) {
self.v[y * self.w + x] = val;
}
pub fn dim(&self) -> (usize, usize) {
(self.w, self.v.len() / self.w)
}
pub fn from_file_contents(in_bytes: &[u8]) -> Result<Self, &'static str> {
let mut v = Vec::with_capacity(in_bytes.len());
let mut w = None;
let mut dev_name_str = None;
let in_str = str::from_utf8(in_bytes);
if in_str.is_err() {
return Err("invalid characters in crbit");
}
for l in in_str.unwrap().split('\n') {
let l = l.trim_matches(|c| c == ' ' || c == '\r' || c == '\n');
if l.len() == 0 {
continue;
}
if l.starts_with("// DEVICE ") {
dev_name_str = Some(l["// DEVICE ".len()..].to_owned());
} else if !l.starts_with("//") {
if w.is_none() {
w = Some(l.len());
}
for c in l.chars() {
match c {
'0' => v.push(false),
'1' => v.push(true),
_ => return Err("invalid character in crbit"),
}
}
}
}
if w.is_none() {
return Err("crbit contained no data");
}
Ok(FuseArray {
v,
w: w.unwrap(),
dev_name_str
})
}
pub fn from_dim(w: usize, h: usize) -> Self {
FuseArray {
w,
v: vec![false; w*h],
dev_name_str: None,
}
}
pub fn write_to_writer<W: Write>(&self, mut writer: W) -> Result<(), io::Error> {
write!(writer, "// crbit native bitstream file written by xc2bit\n")?;
write!(writer, "// https://github.com/azonenberg/openfpga\n\n")?;
if let Some(ref dev_name) = self.dev_name_str {
write!(writer, "// DEVICE {}\n\n", dev_name)?;
}
let (w, h) = self.dim();
for y in 0..h {
for x in 0..w {
write!(writer, "{}", b2s(self.get(x, y)))?;
}
write!(writer, "\n")?;
}
write!(writer, "\n")?;
Ok(())
}
}
impl Index<(usize, usize)> for FuseArray {
type Output = bool;
fn index(&self, coords: (usize, usize)) -> &bool {
&self.v[coords.1 * self.w + coords.0]
}
}
impl IndexMut<(usize, usize)> for FuseArray {
fn index_mut(&mut self, coords: (usize, usize)) -> &mut bool {
&mut self.v[coords.1 * self.w + coords.0]
}
}