parent
f7e037cfdd
commit
5842b2df0b
@ -0,0 +1,104 @@
|
||||
use core::convert::TryFrom;
|
||||
use std::io::{self, Write};
|
||||
|
||||
#[macro_use]
|
||||
mod spec;
|
||||
pub use spec::*;
|
||||
|
||||
/// Collapses GCode words into higher-level commands
|
||||
pub struct CommandVecIntoIterator {
|
||||
vec: Vec<Word>,
|
||||
index: usize,
|
||||
}
|
||||
|
||||
impl Iterator for CommandVecIntoIterator {
|
||||
type Item = Command;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.vec.len() <= self.index {
|
||||
return None;
|
||||
}
|
||||
let mut i = self.index + 1;
|
||||
while i < self.vec.len() {
|
||||
if CommandWord::is_command(&self.vec[i]) {
|
||||
break;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
let command = Command::try_from(&self.vec[self.index..i]).ok();
|
||||
self.index = i;
|
||||
command
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<Word>> for CommandVecIntoIterator {
|
||||
fn from(vec: Vec<Word>) -> Self {
|
||||
Self { vec, index: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_gcode(gcode: &str) -> Vec<Word> {
|
||||
let mut vec = vec![];
|
||||
let mut in_string = false;
|
||||
let mut letter: Option<char> = None;
|
||||
let mut value_range = 0..0;
|
||||
gcode.char_indices().for_each(|(i, c)| {
|
||||
if (c.is_alphabetic() || c.is_ascii_whitespace()) && !in_string {
|
||||
if let Some(l) = letter {
|
||||
vec.push(Word {
|
||||
letter: l,
|
||||
value: parse_value(&gcode[value_range.clone()]),
|
||||
});
|
||||
letter = None;
|
||||
}
|
||||
if c.is_alphabetic() {
|
||||
letter = Some(c);
|
||||
}
|
||||
value_range = (i + 1)..(i + 1);
|
||||
} else if in_string {
|
||||
value_range = value_range.start..(i + 1);
|
||||
} else {
|
||||
if c == '"' {
|
||||
in_string = !in_string;
|
||||
}
|
||||
value_range = value_range.start..(i + 1);
|
||||
}
|
||||
});
|
||||
if let Some(l) = letter {
|
||||
vec.push(Word {
|
||||
letter: l,
|
||||
value: parse_value(&gcode[value_range.clone()]),
|
||||
});
|
||||
}
|
||||
vec
|
||||
}
|
||||
|
||||
fn parse_value(word: &str) -> Value {
|
||||
if word.starts_with('"') && word.ends_with('"') {
|
||||
Value::String(Box::new(word.to_string()))
|
||||
} else {
|
||||
let index_of_dot = word.find('.');
|
||||
Value::Fractional(
|
||||
word[..index_of_dot.unwrap_or(word.len())]
|
||||
.parse::<u32>()
|
||||
.unwrap(),
|
||||
index_of_dot.map(|j| word[j + 1..].parse::<u32>().unwrap()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Writes a GCode program or sequence to a Writer
|
||||
/// Each command is placed on a separate line
|
||||
pub fn program2gcode<W: Write>(program: Vec<Command>, mut w: W) -> io::Result<()> {
|
||||
for command in program.into_iter() {
|
||||
let words: Vec<Word> = command.into();
|
||||
let mut it = words.iter();
|
||||
if let Some(command_word) = it.next() {
|
||||
write!(w, "{}{}", command_word.letter, command_word.value)?;
|
||||
for word in it {
|
||||
write!(w, " {}{} ", word.letter, word.value)?;
|
||||
}
|
||||
writeln!(w, "")?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in new issue