Finish pass of macro conversion, continue docs

master
Sameer Puri 5 years ago
parent b89849555f
commit f7e037cfdd

250
Cargo.lock generated

@ -2,10 +2,10 @@
# It is not intended for manual editing.
[[package]]
name = "aho-corasick"
version = "0.7.10"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -13,37 +13,39 @@ name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "arrayvec"
version = "0.5.1"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "atty"
version = "0.2.14"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"hermit-abi 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "autocfg"
version = "1.0.0"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bitflags"
version = "1.2.1"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cfg-if"
version = "0.1.10"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -52,63 +54,55 @@ version = "2.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "env_logger"
version = "0.7.1"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
"humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "euclid"
version = "0.20.8"
version = "0.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "float-cmp"
version = "0.5.3"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "hermit-abi"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "humantime"
version = "1.3.0"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.68"
version = "0.2.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -116,30 +110,35 @@ name = "log"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lyon_geom"
version = "0.15.1"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.20.8 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "memchr"
version = "2.3.3"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "nodrop"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "num-traits"
version = "0.2.11"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -148,7 +147,7 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"paste-impl 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro-hack 0.5.14 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro-hack 0.5.15 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -156,15 +155,31 @@ name = "paste-impl"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro-hack 0.5.14 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro-hack 0.5.15 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "phf"
version = "0.7.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "phf_shared"
version = "0.7.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "proc-macro-hack"
version = "0.5.14"
version = "0.5.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -177,7 +192,7 @@ dependencies = [
[[package]]
name = "quick-error"
version = "1.2.3"
version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -190,18 +205,18 @@ dependencies = [
[[package]]
name = "regex"
version = "1.3.6"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-syntax"
version = "0.6.17"
version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -214,11 +229,8 @@ dependencies = [
[[package]]
name = "simplecss"
version = "0.2.0"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "siphasher"
@ -240,36 +252,34 @@ name = "svg2gcode"
version = "0.0.1"
dependencies = [
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"lyon_geom 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lyon_geom 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"paste 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"svgdom 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
"uom 0.27.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"svgdom 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
"uom 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "svgdom"
version = "0.18.0"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"roxmltree 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"simplecss 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"simplecss 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"svgtypes 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"xmlwriter 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"svgtypes 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "svgtypes"
version = "0.5.0"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"float-cmp 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"float-cmp 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -284,10 +294,10 @@ dependencies = [
[[package]]
name = "termcolor"
version = "1.1.0"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -295,25 +305,25 @@ name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thread_local"
version = "1.0.1"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "typenum"
version = "1.11.2"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-width"
version = "0.1.7"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -323,11 +333,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "uom"
version = "0.27.0"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"typenum 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -337,7 +347,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.3.8"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -351,10 +361,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-util"
version = "0.1.3"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -363,62 +373,68 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "xmlparser"
version = "0.9.0"
name = "wincolor"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "xmlwriter"
version = "0.1.0"
name = "xmlparser"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada"
"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba"
"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90"
"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875"
"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
"checksum env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
"checksum euclid 0.20.8 (registry+https://github.com/rust-lang/crates.io-index)" = "57d9ae79e19d69ffb5b47b0a744c4215c115dfed4039314c9ca1b8ddc6c333be"
"checksum float-cmp 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75224bec9bfe1a65e2d34132933f2de7fe79900c96a0174307554244ece8150e"
"checksum hermit-abi 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "725cf19794cf90aa94e65050cb4191ff5d8fa87a498383774c47b332e3af952e"
"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)" = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0"
"checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3"
"checksum euclid 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89c879a4e57d6a2785d517b0771ea6857916173debef0102bf81142d36ca9254"
"checksum float-cmp 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7ef4eee449a2818084dad09f4fcd6e6e8932c482d8d94298493226782bb45b5e"
"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114"
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba"
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
"checksum lyon_geom 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76579b1f0a1ab9c3565c48faf951152d772d67ea35292fa9d36a991916b19a21"
"checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
"checksum lyon_geom 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "69589b8844c0b3745cc031a35b62bc33b0fb9e5ba7613756d802c52861dcdb4c"
"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32"
"checksum paste 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "092d791bf7847f70bbd49085489fba25fc2c193571752bff9e36e74e72403932"
"checksum paste-impl 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "406c23fb4c45cc6f68a9bbabb8ec7bd6f8cfcbd17e9e8f72c2460282f8325729"
"checksum proc-macro-hack 0.5.14 (registry+https://github.com/rust-lang/crates.io-index)" = "fcfdefadc3d57ca21cf17990a28ef4c0f7c61383a28cb7604cf4a18e6ede1420"
"checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18"
"checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0"
"checksum proc-macro-hack 0.5.15 (registry+https://github.com/rust-lang/crates.io-index)" = "0d659fe7c6d27f25e9d80a1a094c223f5246f6a6596453e09d7229bf42750b63"
"checksum proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3"
"checksum quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
"checksum quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
"checksum regex 1.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7f6946991529684867e47d86474e3a6d0c0ab9b82d5821e314b1ede31fa3a4b3"
"checksum regex-syntax 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae"
"checksum regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88c3d9193984285d544df4a30c23a4e62ead42edf70a4452ceb76dac1ce05c26"
"checksum regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b143cceb2ca5e56d5671988ef8b15615733e7ee16cd348e064333b251b89343f"
"checksum roxmltree 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "330d8f80a274bc3cb608908ee345970e7e24b96907f1ad69615a498bec57871c"
"checksum simplecss 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "596554e63596d556a0dbd681416342ca61c75f1a45203201e7e77d3fa2fa9014"
"checksum simplecss 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "135685097a85a64067df36e28a243e94a94f76d829087ce0be34eeb014260c0e"
"checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac"
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
"checksum svgdom 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e4ae7d6df72b3a36c0f003f1f8919c96be43d20d7c015f8dcf2f82531a4fc33b"
"checksum svgtypes 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c536faaff1a10837cfe373142583f6e27d81e96beba339147e77b67c9f260ff"
"checksum svgdom 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9ddce601e49ed213b0126ff4172cd9f5f8dba5f1df2277ecbe0e298f9865baba"
"checksum svgtypes 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "444c882c28925ae0585df228a90f9951569588646ceca4753560de93cdd02258"
"checksum syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03"
"checksum termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
"checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e"
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9"
"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
"checksum typenum 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9af116643fb2603767cc7850b2f70b571ae451a2abe795acbf01747dfd33aa70"
"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20"
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
"checksum uom 0.27.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51fc04fb44bcb7806da71885872cb15d123b681e459a476ef8a0bab287bee0cd"
"checksum uom 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3198c29f199fa8a23d732f4aa21ddc4f4d0a257cb0c2a44afea30145ce2575c1"
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4ccfbf554c6ad11084fb7517daca16cfdcaccbdadba4fc336f032a8b12c2ad80"
"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
"checksum wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96f5016b18804d24db43cebf3c77269e7569b8954a8464501c216cc5e070eaa9"
"checksum xmlparser 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ecec95f00fb0ff019153e64ea520f87d1409769db3e8f4db3ea588638a3e1cee"
"checksum xmlwriter 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9"

@ -1,236 +1,343 @@
use core::convert::TryFrom;
use std::io::{self, Write};
/// Fields are the basic unit of GCode.
trait Field {
/// An uppercase letter
const LETTER: char;
/// A number if the field has a fixed number.
const NUMBER: Option<u16>;
/// A fraction if the field has a fixed fraction following a fixed number.
const FRACTION: Option<u16>;
fn from_arguments<'a>(arguments: &[Argument<'a>]) -> Self;
fn into_arguments<'a>(&'a self) -> Vec<Argument<'a>>;
/// Collapses GCode words into higher-level commands
/// Relies on the first word being a command.
pub struct CommandVec {
pub inner: Vec<Word>,
}
/// Arguments, described by a letter and a value, belong to a field.
pub struct Argument<'a> {
letter: char,
value: &'a str,
impl Default for CommandVec {
fn default() -> Self {
Self {
inner: vec![]
}
}
}
impl IntoIterator for CommandVec {
type Item = Command;
type IntoIter = CommandVecIntoIterator;
fn into_iter(self) -> Self::IntoIter {
CommandVecIntoIterator {
vec: self,
index: 0,
}
}
}
pub struct CommandVecIntoIterator {
vec: CommandVec,
index: usize,
}
impl Iterator for CommandVecIntoIterator {
type Item = Command;
fn next(&mut self) -> Option<Self::Item> {
if self.vec.inner.len() == self.index {
return None;
}
let mut i = self.index + 1;
while i < self.vec.inner.len() {
if CommandWord::is_command(&self.vec.inner[i]) {
break;
}
i += 1;
}
Command::try_from(&self.vec.inner[self.index..i]).ok()
}
}
/// Fundamental unit of GCode: a value preceded by a descriptive letter.
/// A float is used here to encompass all the possible variations of a value.
/// Some flavors of GCode may allow strings, but that is currently not supported.
#[derive(Clone, PartialEq, Debug)]
pub struct Word {
pub letter: char,
pub value: f64,
}
#[macro_export]
macro_rules! command {
($commandWord: expr, {$($argument: ident : $value: expr,)*}) => {
paste::expr! (Command::new($commandWord, vec![$(Word {
letter: stringify!([<$argument:upper>]).chars().next().unwrap(),
value: $value as f64,
},)*]))
};
}
macro_rules! field {
($(#[$outer:meta])* $fieldName: ident {$letter: pat, $number: pat, $fraction: pat, {$($(#[$inner:meta])* $argument: ident : $type: ty), *} }) => {
$(#[$outer])*
struct $fieldName {
macro_rules! commands {
($($(#[$outer:meta])* $commandName: ident {$letter: pat, $number: pat, $fraction: pat, {$($(#[$inner:meta])* $argument: ident), *} },)*) => {
/// Commands are the operational unit of GCode
/// They consist of an identifying word followed by arguments
#[derive(Clone, PartialEq)]
pub struct Command {
command_word: CommandWord,
arguments: Vec<Word>
}
paste::item! {
impl Command {
pub fn new(command_word: CommandWord, mut arguments: Vec<Word>) -> Self {
Self {
command_word: command_word.clone(),
arguments: arguments.drain(..).filter(|w| {
match command_word {
$(CommandWord::$commandName => match w.letter.to_lowercase() {
$($argument => true,)*
_ => false
},)*
_ => false
}
}).collect()
}
}
pub fn push(&mut self, argument: Word) {
match self.command_word {
$(CommandWord::$commandName => match argument.letter.to_lowercase() {
$($argument => {
self.arguments.push(argument);
})*
_ => {}
},)*
_ => {}
}
}
}
}
paste::item! {
impl Into<Vec<Word>> for Command {
fn into(self) -> Vec<Word> {
let mut args = self.arguments;
args.insert(0, self.command_word.into());
args
}
}
}
paste::item! {
impl TryFrom<&[Word]> for Command {
type Error = ();
fn try_from(words: &[Word]) -> Result<Self, ()> {
let command_word = CommandWord::try_from(&words[0])?;
let mut arguments = Vec::with_capacity(words.len() - 1);
for i in 1..words.len() {
match command_word {
$(CommandWord::$commandName => match words[i].letter.to_lowercase() {
$($argument => {
arguments.push(words[i].clone());
})*
_ => {}
},)*
_ => {}
}
}
Ok(Self {
command_word,
arguments
})
}
}
}
#[derive(Clone, PartialEq, Eq)]
pub enum CommandWord {
$(
$(#[$inner])*
$argument: Option<$type>,
$(#[$outer])*
$commandName,
)*
/// A comment is a special command: it is a semicolon followed by text until the end of the line
Comment(Box<String>),
/// Letter N followed by an integer (with no sign) between 0 and 99999 written with no more than five digits
LineNumber(u16),
/// Byte-sized checksums are used by some GCode generators at the end of each line
Checksum(u8),
}
paste::item! {
impl Field for $fieldName {
const LETTER: char = $letter;
const NUMBER: Option<u16> = $number;
const FRACTION: Option<u16> = $fraction;
fn from_arguments<'a>(arguments: &[Argument<'a>]) -> Self {
let mut field = Self {
$($argument: None,)*
impl CommandWord {
pub fn is_command(word: &Word) -> bool {
let number = word.value as u16;
let fraction_numeric =
f64::from_bits(word.value.fract().to_bits() & 0x00_00_FF_FF_FF_FF_FF_FF) as u16;
let fraction = if fraction_numeric == 0 {
None
} else {
Some(fraction_numeric)
};
for arg in arguments.iter() {
$(if arg.letter == stringify!([<$argument:upper>]).chars().next().unwrap() {
field.$argument = Some(arg.value.parse().unwrap());
})*
match (word.letter, number, fraction) {
$(($letter, $number, $fraction) => true,)*
('*', _checksum, None) => true,
('N', _line_number, None) => true,
(_, _, _) => false
}
field
}
fn into_arguments<'a>(&'a self) -> Vec<Argument<'a>> {
let mut args = vec![];
$(
if let Some(value) = self.$argument {
args.push(Argument {
letter: stringify!([<$argument:upper>]).chars().next().unwrap(),
value: &value.to_string()
});
}
}
paste::item! {
impl TryFrom<&Word> for CommandWord {
type Error = ();
fn try_from(word: &Word) -> Result<Self, ()> {
let number = word.value as u16;
let fraction_numeric =
f64::from_bits(word.value.fract().to_bits() & 0x00_00_FF_FF_FF_FF_FF_FF) as u16;
let fraction = if fraction_numeric == 0 {
None
} else {
Some(fraction_numeric)
};
match (word.letter, number, fraction) {
$(($letter, $number, $fraction) => Ok(Self::$commandName),)*
('*', checksum, None) => Ok(Self::Checksum(checksum as u8)),
('N', line_number, None) => Ok(Self::LineNumber(line_number)),
(_, _, _) => Err(())
}
}
}
}
paste::item!{
impl Into<Word> for CommandWord {
fn into(self) -> Word {
match self {
$(
Self::$commandName {} => Word {
letter: $letter,
// TODO: fix fraction
value: $number as f64 + ($fraction.unwrap_or(0) as f64)
},
)*
Self::Checksum(value) => Word {
letter: '*',
value: value as f64
},
Self::LineNumber(value) => Word {
letter: 'N',
value: value as f64
},
Self::Comment(_string) => Word {
letter: ';',
value: 0.0
}
)*
args
}
}
}
}
};
}
field!(
/// Moves the head at the fastest possible speed to the desired speed.
/// Never enter a cut with rapid positioning.
/// Some older machines may "dog leg" rapid positioning, moving one axis at a time.
commands!(
/// Moves the head at the fastest possible speed to the desired speed
/// Never enter a cut with rapid positioning
/// Some older machines may "dog leg" rapid positioning, moving one axis at a time
RapidPositioning {
'G', Some(0), None, {
x: f64,
y: f64,
z: f64,
e: f64,
f: f64,
h: f64,
r: f64,
s: f64,
a: f64,
b: f64,
c: f64
}
});
field!(
'G', 0, None, {
x,
y,
z,
e,
f,
h,
r,
s,
a,
b,
c
}
},
/// Typically used for "cutting" motion
LinearInterpolation {
'G', Some(1), None, {
x: f64,
y: f64,
z: f64,
e: f64,
f: f64,
h: f64,
r: f64,
s: f64,
a: f64,
b: f64,
c: f64
}
});
field!(
/// This will keep the axes unmoving for the period of time in seconds specified by the P number.
'G', 1, None, {
x,
y,
z,
e,
f,
h,
r,
s,
a,
b,
c
}
},
/// This will keep the axes unmoving for the period of time in seconds specified by the P number
Dwell {
'G', Some(4), None, {
/// Time in seconds
p: f64
}
});
field!(
'G', 4, None, {
/// Time in seconds
p
}
},
/// Use inches for length units
UnitsInches {
'G', Some(20), None, {}
});
field!(
'G', 20, None, {}
},
/// Use millimeters for length units
UnitsMillimeters {
'G', Some(21), None, {}
});
field!(
'G', 21, None, {}
},
/// In absolute distance mode, axis numbers usually represent positions in terms of the currently active coordinate system.
AbsoluteDistanceMode {
'G', Some(90), None, {}
});
field!(
/// In incremental distance mode, axis numbers usually represent increments from the current values of the numbers.
IncrementalDistanceMode {
'G', Some(91), None, {}
});
field!(
'G', 90, None, {}
},
/// In relative distance mode, axis numbers usually represent increments from the current values of the numbers
RelativeDistanceMode {
'G', 91, None, {}
},
/// Start spinning the spindle clockwise with speed `p`
StartSpindleClockwise {
'M', Some(3), None, {
'M', 3, None, {
/// Speed
p: f64
p
}
}
);
field!(
},
/// Start spinning the spindle counterclockwise with speed `p`
StartSpindleCounterclockwise {
'M', Some(4), None, {
'M', 4, None, {
/// Speed
p: f64
p
}
}
);
field!(
},
/// Stop spinning the spindle
StopSpindle {
'M', Some(5), None, {}
}
);
field!(
'M', 5, None, {}
},
/// Signals the end of a program
ProgramEnd {
'M', Some(20), None, {}
}
'M', 20, None, {}
},
);
/// Checksums are used by some GCode generators at the end of each line
struct Checksum {
/// Checksum value
value: u8,
}
impl Field for Checksum {
const LETTER: char = '*';
const NUMBER: Option<u16> = None;
const FRACTION: Option<u16> = None;
fn from_arguments<'a>(arguments: &[Argument<'a>]) -> Self {
Self { value: 0 }
}
fn into_arguments(&self) -> Vec<Argument> {
vec![]
}
}
/// A line number is the letter N followed by an integer (with no sign) between 0 and 99999 written with no more than five digits
struct LineNumber {
/// Line number
value: u16,
}
impl Field for LineNumber {
const LETTER: char = 'N';
const NUMBER: Option<u16> = None;
const FRACTION: Option<u16> = None;
fn from_arguments<'a>(arguments: &[Argument<'a>]) -> Self {
Self { value: 0 }
}
fn into_arguments(&self) -> Vec<Argument> {
vec![]
}
}
/// Rudimentary regular expression GCode validator.
/// Rudimentary regular expression GCode validator
pub fn validate_gcode(gcode: &&str) -> bool {
use regex::Regex;
let re = Regex::new(r##"^(?:(?:%|\(.*\)|(?:[A-Z^E^U][+-]?\d+(?:\.\d*)?))\h*)*$"##).unwrap();
gcode.lines().all(|line| re.is_match(line))
}
// TODO: Documentation
// TODO: This function is too large
pub fn program2gcode<W: Write>(p: &Program, mut w: W) -> io::Result<()> {
let mut last_feedrate: Option<f64> = None;
let letter = '*';
let number = Some(0);
let fraction = None;
macro_rules! match_field {
($($fieldName: ident)*) => {
match (letter, number, fraction) {
$(($fieldName::LETTER, $fieldName::NUMBER, $fieldName::FRACTION) => {
Some($fieldName::from_arguments(arguments))
},)*
_ => {None}
/// Writes a GCode program (or sequence) to a Writer
pub fn program2gcode<W: Write>(program: Vec<Command>, mut w: W) -> io::Result<()> {
for command in program.into_iter() {
match &command.command_word {
CommandWord::Comment(string) => {
writeln!(w, ";{}", string)?;
},
_other => {
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, "")?;
}
};
}
for code in p.iter() {
match_field!(LineNumber);
}
}
}
Ok(())
}

@ -1,3 +1,4 @@
#[macro_use]
use crate::code::*;
//// Direction of the machine spindle
@ -22,44 +23,29 @@ pub enum Distance {
}
/// Generic machine state simulation, assuming nothing is known about the machine when initialized.
/// This is used to reduce output GCode verbosity and run repetitive actions.
pub struct Machine {
tool_state: Option<Tool>,
distance_mode: Option<Distance>,
pub tool_on_action: Vec<GCode>,
pub tool_off_action: Vec<GCode>,
tool_on_action: Vec<Command>,
tool_off_action: Vec<Command>,
}
/// Assigns reasonable default settings that apply to most gcode applications.
impl Machine {
fn default() -> Self {
/// Create a generic machine, given a tool on/off GCode sequence.
pub fn new(tool_on_action: CommandVec, tool_off_action: CommandVec) -> Self {
Self {
tool_state: None,
distance_mode: None,
tool_on_action: vec![
GCode::Dwell { p: 0.1 },
GCode::StartSpindle {
d: Direction::Clockwise,
s: 70.0,
},
GCode::Dwell { p: 0.1 },
],
tool_off_action: vec![
GCode::Dwell { p: 0.1 },
GCode::StartSpindle {
d: Direction::Clockwise,
s: 50.0,
},
GCode::Dwell { p: 0.1 },
],
tool_on_action: tool_on_action.into_iter().collect(),
tool_off_action: tool_off_action.into_iter().collect()
}
}
}
// TODO: Documentation
// Implements the state machine functions to export Gcode.
impl Machine {
// Outputs gcode to turn the tool on.
pub fn tool_on(&mut self) -> Vec<GCode> {
/// Output gcode to turn the tool on.
pub fn tool_on(& mut self) -> Vec<Command> {
if self.tool_state == Some(Tool::Off) || self.tool_state == None {
self.tool_state = Some(Tool::On);
self.tool_on_action.clone()
@ -68,8 +54,8 @@ impl Machine {
}
}
// Outputs gcode to turn the tool off.
pub fn tool_off(&mut self) -> Vec<GCode> {
/// Output gcode to turn the tool off.
pub fn tool_off(&mut self) -> Vec<Command> {
if self.tool_state == Some(Tool::On) || self.tool_state == None {
self.tool_state = Some(Tool::Off);
self.tool_off_action.clone()
@ -77,31 +63,21 @@ impl Machine {
vec![]
}
}
// Outputs gcode for how distance should be measured: relative or absolute.
pub fn distance(&mut self, is_absolute: bool) -> Vec<GCode> {
if is_absolute {
self.absolute()
} else {
self.relative()
}
}
// Outputs gcode command to use absolute motion
pub fn absolute(&mut self) -> Vec<GCode> {
/// Output relative distance field if mode was absolute or unknown.
pub fn absolute(&mut self) -> Vec<Command> {
if self.distance_mode == Some(Distance::Relative) || self.distance_mode == None {
self.distance_mode = Some(Distance::Absolute);
vec![GCode::DistanceMode(Distance::Absolute)]
vec![command!(CommandWord::AbsoluteDistanceMode, {})]
} else {
vec![]
}
}
/// Set the distance mode to relative
pub fn relative(&mut self) -> Vec<GCode> {
/// Output absolute distance field if mode was relative or unknown.
pub fn relative(&mut self) -> Vec<Command> {
if self.distance_mode == Some(Distance::Absolute) || self.distance_mode == None {
self.distance_mode = Some(Distance::Relative);
vec![GCode::DistanceMode(Distance::Relative)]
vec![command!(CommandWord::RelativeDistanceMode, {})]
} else {
vec![]
}

@ -17,6 +17,7 @@ use std::io::{self, Read};
use lyon_geom::{euclid, math};
use svgdom::{AttributeId, AttributeValue, ElementId, ElementType, PathSegment};
#[macro_use]
mod code;
mod machine;
mod turtle;
@ -60,7 +61,7 @@ fn main() -> io::Result<()> {
};
let mut opts = ProgramOptions::default();
let mut mach = Machine::default();
let mut mach = Machine::new(CommandVec::default(), CommandVec::default());
if let Some(tolerance) = matches.value_of("tolerance").and_then(|x| x.parse().ok()) {
opts.tolerance = tolerance;
@ -72,17 +73,17 @@ fn main() -> io::Result<()> {
opts.dpi = dpi;
}
if let Some(tool_on_action) = matches.value_of("tool_on_action").filter(validate_gcode) {
mach.tool_on_action = vec![GCode::Raw(Box::new(tool_on_action.to_string()))];
}
if let Some(tool_off_action) = matches.value_of("tool_off_action").filter(validate_gcode) {
mach.tool_off_action = vec![GCode::Raw(Box::new(tool_off_action.to_string()))];
}
// if let Some(tool_on_action) = matches.value_of("tool_on_action").filter(validate_gcode) {
// mach.tool_on_action = vec![GCode::Raw(Box::new(tool_on_action.to_string()))];
// }
// if let Some(tool_off_action) = matches.value_of("tool_off_action").filter(validate_gcode) {
// mach.tool_off_action = vec![GCode::Raw(Box::new(tool_off_action.to_string()))];
// }
let doc = svgdom::Document::from_str(&input).expect("Invalid or unsupported SVG file");
let prog = svg2program(&doc, opts, mach);
program2gcode(&prog, File::create("out.gcode")?)
program2gcode(prog, File::create("out.gcode")?)
}
// TODO: Documentation
@ -105,15 +106,16 @@ impl Default for ProgramOptions {
// TODO: Documentation
// TODO: This function is much too large
fn svg2program(doc: &svgdom::Document, opts: ProgramOptions, mach: Machine) -> Program {
let mut p = Program::default();
let mut t = Turtle::from(mach);
fn svg2program(doc: &svgdom::Document, opts: ProgramOptions, mach: Machine) -> Vec<Command> {
let mut p = vec![];
let mut t = Turtle::new(mach);
let mut namestack: Vec<String> = vec![];
p.push(GCode::UnitsMillimeters);
p += t.mach.tool_off().into();
p += t.move_to(true, 0.0, 0.0).into();
p.push(command!(CommandWord::UnitsMillimeters, {}));
p.append(&mut t.mach.tool_off());
p.append(&mut
t.move_to(true, 0.0, 0.0));
for edge in doc.root().traverse() {
let (node, is_start) = match edge {
@ -149,7 +151,7 @@ fn svg2program(doc: &svgdom::Document, opts: ProgramOptions, mach: Machine) -> P
}
if let ElementId::G = id {
if is_start {
namestack.push(node.id().to_string());
namestack.push(format!("{}#{}", node.tag_name(), node.id().to_string()));
} else {
namestack.pop();
}
@ -180,13 +182,16 @@ fn svg2program(doc: &svgdom::Document, opts: ProgramOptions, mach: Machine) -> P
let prefix: String =
namestack.iter().fold(String::new(), |mut acc, name| {
acc += name;
acc += "-->";
acc += " => ";
acc
});
p.push(GCode::Comment(Box::new(prefix + &node.id())));
p.push(command!(
CommandWord::Comment(Box::new(prefix + &node.id())),
{}
));
t.reset();
for segment in path.iter() {
let segment_gcode = match segment {
p.append(&mut match segment {
PathSegment::MoveTo { abs, x, y } => t.move_to(*abs, *x, *y),
PathSegment::ClosePath { abs } => {
// Ignore abs, should have identical effect: https://www.w3.org/TR/SVG/paths.html#PathDataClosePathCommand
@ -273,8 +278,7 @@ fn svg2program(doc: &svgdom::Document, opts: ProgramOptions, mach: Machine) -> P
opts.feedrate,
opts.tolerance,
),
};
p += segment_gcode.into();
});
}
}
}
@ -285,13 +289,13 @@ fn svg2program(doc: &svgdom::Document, opts: ProgramOptions, mach: Machine) -> P
}
}
p += t.mach.tool_off().into();
p += t.mach.absolute().into();
p.push(GCode::RapidPositioning {
x: 0.0.into(),
y: 0.0.into(),
});
p.push(GCode::ProgramEnd);
p.append(&mut t.mach.tool_off());
p.append(&mut t.mach.absolute());
p.push(command!(CommandWord::RapidPositioning, {
x: 0.0,
y: 0.0,
}));
p.push(command!(CommandWord::ProgramEnd, {}));
p
}
@ -313,18 +317,3 @@ fn length_to_mm(l: svgdom::Length, dpi: f64) -> f64 {
length.get::<millimeter>()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_svg2program() {
panic!("TODO: basic passing test");
}
#[test]
fn test_length_to_mm() {
panic!("TODO: basic passing test");
}
}

@ -1,14 +1,12 @@
/// TODO: Documentation
use crate::code::GCode;
use crate::code::*;
use crate::machine::Machine;
use lyon_geom::euclid::{Angle, default::Transform2D};
use lyon_geom::euclid::{default::Transform2D, Angle};
use lyon_geom::math::{point, vector, F64Point};
use lyon_geom::{ArcFlags, CubicBezierSegment, QuadraticBezierSegment, SvgArc};
/// Turtle graphics simulator for paths that outputs the GCode enum
/// representation for each operation. Handles trasforms, scaling, position
/// offsets, etc. See https://www.w3.org/TR/SVG/paths.html
/// Turtle graphics simulator for paths that outputs the gcode representation for each operation.
/// Handles trasforms, scaling, position, offsets, etc. See https://www.w3.org/TR/SVG/paths.html
pub struct Turtle {
curpos: F64Point,
initpos: F64Point,
@ -19,33 +17,25 @@ pub struct Turtle {
prev_ctrl: Option<F64Point>,
}
// TODO: Documentation
impl Default for Turtle {
fn default() -> Self {
impl Turtle {
/// Create a turtle at the origin with no scaling or transform
pub fn new(machine: Machine) -> Self {
Self {
curpos: point(0.0, 0.0),
initpos: point(0.0, 0.0),
curtran: Transform2D::identity(),
scaling: None,
transtack: vec![],
mach: Machine::default(),
mach: machine,
prev_ctrl: None,
}
}
}
// TODO: Documentation
impl From<Machine> for Turtle {
fn from(m: Machine) -> Self {
let mut t = Self::default();
t.mach = m;
t
}
}
// TODO: Documentation
impl Turtle {
pub fn move_to<X, Y>(&mut self, abs: bool, x: X, y: Y) -> Vec<GCode>
/// Move the turtle to the given absolute/relative coordinates in the current transform
/// https://www.w3.org/TR/SVG/paths.html#PathDataMovetoCommands
pub fn move_to<X, Y>(&mut self, abs: bool, x: X, y: Y) -> Vec<Command>
where
X: Into<Option<f64>>,
Y: Into<Option<f64>>,
@ -67,21 +57,41 @@ impl Turtle {
self.initpos = to;
self.prev_ctrl = None;
vec![
self.mach.tool_off(),
self.mach.absolute(),
vec![GCode::RapidPositioning {
x: to.x.into(),
y: to.y.into(),
}],
]
.drain(..)
.flatten()
.collect()
self.mach
.tool_off()
.iter()
.chain(self.mach.absolute().iter())
.chain(std::iter::once(&command!(CommandWord::RapidPositioning, {
x : to.x as f64,
y : to.y as f64,
})))
.map(Clone::clone)
.collect()
}
fn linear_interpolation(x: f64, y: f64, z: Option<f64>, f: Option<f64>) -> Command {
let mut linear_interpolation = command!(CommandWord::LinearInterpolation, {
x: x,
y: y,
});
if let Some(z) = z {
linear_interpolation.push(Word {
letter: 'Z',
value: z,
});
}
if let Some(f) = f {
linear_interpolation.push(Word {
letter: 'F',
value: f,
});
}
linear_interpolation
}
// TODO: Documentation
pub fn close<Z, F>(&mut self, z: Z, f: F) -> Vec<GCode>
/// Close an SVG path, cutting back to its initial position
/// https://www.w3.org/TR/SVG/paths.html#PathDataClosePathCommand
pub fn close<Z, F>(&mut self, z: Z, f: F) -> Vec<Command>
where
Z: Into<Option<f64>>,
F: Into<Option<f64>>,
@ -96,23 +106,24 @@ impl Turtle {
return vec![];
}
self.curpos = self.initpos;
vec![
self.mach.tool_on(),
self.mach.absolute(),
vec![GCode::LinearInterpolation {
x: self.initpos.x.into(),
y: self.initpos.y.into(),
z: z.into(),
f: f.into(),
}],
]
.drain(..)
.flatten()
.collect()
self.mach
.tool_on()
.iter()
.chain(self.mach.absolute().iter())
.chain(std::iter::once(&Self::linear_interpolation(
self.initpos.x.into(),
self.initpos.y.into(),
z.into(),
f.into(),
)))
.map(Clone::clone)
.collect()
}
// TODO: Documentation
pub fn line<X, Y, Z, F>(&mut self, abs: bool, x: X, y: Y, z: Z, f: F) -> Vec<GCode>
/// Draw a line from the current position in the current transform to the specified position
/// https://www.w3.org/TR/SVG/paths.html#PathDataLinetoCommands
pub fn line<X, Y, Z, F>(&mut self, abs: bool, x: X, y: Y, z: Z, f: F) -> Vec<Command>
where
X: Into<Option<f64>>,
Y: Into<Option<f64>>,
@ -135,41 +146,45 @@ impl Turtle {
self.curpos = to;
self.prev_ctrl = None;
vec![
self.mach.tool_on(),
self.mach.absolute(),
vec![GCode::LinearInterpolation {
x: to.x.into(),
y: to.y.into(),
z: z.into(),
f: f.into(),
}],
]
.drain(..)
.flatten()
.collect()
self.mach
.tool_on()
.iter()
.chain(self.mach.absolute().iter())
.chain(std::iter::once(&Self::linear_interpolation(
to.x.into(),
to.y.into(),
z.into(),
f.into(),
)))
.map(Clone::clone)
.collect()
}
/// Draw a cubic bezier curve segment
/// The public bezier functions call this command after converting to a cubic bezier segment
/// https://www.w3.org/TR/SVG/paths.html#PathDataCubicBezierCommands
fn bezier<Z: Into<Option<f64>>, F: Into<Option<f64>>>(
&mut self,
cbs: CubicBezierSegment<f64>,
tolerance: f64,
z: Z,
f: F,
) -> Vec<GCode> {
) -> Vec<Command> {
let z = z.into();
let f = f.into();
let last_point = std::cell::Cell::new(self.curpos);
let mut cubic = vec![];
cbs.flattened(tolerance).for_each(|point| {
cubic.push(GCode::LinearInterpolation {
x: point.x.into(),
y: point.y.into(),
z,
f,
});
last_point.set(point);
});
let mut cubic: Vec<Command> = cbs
.flattened(tolerance)
.map(|point| {
last_point.set(point);
Self::linear_interpolation(
point.x.into(),
point.y.into(),
z.into(),
f.into(),
)
})
.collect();
self.curpos = last_point.get();
// See https://www.w3.org/TR/SVG/paths.html#ReflectedControlPoints
self.prev_ctrl = point(
@ -178,14 +193,17 @@ impl Turtle {
)
.into();
vec![self.mach.tool_on(), self.mach.absolute(), cubic]
.drain(..)
.flatten()
self.mach
.tool_on()
.iter()
.chain(self.mach.absolute().iter())
.chain(cubic.iter())
.map(Clone::clone)
.collect()
}
// TODO: Documentation
// TODO: Function too long
/// Draw a cubic curve from the current point to (x, y) with specified control points (x1, y1) and (x2, y2)
/// https://www.w3.org/TR/SVG/paths.html#PathDataCubicBezierCommands
pub fn cubic_bezier<Z, F>(
&mut self,
abs: bool,
@ -198,7 +216,7 @@ impl Turtle {
tolerance: f64,
z: Z,
f: F,
) -> Vec<GCode>
) -> Vec<Command>
where
Z: Into<Option<f64>>,
F: Into<Option<f64>>,
@ -227,7 +245,8 @@ impl Turtle {
self.bezier(cbs, tolerance, z, f)
}
// TODO: Documentation
/// Draw a shorthand/smooth cubic bezier segment, where the first control point was already given
/// https://www.w3.org/TR/SVG/paths.html#PathDataCubicBezierCommands
pub fn smooth_cubic_bezier<Z, F>(
&mut self,
abs: bool,
@ -238,7 +257,7 @@ impl Turtle {
tolerance: f64,
z: Z,
f: F,
) -> Vec<GCode>
) -> Vec<Command>
where
Z: Into<Option<f64>>,
F: Into<Option<f64>>,
@ -265,7 +284,8 @@ impl Turtle {
self.bezier(cbs, tolerance, z, f)
}
// TODO: Documentation
/// Draw a shorthand/smooth cubic bezier segment, where the control point was already given
/// https://www.w3.org/TR/SVG/paths.html#PathDataQuadraticBezierCommands
pub fn smooth_quadratic_bezier<Z, F>(
&mut self,
abs: bool,
@ -274,7 +294,7 @@ impl Turtle {
tolerance: f64,
z: Z,
f: F,
) -> Vec<GCode>
) -> Vec<Command>
where
Z: Into<Option<f64>>,
F: Into<Option<f64>>,
@ -293,7 +313,8 @@ impl Turtle {
self.bezier(qbs.to_cubic(), tolerance, z, f)
}
// TODO: Documentation
/// Draw a quadratic bezier segment
/// https://www.w3.org/TR/SVG/paths.html#PathDataQuadraticBezierCommands
pub fn quadratic_bezier<Z, F>(
&mut self,
abs: bool,
@ -304,7 +325,7 @@ impl Turtle {
tolerance: f64,
z: Z,
f: F,
) -> Vec<GCode>
) -> Vec<Command>
where
Z: Into<Option<f64>>,
F: Into<Option<f64>>,
@ -325,7 +346,8 @@ impl Turtle {
self.bezier(qbs.to_cubic(), tolerance, z, f)
}
// TODO: Documentation
/// Draw an elliptical arc curve
/// https://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands
pub fn elliptical<Z, F>(
&mut self,
abs: bool,
@ -339,7 +361,7 @@ impl Turtle {
z: Z,
f: F,
tolerance: f64,
) -> Vec<GCode>
) -> Vec<Command>
where
Z: Into<Option<f64>>,
F: Into<Option<f64>>,
@ -374,24 +396,29 @@ impl Turtle {
let mut ellipse = vec![];
sarc.for_each_flattened(tolerance, &mut |point: F64Point| {
ellipse.push(GCode::LinearInterpolation {
x: point.x.into(),
y: point.y.into(),
z,
f,
});
ellipse.push(Self::linear_interpolation(
point.x.into(),
point.y.into(),
z.into(),
f.into(),
));
last_point.set(point);
});
self.curpos = last_point.get();
self.prev_ctrl = None;
vec![self.mach.tool_on(), self.mach.absolute(), ellipse]
.drain(..)
.flatten()
self.mach
.tool_on()
.iter()
.chain(self.mach.absolute().iter())
.chain(ellipse.iter())
.map(Clone::clone)
.collect()
}
// TODO: Documentation
/// Push a new scaling-only transform onto the stack
/// This is useful for handling things like the viewBox
/// https://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute
pub fn stack_scaling(&mut self, scaling: Transform2D<f64>) {
self.curtran = self.curtran.post_transform(&scaling);
if let Some(ref current_scaling) = self.scaling {
@ -401,7 +428,9 @@ impl Turtle {
}
}
// TODO: Documentation
/// Push a generic transform onto the stack
/// Could be any valid CSS transform https://drafts.csswg.org/css-transforms-1/#typedef-transform-function
/// https://www.w3.org/TR/SVG/coords.html#InterfaceSVGTransform
pub fn push_transform(&mut self, trans: Transform2D<f64>) {
self.transtack.push(self.curtran);
if let Some(ref scaling) = self.scaling {
@ -415,7 +444,8 @@ impl Turtle {
}
}
// TODO: Documentation
/// Pop a generic transform off the stack, returning to the previous transform state
/// This means that most recent transform went out of scope
pub fn pop_transform(&mut self) {
self.curtran = self
.transtack
@ -423,7 +453,7 @@ impl Turtle {
.expect("popped when no transforms left");
}
// TODO: Documentation
/// Reset the position of the turtle to the origin in the current transform stack
pub fn reset(&mut self) {
self.curpos = point(0.0, 0.0);
self.curpos = self.curtran.transform_point(self.curpos);
@ -431,73 +461,3 @@ impl Turtle {
self.initpos = self.curpos;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_move_to() {
panic!("TODO: basic passing test");
}
#[test]
fn test_close() {
panic!("TODO: basic passing test");
}
#[test]
fn test_line() {
panic!("TODO: basic passing test");
}
#[test]
fn test_bezier() {
panic!("TODO: basic passing test");
}
#[test]
fn test_cubic_bezier() {
panic!("TODO: basic passing test");
}
#[test]
fn test_smooth_cubic_bezier() {
panic!("TODO: basic passing test");
}
#[test]
fn test_smooth_quadratic_bezier() {
panic!("TODO: basic passing test");
}
#[test]
fn test_quadratic_bezier() {
panic!("TODO: basic passing test");
}
#[test]
fn test_elliptical() {
panic!("TODO: basic passing test");
}
#[test]
fn test_stack_scaling() {
panic!("TODO: basic passing test");
}
#[test]
fn test_push_transform() {
panic!("TODO: basic passing test");
}
#[test]
fn test_pop_transform() {
panic!("TODO: basic passing test");
}
#[test]
fn test_reset() {
panic!("TODO: basic passing test");
}
}

Loading…
Cancel
Save