├── .gitignore ├── cidr-calc ├── example-inputs │ ├── remove_single.txt │ ├── remove_single_v6.txt │ ├── let.txt │ └── remove_single_reverse.txt ├── src │ ├── lib.rs │ ├── syntax.pest │ ├── data.rs │ ├── main.rs │ ├── parser.rs │ └── eval.rs ├── Cargo.toml ├── LICENSE └── Cargo.lock ├── cidr-calc-web ├── .gitignore ├── src │ ├── utils.rs │ └── lib.rs ├── Cargo.toml └── index.html ├── Cargo.toml ├── .github ├── dependabot.yml └── workflows │ └── test.yml ├── README.md └── Cargo.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /cidr-calc/example-inputs/remove_single.txt: -------------------------------------------------------------------------------- 1 | 0.0.0.0/0 - 101.6.6.6/32 -------------------------------------------------------------------------------- /cidr-calc/example-inputs/remove_single_v6.txt: -------------------------------------------------------------------------------- 1 | ::/0 - 2001:da8::666/128 -------------------------------------------------------------------------------- /cidr-calc/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod parser; 2 | pub mod eval; 3 | pub mod data; -------------------------------------------------------------------------------- /cidr-calc-web/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | bin/ 5 | pkg/ 6 | wasm-pack.log 7 | -------------------------------------------------------------------------------- /cidr-calc/example-inputs/let.txt: -------------------------------------------------------------------------------- 1 | let meow = ::/0 2 | let meow_meow = 2001:da8::666/128 3 | meow + meow_meow -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | 3 | members = [ 4 | 'cidr-calc', 5 | 'cidr-calc-web', 6 | ] 7 | resolver = "2" 8 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: cargo 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "08:00" 8 | open-pull-requests-limit: 10 9 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Build and test 2 | 3 | on: 4 | - push 5 | - pull_request 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v4 12 | - name: Install Rust toolchain 13 | uses: actions-rs/toolchain@v1 14 | with: 15 | toolchain: stable 16 | override: true 17 | - name: Build 18 | run: cargo build --verbose 19 | - name: Run tests 20 | run: cargo test --verbose 21 | -------------------------------------------------------------------------------- /cidr-calc-web/src/utils.rs: -------------------------------------------------------------------------------- 1 | pub fn set_panic_hook() { 2 | // When the `console_error_panic_hook` feature is enabled, we can call the 3 | // `set_panic_hook` function at least once during initialization, and then 4 | // we will get better error messages if our code ever panics. 5 | // 6 | // For more details see 7 | // https://github.com/rustwasm/console_error_panic_hook#readme 8 | #[cfg(feature = "console_error_panic_hook")] 9 | console_error_panic_hook::set_once(); 10 | } 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CIDR Calculator 2 | 3 | [![Crates.io Version](https://img.shields.io/crates/v/cidr-calculator)](https://crates.io/crates/cidr-calculator) 4 | 5 | CIDR addition / subtraction calculator. Maybe useful for setting route tables when metrics are not available (e.g. wireguard next-hop) 6 | 7 | ``` 8 | > let univ = ::/0 9 | > univ - 2001:da8::/56 10 | [ 11 | ::/3 12 | 2000::/16 13 | 2001::/21 14 | 2001:800::/22 15 | 2001:c00::/24 16 | 2001:d00::/25 17 | 2001:d80::/27 18 | 2001:da0::/29 19 | 2001:da8:0:100::/56 20 | ... 21 | ``` 22 | -------------------------------------------------------------------------------- /cidr-calc/example-inputs/remove_single_reverse.txt: -------------------------------------------------------------------------------- 1 | 101.6.6.6/32 2 | + 0.0.0.0/2 3 | + 64.0.0.0/3 4 | + 96.0.0.0/6 5 | + 100.0.0.0/8 6 | + 101.0.0.0/14 7 | + 101.4.0.0/15 8 | + 101.6.0.0/22 9 | + 101.6.4.0/23 10 | + 101.6.6.0/30 11 | + 101.6.6.4/31 12 | + 101.6.6.7/32 13 | + 101.6.6.8/29 14 | + 101.6.6.16/28 15 | + 101.6.6.32/27 16 | + 101.6.6.64/26 17 | + 101.6.6.128/25 18 | + 101.6.7.0/24 19 | + 101.6.8.0/21 20 | + 101.6.16.0/20 21 | + 101.6.32.0/19 22 | + 101.6.64.0/18 23 | + 101.6.128.0/17 24 | + 101.7.0.0/16 25 | + 101.8.0.0/13 26 | + 101.16.0.0/12 27 | + 101.32.0.0/11 28 | + 101.64.0.0/10 29 | + 101.128.0.0/9 30 | + 102.0.0.0/7 31 | + 104.0.0.0/5 32 | + 112.0.0.0/4 33 | + 128.0.0.0/1 -------------------------------------------------------------------------------- /cidr-calc-web/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cidr-calculator-web" 3 | version = "0.1.0" 4 | authors = ["Liu Xiaoyi "] 5 | edition = "2021" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "rlib"] 9 | 10 | [features] 11 | default = ["console_error_panic_hook"] 12 | 13 | [dependencies] 14 | wasm-bindgen = "0.2.104" 15 | 16 | # The `console_error_panic_hook` crate provides better debugging of panics by 17 | # logging them with `console.error`. This is great for development, but requires 18 | # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for 19 | # code size when deploying. 20 | console_error_panic_hook = { version = "0.1.7", optional = true } 21 | 22 | cidr-calculator = { path = "../cidr-calc", default-features = false } 23 | -------------------------------------------------------------------------------- /cidr-calc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cidr-calculator" 3 | version = "0.2.0" 4 | edition = "2021" 5 | description = "CIDR addition / subtraction calculator. Maybe useful for setting route tables when metrics are not available (e.g. wireguard next-hop)" 6 | license = "MIT" 7 | repository = "https://github.com/CircuitCoder/cidr-calc" 8 | readme = "../README.md" 9 | 10 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 11 | 12 | [dependencies] 13 | anyhow = "1.0.100" 14 | im = "15.1.0" 15 | pest = "2.8.2" 16 | pest_derive = "2.8.2" 17 | rustyline = { version = "17.0.1", optional = true } 18 | clap = { version = "4.5.48", features = ["derive"], optional = true } 19 | 20 | [features] 21 | default = ["cli"] 22 | cli = ["dep:rustyline", "dep:clap"] 23 | 24 | [[bin]] 25 | name = "cidr-calculator" 26 | required-features = ["cli"] 27 | -------------------------------------------------------------------------------- /cidr-calc/src/syntax.pest: -------------------------------------------------------------------------------- 1 | WHITESPACE = _{ " " | "\n" | "\r" } 2 | 3 | number = @{ 4 | ASCII_DIGIT+ 5 | } 6 | hex = @{ 7 | ASCII_HEX_DIGIT{1,4} 8 | } 9 | kw = @{ 10 | "let" | "in" 11 | } 12 | ident_head = @{ 13 | ASCII_ALPHA | "_" 14 | } 15 | ident_tail = @{ 16 | ASCII_ALPHANUMERIC | "_" 17 | } 18 | ident = @{ 19 | !(hex ~ ":") 20 | ~ !(kw ~ !ident_tail) 21 | ~ ident_head ~ ident_tail* 22 | } 23 | 24 | v4addr = @{ number ~ "." ~ number ~ "." ~ number ~ "." ~ number } 25 | v4cidr = @{ v4addr ~ "/" ~ number } // No spaces allowed here 26 | 27 | v6seg = @{ hex ~ (":" ~ hex)* } 28 | v6addr = @{ v6seg? ~ ("::" ~ v6seg?)? } 29 | v6cidr = @{ v6addr ~ "/" ~ number } 30 | 31 | paren_expr = { "(" ~ expr ~ ")" } 32 | atomic = { 33 | paren_expr 34 | | ident 35 | | v4cidr 36 | | v6cidr 37 | } 38 | 39 | let_in = { "let" ~ ident ~ "=" ~ expr } 40 | add_op = { "+" } 41 | sub_op = { "-" } 42 | expr = { atomic ~ ((add_op | sub_op) ~ atomic)* } 43 | stmt = { 44 | let_in | expr 45 | } 46 | 47 | multiple_stmt = { SOI ~ stmt+ ~ EOI } 48 | single_stmt = { SOI ~ stmt ~ EOI } -------------------------------------------------------------------------------- /cidr-calc-web/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod utils; 2 | 3 | use cidr_calculator::eval::Value; 4 | use wasm_bindgen::prelude::*; 5 | use cidr_calculator::parser::parse_single; 6 | use cidr_calculator::eval::eval_stmt; 7 | use cidr_calculator::eval::Scope; 8 | use cidr_calculator::eval::format; 9 | 10 | #[wasm_bindgen] 11 | #[derive(Default)] 12 | pub struct EvalState { 13 | scope: Scope 14 | } 15 | 16 | #[wasm_bindgen] 17 | pub fn create_state() -> EvalState { 18 | Default::default() 19 | } 20 | 21 | #[wasm_bindgen] 22 | pub fn print_scope(state: &EvalState) -> Vec { 23 | state.scope.keys().map(|e| e.to_owned()).collect() 24 | } 25 | 26 | #[wasm_bindgen] 27 | pub fn eval_input(state: &mut EvalState, input: String) -> Result, String> { 28 | let stmt = parse_single(&input).map_err(|e| e.to_string())?; 29 | let (v, s) = eval_stmt(&stmt, state.scope.clone()).map_err(|e| e.to_string())?; 30 | state.scope = s; 31 | 32 | match v { 33 | Value::Unit => { 34 | Ok(vec![]) 35 | } 36 | v => { 37 | Ok(format(&v).collect()) 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /cidr-calc/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Liu Xiaoyi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /cidr-calc/src/data.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, Eq, PartialEq)] 2 | pub struct V4(pub u32, pub u8); 3 | 4 | #[derive(Debug, Eq, PartialEq)] 5 | pub struct V6(pub u128, pub u8); 6 | 7 | impl ToString for V4 { 8 | fn to_string(&self) -> String { 9 | // Mask end zeros 10 | if self.1 == 0 { 11 | return "0.0.0.0/0".to_owned(); 12 | } 13 | 14 | let masked = self.0 & !((1u32 << (32 - self.1)) - 1); 15 | format!("{}/{}", masked.to_be_bytes().map(|e| e.to_string()).join("."), self.1) 16 | } 17 | } 18 | 19 | impl ToString for V6 { 20 | fn to_string(&self) -> String { 21 | if self.1 == 0 { 22 | return "::/0".to_owned(); 23 | } 24 | 25 | let masked = self.0 & !((1u128 << (128 - self.1)) - 1); 26 | let mut segs = <[Option::; 8]>::default(); 27 | 28 | for grpidx in 0..8 { 29 | let grp = (masked >> ((8 - grpidx - 1) * 16)) & 0xFFFFu128; 30 | if grp != 0 { 31 | segs[grpidx] = Some(format!("{:x}", grp)); 32 | } 33 | } 34 | 35 | let mut zero_lengths = [0; 8]; 36 | zero_lengths[0] = if segs[0].is_none() { 1 } else { 0 }; 37 | let mut zero_lengths_max = (zero_lengths[0], 0usize); 38 | for grpidx in 1..8 { 39 | zero_lengths[grpidx] = if segs[grpidx].is_none() { 40 | zero_lengths[grpidx - 1] + 1 41 | } else { 42 | 0 43 | }; 44 | 45 | if zero_lengths_max.0 < zero_lengths[grpidx] { 46 | zero_lengths_max = (zero_lengths[grpidx], grpidx); 47 | } 48 | } 49 | 50 | // Format 51 | if zero_lengths_max.0 == 0 { 52 | // No zero segments 53 | format!("{}/{}", segs.map(Option::unwrap).join(":"), self.1) 54 | } else { 55 | let seg_start = zero_lengths_max.1 + 1 - zero_lengths_max.0; 56 | let seg_head = &segs[0..seg_start]; 57 | let seg_tail= &segs[(zero_lengths_max.1 + 1)..8]; 58 | let head = seg_head.iter().map(|e| e.as_ref().map(|i| i.as_str()).unwrap_or("0")).collect::>().join(":"); 59 | let tail = seg_tail.iter().map(|e| e.as_ref().map(|i| i.as_str()).unwrap_or("0")).collect::>().join(":"); 60 | format!("{}::{}/{}", head, tail, self.1) 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /cidr-calc/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::path::PathBuf; 2 | 3 | use clap::Parser; 4 | use cidr_calculator::eval::{eval, format, Value, eval_stmt, Scope}; 5 | use cidr_calculator::parser::{parse, parse_single}; 6 | use rustyline::DefaultEditor; 7 | 8 | #[derive(Parser)] 9 | struct Args { 10 | input: Option, // TODO: option, none is repl 11 | } 12 | 13 | fn main() -> anyhow::Result<()> { 14 | let args = Args::parse(); 15 | if args.input.is_none() { 16 | return repl(); 17 | } 18 | 19 | let input = args.input.unwrap(); 20 | let content = std::fs::read_to_string(&input)?; 21 | let parsed = parse(&content)?; 22 | let evaled = eval(&parsed)?; 23 | for value in evaled { 24 | match value { 25 | Value::Unit => {}, 26 | _ => { 27 | println!("[{}]", format(&value).collect::>().join(",")) 28 | } 29 | } 30 | } 31 | 32 | Ok(()) 33 | } 34 | 35 | fn repl() -> anyhow::Result<()> { 36 | let mut rl = DefaultEditor::new()?; 37 | 38 | let mut scope = Scope::default(); 39 | loop { 40 | let line = rl.readline("> "); 41 | match line { 42 | Ok(line) => { 43 | if line == "/s" { 44 | println!("In scope: {}", scope.keys().collect::>().join(", ")); 45 | } else { 46 | let evaled: anyhow::Result<_> = (|| { 47 | let stmt = parse_single(&line)?; 48 | let (v, s) = eval_stmt(&stmt, scope.clone())?; 49 | scope = s; 50 | Ok(v) 51 | })(); 52 | match evaled { 53 | Ok(Value::Unit) => { 54 | continue; 55 | } 56 | Ok(v) => { 57 | println!("["); 58 | for l in format(&v) { 59 | println!("\t{}", l); 60 | } 61 | println!("]"); 62 | } 63 | Err(e) => { 64 | println!("Evaluation error:"); 65 | println!("{}", e); 66 | } 67 | } 68 | } 69 | } 70 | Err(rustyline::error::ReadlineError::Eof) => { 71 | return Ok(()) 72 | } 73 | Err(rustyline::error::ReadlineError::Interrupted) => { 74 | return Err(anyhow::anyhow!("Interrupted")); 75 | } 76 | Err(e) => { 77 | return Err(anyhow::anyhow!("Unexpected error: {}", e)); 78 | } 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /cidr-calc-web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | CIDR Calculator 4 | 5 | 104 | 105 | 108 | 109 | 184 | 185 | 186 |
187 | Loading... 188 |
189 | 190 |
191 | 192 | -------------------------------------------------------------------------------- /cidr-calc/src/parser.rs: -------------------------------------------------------------------------------- 1 | use pest::{Parser, iterators::Pair}; 2 | use pest_derive::Parser; 3 | use anyhow::anyhow; 4 | 5 | use crate::data::*; 6 | 7 | #[derive(Parser)] 8 | #[grammar="./syntax.pest"] 9 | struct SrcParser; 10 | 11 | #[derive(Debug, PartialEq, Eq)] 12 | pub enum Stmt<'a> { 13 | LetIn { 14 | ident: &'a str, 15 | val: Box>, 16 | }, 17 | Expr(Expr<'a>) 18 | } 19 | 20 | impl<'a> From> for Stmt<'a> { 21 | fn from(value: Expr<'a>) -> Self { 22 | Self::Expr(value) 23 | } 24 | } 25 | 26 | #[derive(Debug, PartialEq, Eq)] 27 | pub enum Expr<'a> { 28 | Addition(Box>, Box>), 29 | Subtraction(Box>, Box>), 30 | Atomic(Atomic<'a>), 31 | } 32 | 33 | #[derive(Debug, PartialEq, Eq)] 34 | pub enum Atomic<'a> { 35 | Ident(&'a str), 36 | V4(V4), 37 | V6(V6), 38 | } 39 | 40 | fn process_v6_half(half: &str) -> (u128, u8) { 41 | if half.len() == 0 { 42 | // Is empty string 43 | return (0, 0); 44 | } 45 | let mut cnt = 0; 46 | let mut result = 0; 47 | for seg in half.split(":") { 48 | let s = u32::from_str_radix(seg, 16).unwrap(); 49 | result = (result << 16) | (s as u128); 50 | cnt += 1; 51 | } 52 | (result, cnt) 53 | } 54 | 55 | fn map_expr<'a>(p: Pair<'a, Rule>) -> anyhow::Result> { 56 | // println!("Processing: {:?}", p.as_rule()); 57 | // TODO: a million assertions 58 | match p.as_rule() { 59 | Rule::ident => Ok(Expr::Atomic(Atomic::Ident(p.as_str()))), 60 | Rule::v4cidr => { 61 | let mut collected: u32 = 0; 62 | let mut segs = p.as_str().split("/"); 63 | let addr = segs.next().unwrap(); 64 | let len = segs.next().unwrap(); 65 | for seg in addr.split(".") { 66 | if seg.len() > 3 { 67 | return Err(anyhow!("Number too big for v4 segment: {}", seg)) 68 | } 69 | let parsed: u32 = seg.parse().unwrap(); 70 | if parsed > 256 { 71 | return Err(anyhow!("Number too big for v4 segment: {}", seg)) 72 | } 73 | collected = collected << 8 | parsed; 74 | } 75 | if len.len() > 2 { 76 | return Err(anyhow!("Number too big for v4 CIDR length: {}", len)) 77 | } 78 | let len_parsed: u32 = len.parse().unwrap(); 79 | if len_parsed > 32 { 80 | return Err(anyhow!("Number too big for v4 CIDR length: {}", len)) 81 | } 82 | Ok(Expr::Atomic(Atomic::V4(V4(collected, len_parsed as u8)))) 83 | }, 84 | Rule::v6cidr => { 85 | let mut split = p.as_str().split("/"); 86 | let addr_str = split.next().unwrap(); 87 | let len_str = split.next().unwrap(); 88 | 89 | let mut halves = addr_str.split("::"); 90 | let first_half = process_v6_half(halves.next().unwrap()); 91 | let second_half = halves.next().map(process_v6_half); 92 | if halves.next().is_some() { 93 | return Err(anyhow!("IPv6 address containing more than one `::`: {}", p.as_str())) 94 | } 95 | let addr = if let Some(second_half) = second_half { 96 | if second_half.1 + first_half.1 > 8 { 97 | return Err(anyhow!("IPv6 address containing too much specified segments: {}", p.as_str())) 98 | } 99 | let first_shifter = 8 - first_half.1; 100 | let collected = if first_shifter == 8 { 101 | // First segment 0. Don't shift, because <<128 is UB 102 | 0 103 | } else { 104 | first_half.0 << (first_shifter as i32 * 16) 105 | }; 106 | collected | second_half.0 107 | } else { 108 | if first_half.1 != 8 { 109 | return Err(anyhow!("IPv6 address containing too little specified segments: {}", p.as_str())) 110 | } 111 | first_half.0 112 | }; 113 | if len_str.len() > 3 { 114 | return Err(anyhow!("Number too big for v6 CIDR length: {}", len_str)) 115 | } 116 | let len_parsed: u32 = len_str.parse().unwrap(); 117 | if len_parsed > 128 { 118 | return Err(anyhow!("Number too big for v6 CIDR length: {}", len_str)) 119 | } 120 | 121 | Ok(Expr::Atomic(Atomic::V6(V6(addr, len_parsed as u8)))) 122 | } 123 | Rule::expr => { 124 | let mut p = p.into_inner(); 125 | let mut collected = map_expr(p.next().unwrap())?; 126 | while let Some(op) = p.next() { 127 | let rhs = map_expr(p.next().unwrap())?; 128 | if op.as_rule() == Rule::add_op { 129 | collected = Expr::Addition(Box::new(collected), Box::new(rhs)); 130 | } else { 131 | collected = Expr::Subtraction(Box::new(collected), Box::new(rhs)); 132 | } 133 | } 134 | Ok(collected) 135 | } 136 | Rule::atomic => map_expr(p.into_inner().next().unwrap()), 137 | Rule::paren_expr => map_expr(p.into_inner().skip(1).next().unwrap()), 138 | e => unreachable!("Excuse me pest? Why am I reading {:?}?", e) 139 | } 140 | } 141 | 142 | fn map_stmt<'a>(p: Pair<'a, Rule>) -> anyhow::Result> { 143 | assert_eq!(p.as_rule(), Rule::stmt); 144 | let p = p.into_inner().next().unwrap(); 145 | match p.as_rule() { 146 | Rule::let_in => { 147 | let mut p = p.into_inner(); 148 | let ident = p.next().unwrap().as_str(); 149 | let val = Box::new(map_expr(p.next().unwrap())?); 150 | Ok(Stmt::LetIn { ident, val }) 151 | }, 152 | Rule::expr => { 153 | map_expr(p).map(Into::into) 154 | }, 155 | e => unreachable!("Excuse me pest? Why am I reading {:?}?", e) 156 | } 157 | } 158 | 159 | pub fn parse_single<'a>(input: &'a str) -> anyhow::Result> { 160 | let raw = SrcParser::parse(Rule::single_stmt, input)?.next().unwrap().into_inner().next().unwrap(); 161 | map_stmt(raw) 162 | } 163 | 164 | pub fn parse<'a>(input: &'a str) -> anyhow::Result>> { 165 | let raw = SrcParser::parse(Rule::multiple_stmt, input)?.next().unwrap(); 166 | raw.into_inner().filter(|e| e.as_rule() != Rule::EOI).map(|p| map_stmt(p)).collect() 167 | } 168 | 169 | #[test] 170 | fn test_parser() { 171 | let parsed = parse_single("0.0.0.0/0"); 172 | assert!(parsed.is_ok()); 173 | assert_eq!(parsed.unwrap(), Stmt::Expr(Expr::Atomic(Atomic::V4(V4(0, 0))))); 174 | 175 | let parsed = parse_single("101.6.6.6/32"); 176 | assert!(parsed.is_ok()); 177 | assert_eq!(parsed.unwrap(), Stmt::Expr(Expr::Atomic(Atomic::V4(V4(1694893574u32, 32))))); 178 | 179 | let parsed = parse_single("::/0"); 180 | assert!(parsed.is_ok()); 181 | assert_eq!(parsed.unwrap(), Stmt::Expr(Expr::Atomic(Atomic::V6(V6(0, 0))))); 182 | 183 | let parsed = parse_single("::1/128"); 184 | assert!(parsed.is_ok()); 185 | assert_eq!(parsed.unwrap(), Stmt::Expr(Expr::Atomic(Atomic::V6(V6(1, 128))))); 186 | 187 | let parsed = parse_single("2001:da8::666/24"); 188 | assert!(parsed.is_ok()); 189 | assert_eq!(parsed.unwrap(), Stmt::Expr(Expr::Atomic(Atomic::V6(V6(42540765143631992628674583454950622822u128, 24))))); 190 | 191 | let example = r#" 192 | let meow = ::/0 193 | let meow_meow = 2001:da8::666/128 194 | meow + meow_meow - meow 195 | "#; 196 | let parsed = parse(example); 197 | // assert!(parsed.is_ok()); 198 | println!("{:?}", parsed) 199 | } -------------------------------------------------------------------------------- /cidr-calc/src/eval.rs: -------------------------------------------------------------------------------- 1 | use std::{rc::Rc, collections::VecDeque, iter}; 2 | 3 | use anyhow::anyhow; 4 | 5 | use crate::{parser::{Expr, Atomic, Stmt}, data::{V4, V6}}; 6 | 7 | #[derive(Clone, Debug)] 8 | struct SetNode { 9 | depth: usize, 10 | covered: bool, 11 | left: Option>>, 12 | right: Option>>, 13 | } 14 | 15 | fn union_option( 16 | lhs: &Option>>, 17 | rhs: &Option>>, 18 | ) -> Option>> { 19 | match (lhs, rhs) { 20 | (None, r) => r.clone(), 21 | (l @ Some(_), None) => l.clone(), 22 | (Some(l), Some(r)) => Some(Rc::new(l.union(r.as_ref()))), 23 | } 24 | } 25 | 26 | fn subtract_option( 27 | lhs: &Option>>, 28 | rhs: &Option>>, 29 | ) -> Option>> { 30 | match (lhs, rhs) { 31 | (None, _) => None, 32 | (l @ Some(_), None) => l.clone(), 33 | (Some(l), Some(r)) => { 34 | let raw = l.subtract(r.as_ref()); 35 | // Subtraction may result in empty set 36 | if !raw.covered && raw.left.is_none() && raw.right.is_none() { 37 | None 38 | } else { 39 | Some(Rc::new(raw)) 40 | } 41 | } 42 | } 43 | } 44 | 45 | impl SetNode { 46 | pub fn union(&self, ano: &SetNode) -> SetNode { 47 | assert_eq!(ano.depth, self.depth); 48 | if self.covered || ano.covered { 49 | return SetNode { 50 | depth: self.depth, 51 | covered: true, 52 | left: None, 53 | right: None, 54 | }; 55 | } 56 | 57 | if self.is_empty() && ano.is_empty() { 58 | return self.clone(); 59 | } 60 | 61 | assert_ne!(self.depth, MAX_DEPTH); 62 | let left = union_option(&self.left, &ano.left); 63 | let right = union_option(&self.right, &ano.right); 64 | let covered = left.as_ref().map_or(false, |i| i.covered) 65 | && right.as_ref().map_or(false, |i| i.covered); 66 | 67 | if covered { 68 | return SetNode { 69 | depth: self.depth, 70 | covered: true, 71 | left: None, 72 | right: None, 73 | }; 74 | } 75 | 76 | SetNode { 77 | depth: self.depth, 78 | covered: false, 79 | left, 80 | right, 81 | } 82 | } 83 | 84 | pub fn subtract(&self, ano: &SetNode) -> SetNode { 85 | assert_eq!(ano.depth, self.depth); 86 | if self.is_empty() || ano.covered { 87 | return SetNode { 88 | depth: self.depth, 89 | covered: false, 90 | left: None, 91 | right: None, 92 | } 93 | } 94 | 95 | if ano.is_empty() { 96 | return self.clone(); 97 | } 98 | 99 | let mut left_ref = &self.left; 100 | let mut right_ref = &self.right; 101 | let full; 102 | if self.covered { 103 | full = Some(Rc::new(SetNode { 104 | depth: self.depth + 1, 105 | covered: true, 106 | left: None, 107 | right: None, 108 | })); 109 | left_ref = &full; 110 | right_ref = &full; 111 | } 112 | 113 | assert_ne!(self.depth, MAX_DEPTH); 114 | let left = subtract_option(left_ref, &ano.left); 115 | let right = subtract_option(right_ref, &ano.right); 116 | let covered = left.as_ref().map_or(false, |i| i.covered) 117 | && right.as_ref().map_or(false, |i| i.covered); 118 | 119 | if covered { 120 | return SetNode { 121 | depth: self.depth, 122 | covered: true, 123 | left: None, 124 | right: None, 125 | }; 126 | } 127 | 128 | SetNode { 129 | depth: self.depth, 130 | covered: false, 131 | left, 132 | right, 133 | } 134 | } 135 | 136 | pub fn is_empty(&self) -> bool { 137 | !self.covered && self.left.is_none() && self.right.is_none() 138 | } 139 | 140 | pub fn is_canonical(&self) -> bool { 141 | todo!() 142 | } 143 | } 144 | 145 | #[derive(Clone)] 146 | struct SetWalkerFrame<'a, const MAX_DEPTH: usize> { 147 | node: &'a SetNode, 148 | inspected_branches: usize, // Inspected branches. Now always 0 / 1 / 2 149 | } 150 | 151 | // Iterator, stack top always pointing at a covered node, except in the terminal state, where the stack is empty 152 | struct SetWalker<'a, const MAX_DEPTH: usize> { 153 | stack: VecDeque> 154 | } 155 | 156 | impl<'a, const MAX_DEPTH: usize> SetWalker<'a, MAX_DEPTH> { 157 | pub fn new(n: &'a SetNode) -> Self { 158 | let mut s = Self { 159 | stack: VecDeque::with_capacity(MAX_DEPTH + 1), 160 | }; 161 | s.stack.push_back(SetWalkerFrame { node: n, inspected_branches: 0 }); 162 | s 163 | } 164 | 165 | fn step(&mut self) { 166 | if self.stack.is_empty() { 167 | assert!(self.stack.is_empty()); 168 | return; 169 | } 170 | 171 | let top_node = self.stack.back_mut().unwrap().node; 172 | let top_inspected = &mut self.stack.back_mut().unwrap().inspected_branches; 173 | match *top_inspected { 174 | 0 => { 175 | *top_inspected += 1; 176 | if let Some(ref cur) = top_node.left { 177 | self.stack.push_back(SetWalkerFrame { node: cur.as_ref(), inspected_branches: 0 }) 178 | } 179 | }, 180 | 1 => { 181 | *top_inspected += 1; 182 | if let Some(ref cur) = top_node.right { 183 | self.stack.push_back(SetWalkerFrame { node: cur.as_ref(), inspected_branches: 0 }) 184 | } 185 | }, 186 | 2 => { 187 | self.stack.pop_back(); 188 | }, 189 | _ => unreachable!() 190 | } 191 | } 192 | } 193 | 194 | impl<'a, const MAX_DEPTH: usize> Iterator for SetWalker<'a, MAX_DEPTH> { 195 | type Item = (u128, usize); // TODO: high percision? 196 | 197 | fn next(&mut self) -> Option { 198 | while match self.stack.back() { 199 | None => false, 200 | Some(inner) => !inner.node.covered || inner.inspected_branches > 0 201 | } { 202 | self.step(); 203 | } 204 | 205 | if self.stack.is_empty() { 206 | return None; 207 | } 208 | 209 | // Arrived at a covered node 210 | assert_eq!(self.stack.back().map(|e| e.node.covered), Some(true)); 211 | 212 | // Serialize stack 213 | let mut addr = 0u128; 214 | let mut len = 0; 215 | for elem in &self.stack { 216 | if elem.inspected_branches == 0 { 217 | // Last one 218 | break; 219 | } 220 | addr <<= 1; 221 | addr |= (elem.inspected_branches - 1) as u128; 222 | len += 1; 223 | } 224 | 225 | if len != 0 { // Avoid UB 226 | addr <<= MAX_DEPTH - len; 227 | } 228 | 229 | self.step(); 230 | 231 | return Some((addr, len)); 232 | } 233 | } 234 | 235 | #[derive(Clone, Debug)] 236 | pub enum Value { 237 | Unit, 238 | V4Set(SetNode<32>), 239 | V6Set(SetNode<128>), 240 | } 241 | 242 | impl Value { 243 | fn is_same_len(&self, ano: &Value) -> bool { 244 | match (self, ano) { 245 | (Value::V4Set(_), Value::V6Set(_)) | (Value::V6Set(_), Value::V4Set(_)) => false, 246 | _ => true, 247 | } 248 | } 249 | 250 | fn union(&self, ano: &Value) -> anyhow::Result { 251 | if !self.is_same_len(&ano) { 252 | return Err(anyhow!("Cannot add a v4 set to a v6 set")); // TODO: diagnostic 253 | } 254 | 255 | match (self, ano) { 256 | (Value::V4Set(l), Value::V4Set(r)) => Ok(Value::V4Set(l.union(r))), 257 | (Value::V6Set(l), Value::V6Set(r)) => Ok(Value::V6Set(l.union(r))), 258 | _ => unreachable!(), 259 | } 260 | } 261 | 262 | fn subtract(&self, ano: &Value) -> anyhow::Result { 263 | if !self.is_same_len(&ano) { 264 | return Err(anyhow!("Cannot subtract a v4 set to a v6 set")); // TODO: diagnostic 265 | } 266 | 267 | match (self, ano) { 268 | (Value::V4Set(l), Value::V4Set(r)) => Ok(Value::V4Set(l.subtract(r))), 269 | (Value::V6Set(l), Value::V6Set(r)) => Ok(Value::V6Set(l.subtract(r))), 270 | _ => unreachable!(), 271 | } 272 | } 273 | } 274 | 275 | fn construct_set_node(addr: u128, len: usize, depth: usize) -> SetNode { 276 | if depth == len { 277 | assert!(depth <= MAX_DEPTH); 278 | return SetNode { 279 | depth, 280 | covered: true, 281 | left: None, 282 | right: None, 283 | }; 284 | } 285 | 286 | assert!(depth < MAX_DEPTH); 287 | 288 | let child = Some(Rc::new(construct_set_node(addr, len, depth + 1))); 289 | let mut cur = SetNode { 290 | depth, 291 | covered: false, 292 | left: None, 293 | right: None, 294 | }; 295 | if (addr >> (MAX_DEPTH - depth - 1)) & 1 == 0 { 296 | cur.left = child; 297 | } else { 298 | cur.right = child; 299 | } 300 | 301 | cur 302 | } 303 | 304 | impl From<&V4> for SetNode<32> { 305 | fn from(value: &V4) -> Self { 306 | construct_set_node(value.0 as u128, value.1 as usize, 0) 307 | } 308 | } 309 | 310 | impl From<(u128, usize)> for V4 { 311 | fn from(value: (u128, usize)) -> Self { 312 | Self(value.0 as u32, value.1 as u8) 313 | } 314 | } 315 | 316 | impl From<&V6> for SetNode<128> { 317 | fn from(value: &V6) -> Self { 318 | construct_set_node(value.0, value.1 as usize, 0) 319 | } 320 | } 321 | 322 | impl From<(u128, usize)> for V6 { 323 | fn from(value: (u128, usize)) -> Self { 324 | Self(value.0, value.1 as u8) 325 | } 326 | } 327 | 328 | #[derive(Clone)] 329 | pub struct Scope { 330 | bindings: im::HashMap, 331 | } 332 | 333 | impl Default for Scope { 334 | fn default() -> Self { 335 | Self { bindings: Default::default() } 336 | } 337 | } 338 | 339 | impl Scope { 340 | pub fn keys<'s>(&'s self) -> impl Iterator + 's { 341 | self.bindings.keys().map(String::as_str) 342 | } 343 | } 344 | 345 | pub fn eval<'a>(stmts: &Vec>) -> anyhow::Result> { 346 | let mut scope = Scope { 347 | bindings: Default::default() 348 | }; 349 | 350 | let mut output = Vec::with_capacity(stmts.len()); 351 | 352 | for stmt in stmts { 353 | let (v, s) = eval_stmt(stmt, scope)?; 354 | scope = s; 355 | output.push(v); 356 | } 357 | 358 | Ok(output) 359 | } 360 | 361 | pub fn format<'a>(v: &'a Value) -> Box + 'a> { 362 | match v { 363 | Value::Unit => Box::new(iter::empty()), 364 | Value::V4Set(s) => Box::new(SetWalker::new(s).map(V4::from).map(|e| e.to_string())), 365 | Value::V6Set(s) => Box::new(SetWalker::new(s).map(V6::from).map(|e| e.to_string())), 366 | } 367 | } 368 | 369 | pub fn eval_stmt<'a>(stmt : &Stmt<'a>, mut s: Scope) -> anyhow::Result<(Value, Scope)> { 370 | match stmt { 371 | Stmt::LetIn { ident, val } => { 372 | let val_evaled = eval_expr(val.as_ref(), s.clone())?; 373 | s.bindings.insert(ident.to_string(), val_evaled); 374 | Ok((Value::Unit, s)) 375 | }, 376 | Stmt::Expr(e) => eval_expr(e, s.clone()).map(|r| (r, s)) 377 | } 378 | } 379 | 380 | fn eval_expr<'a>(expr: &Expr<'a>, s: Scope) -> anyhow::Result { 381 | match expr { 382 | Expr::Addition(lhs, rhs) => { 383 | let lhs = eval_expr(lhs, s.clone())?; 384 | let rhs = eval_expr(rhs, s)?; 385 | lhs.union(&rhs) 386 | } 387 | Expr::Subtraction(lhs, rhs) => { 388 | let lhs = eval_expr(lhs, s.clone())?; 389 | let rhs = eval_expr(rhs, s)?; 390 | lhs.subtract(&rhs) 391 | } 392 | Expr::Atomic(a) => match a { 393 | Atomic::Ident(i) => { 394 | let lookup = s.bindings.get(*i); 395 | lookup.cloned().ok_or_else(|| anyhow!("Identifier not found in scope: {}", *i)) 396 | } 397 | Atomic::V4(v) => Ok(Value::V4Set(v.into())), 398 | Atomic::V6(v) => Ok(Value::V6Set(v.into())), 399 | } 400 | } 401 | } 402 | 403 | #[test] 404 | fn test() { 405 | fn eval_single<'a>(stmt: &Stmt<'a>) -> anyhow::Result { 406 | eval_stmt(stmt, Scope { 407 | bindings: Default::default() 408 | }).map(|e| e.0) 409 | } 410 | use crate::parser::parse_single; 411 | // FIXME: write real test! 412 | println!("{:?}", eval_single(&parse_single("0.0.0.0/0").unwrap())); 413 | println!("{:?}", eval_single(&parse_single("::1/128").unwrap())); 414 | println!("{:?}", eval_single(&parse_single("::1/128 - ::/0").unwrap())); 415 | println!("{:?}", eval_single(&parse_single("0.0.0.0/1").unwrap())); 416 | println!("{:?}", eval_single(&parse_single("0.0.0.0/1 + 128.0.0.0/1").unwrap())); 417 | println!("{:?}", eval_single(&parse_single("0.0.0.0/0 - 101.6.6.6/32").unwrap())); 418 | } -------------------------------------------------------------------------------- /cidr-calc/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "anstream" 7 | version = "0.6.4" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" 10 | dependencies = [ 11 | "anstyle", 12 | "anstyle-parse", 13 | "anstyle-query", 14 | "anstyle-wincon", 15 | "colorchoice", 16 | "utf8parse", 17 | ] 18 | 19 | [[package]] 20 | name = "anstyle" 21 | version = "1.0.4" 22 | source = "registry+https://github.com/rust-lang/crates.io-index" 23 | checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" 24 | 25 | [[package]] 26 | name = "anstyle-parse" 27 | version = "0.2.2" 28 | source = "registry+https://github.com/rust-lang/crates.io-index" 29 | checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" 30 | dependencies = [ 31 | "utf8parse", 32 | ] 33 | 34 | [[package]] 35 | name = "anstyle-query" 36 | version = "1.0.0" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" 39 | dependencies = [ 40 | "windows-sys", 41 | ] 42 | 43 | [[package]] 44 | name = "anstyle-wincon" 45 | version = "3.0.1" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" 48 | dependencies = [ 49 | "anstyle", 50 | "windows-sys", 51 | ] 52 | 53 | [[package]] 54 | name = "anyhow" 55 | version = "1.0.75" 56 | source = "registry+https://github.com/rust-lang/crates.io-index" 57 | checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" 58 | 59 | [[package]] 60 | name = "bitflags" 61 | version = "1.3.2" 62 | source = "registry+https://github.com/rust-lang/crates.io-index" 63 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 64 | 65 | [[package]] 66 | name = "bitflags" 67 | version = "2.4.1" 68 | source = "registry+https://github.com/rust-lang/crates.io-index" 69 | checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" 70 | 71 | [[package]] 72 | name = "bitmaps" 73 | version = "2.1.0" 74 | source = "registry+https://github.com/rust-lang/crates.io-index" 75 | checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" 76 | dependencies = [ 77 | "typenum", 78 | ] 79 | 80 | [[package]] 81 | name = "block-buffer" 82 | version = "0.10.4" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 85 | dependencies = [ 86 | "generic-array", 87 | ] 88 | 89 | [[package]] 90 | name = "cfg-if" 91 | version = "1.0.0" 92 | source = "registry+https://github.com/rust-lang/crates.io-index" 93 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 94 | 95 | [[package]] 96 | name = "cidr-calculator" 97 | version = "0.1.0" 98 | dependencies = [ 99 | "anyhow", 100 | "clap", 101 | "im", 102 | "pest", 103 | "pest_derive", 104 | "rustyline", 105 | ] 106 | 107 | [[package]] 108 | name = "clap" 109 | version = "4.4.6" 110 | source = "registry+https://github.com/rust-lang/crates.io-index" 111 | checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" 112 | dependencies = [ 113 | "clap_builder", 114 | "clap_derive", 115 | ] 116 | 117 | [[package]] 118 | name = "clap_builder" 119 | version = "4.4.6" 120 | source = "registry+https://github.com/rust-lang/crates.io-index" 121 | checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" 122 | dependencies = [ 123 | "anstream", 124 | "anstyle", 125 | "clap_lex", 126 | "strsim", 127 | ] 128 | 129 | [[package]] 130 | name = "clap_derive" 131 | version = "4.4.2" 132 | source = "registry+https://github.com/rust-lang/crates.io-index" 133 | checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" 134 | dependencies = [ 135 | "heck", 136 | "proc-macro2", 137 | "quote", 138 | "syn", 139 | ] 140 | 141 | [[package]] 142 | name = "clap_lex" 143 | version = "0.5.1" 144 | source = "registry+https://github.com/rust-lang/crates.io-index" 145 | checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" 146 | 147 | [[package]] 148 | name = "clipboard-win" 149 | version = "4.5.0" 150 | source = "registry+https://github.com/rust-lang/crates.io-index" 151 | checksum = "7191c27c2357d9b7ef96baac1773290d4ca63b24205b82a3fd8a0637afcf0362" 152 | dependencies = [ 153 | "error-code", 154 | "str-buf", 155 | "winapi", 156 | ] 157 | 158 | [[package]] 159 | name = "colorchoice" 160 | version = "1.0.0" 161 | source = "registry+https://github.com/rust-lang/crates.io-index" 162 | checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" 163 | 164 | [[package]] 165 | name = "cpufeatures" 166 | version = "0.2.10" 167 | source = "registry+https://github.com/rust-lang/crates.io-index" 168 | checksum = "3fbc60abd742b35f2492f808e1abbb83d45f72db402e14c55057edc9c7b1e9e4" 169 | dependencies = [ 170 | "libc", 171 | ] 172 | 173 | [[package]] 174 | name = "crypto-common" 175 | version = "0.1.6" 176 | source = "registry+https://github.com/rust-lang/crates.io-index" 177 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 178 | dependencies = [ 179 | "generic-array", 180 | "typenum", 181 | ] 182 | 183 | [[package]] 184 | name = "digest" 185 | version = "0.10.7" 186 | source = "registry+https://github.com/rust-lang/crates.io-index" 187 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 188 | dependencies = [ 189 | "block-buffer", 190 | "crypto-common", 191 | ] 192 | 193 | [[package]] 194 | name = "endian-type" 195 | version = "0.1.2" 196 | source = "registry+https://github.com/rust-lang/crates.io-index" 197 | checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" 198 | 199 | [[package]] 200 | name = "errno" 201 | version = "0.3.5" 202 | source = "registry+https://github.com/rust-lang/crates.io-index" 203 | checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" 204 | dependencies = [ 205 | "libc", 206 | "windows-sys", 207 | ] 208 | 209 | [[package]] 210 | name = "error-code" 211 | version = "2.3.1" 212 | source = "registry+https://github.com/rust-lang/crates.io-index" 213 | checksum = "64f18991e7bf11e7ffee451b5318b5c1a73c52d0d0ada6e5a3017c8c1ced6a21" 214 | dependencies = [ 215 | "libc", 216 | "str-buf", 217 | ] 218 | 219 | [[package]] 220 | name = "fd-lock" 221 | version = "3.0.13" 222 | source = "registry+https://github.com/rust-lang/crates.io-index" 223 | checksum = "ef033ed5e9bad94e55838ca0ca906db0e043f517adda0c8b79c7a8c66c93c1b5" 224 | dependencies = [ 225 | "cfg-if", 226 | "rustix", 227 | "windows-sys", 228 | ] 229 | 230 | [[package]] 231 | name = "generic-array" 232 | version = "0.14.7" 233 | source = "registry+https://github.com/rust-lang/crates.io-index" 234 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 235 | dependencies = [ 236 | "typenum", 237 | "version_check", 238 | ] 239 | 240 | [[package]] 241 | name = "heck" 242 | version = "0.4.1" 243 | source = "registry+https://github.com/rust-lang/crates.io-index" 244 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 245 | 246 | [[package]] 247 | name = "home" 248 | version = "0.5.5" 249 | source = "registry+https://github.com/rust-lang/crates.io-index" 250 | checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" 251 | dependencies = [ 252 | "windows-sys", 253 | ] 254 | 255 | [[package]] 256 | name = "im" 257 | version = "15.1.0" 258 | source = "registry+https://github.com/rust-lang/crates.io-index" 259 | checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9" 260 | dependencies = [ 261 | "bitmaps", 262 | "rand_core", 263 | "rand_xoshiro", 264 | "sized-chunks", 265 | "typenum", 266 | "version_check", 267 | ] 268 | 269 | [[package]] 270 | name = "libc" 271 | version = "0.2.149" 272 | source = "registry+https://github.com/rust-lang/crates.io-index" 273 | checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" 274 | 275 | [[package]] 276 | name = "linux-raw-sys" 277 | version = "0.4.10" 278 | source = "registry+https://github.com/rust-lang/crates.io-index" 279 | checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" 280 | 281 | [[package]] 282 | name = "log" 283 | version = "0.4.20" 284 | source = "registry+https://github.com/rust-lang/crates.io-index" 285 | checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" 286 | 287 | [[package]] 288 | name = "memchr" 289 | version = "2.6.4" 290 | source = "registry+https://github.com/rust-lang/crates.io-index" 291 | checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" 292 | 293 | [[package]] 294 | name = "nibble_vec" 295 | version = "0.1.0" 296 | source = "registry+https://github.com/rust-lang/crates.io-index" 297 | checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" 298 | dependencies = [ 299 | "smallvec", 300 | ] 301 | 302 | [[package]] 303 | name = "nix" 304 | version = "0.26.4" 305 | source = "registry+https://github.com/rust-lang/crates.io-index" 306 | checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" 307 | dependencies = [ 308 | "bitflags 1.3.2", 309 | "cfg-if", 310 | "libc", 311 | ] 312 | 313 | [[package]] 314 | name = "once_cell" 315 | version = "1.18.0" 316 | source = "registry+https://github.com/rust-lang/crates.io-index" 317 | checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" 318 | 319 | [[package]] 320 | name = "pest" 321 | version = "2.7.4" 322 | source = "registry+https://github.com/rust-lang/crates.io-index" 323 | checksum = "c022f1e7b65d6a24c0dbbd5fb344c66881bc01f3e5ae74a1c8100f2f985d98a4" 324 | dependencies = [ 325 | "memchr", 326 | "thiserror", 327 | "ucd-trie", 328 | ] 329 | 330 | [[package]] 331 | name = "pest_derive" 332 | version = "2.7.4" 333 | source = "registry+https://github.com/rust-lang/crates.io-index" 334 | checksum = "35513f630d46400a977c4cb58f78e1bfbe01434316e60c37d27b9ad6139c66d8" 335 | dependencies = [ 336 | "pest", 337 | "pest_generator", 338 | ] 339 | 340 | [[package]] 341 | name = "pest_generator" 342 | version = "2.7.4" 343 | source = "registry+https://github.com/rust-lang/crates.io-index" 344 | checksum = "bc9fc1b9e7057baba189b5c626e2d6f40681ae5b6eb064dc7c7834101ec8123a" 345 | dependencies = [ 346 | "pest", 347 | "pest_meta", 348 | "proc-macro2", 349 | "quote", 350 | "syn", 351 | ] 352 | 353 | [[package]] 354 | name = "pest_meta" 355 | version = "2.7.4" 356 | source = "registry+https://github.com/rust-lang/crates.io-index" 357 | checksum = "1df74e9e7ec4053ceb980e7c0c8bd3594e977fde1af91daba9c928e8e8c6708d" 358 | dependencies = [ 359 | "once_cell", 360 | "pest", 361 | "sha2", 362 | ] 363 | 364 | [[package]] 365 | name = "proc-macro2" 366 | version = "1.0.69" 367 | source = "registry+https://github.com/rust-lang/crates.io-index" 368 | checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" 369 | dependencies = [ 370 | "unicode-ident", 371 | ] 372 | 373 | [[package]] 374 | name = "quote" 375 | version = "1.0.33" 376 | source = "registry+https://github.com/rust-lang/crates.io-index" 377 | checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" 378 | dependencies = [ 379 | "proc-macro2", 380 | ] 381 | 382 | [[package]] 383 | name = "radix_trie" 384 | version = "0.2.1" 385 | source = "registry+https://github.com/rust-lang/crates.io-index" 386 | checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" 387 | dependencies = [ 388 | "endian-type", 389 | "nibble_vec", 390 | ] 391 | 392 | [[package]] 393 | name = "rand_core" 394 | version = "0.6.4" 395 | source = "registry+https://github.com/rust-lang/crates.io-index" 396 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 397 | 398 | [[package]] 399 | name = "rand_xoshiro" 400 | version = "0.6.0" 401 | source = "registry+https://github.com/rust-lang/crates.io-index" 402 | checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" 403 | dependencies = [ 404 | "rand_core", 405 | ] 406 | 407 | [[package]] 408 | name = "rustix" 409 | version = "0.38.21" 410 | source = "registry+https://github.com/rust-lang/crates.io-index" 411 | checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" 412 | dependencies = [ 413 | "bitflags 2.4.1", 414 | "errno", 415 | "libc", 416 | "linux-raw-sys", 417 | "windows-sys", 418 | ] 419 | 420 | [[package]] 421 | name = "rustyline" 422 | version = "12.0.0" 423 | source = "registry+https://github.com/rust-lang/crates.io-index" 424 | checksum = "994eca4bca05c87e86e15d90fc7a91d1be64b4482b38cb2d27474568fe7c9db9" 425 | dependencies = [ 426 | "bitflags 2.4.1", 427 | "cfg-if", 428 | "clipboard-win", 429 | "fd-lock", 430 | "home", 431 | "libc", 432 | "log", 433 | "memchr", 434 | "nix", 435 | "radix_trie", 436 | "scopeguard", 437 | "unicode-segmentation", 438 | "unicode-width", 439 | "utf8parse", 440 | "winapi", 441 | ] 442 | 443 | [[package]] 444 | name = "scopeguard" 445 | version = "1.2.0" 446 | source = "registry+https://github.com/rust-lang/crates.io-index" 447 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 448 | 449 | [[package]] 450 | name = "sha2" 451 | version = "0.10.8" 452 | source = "registry+https://github.com/rust-lang/crates.io-index" 453 | checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" 454 | dependencies = [ 455 | "cfg-if", 456 | "cpufeatures", 457 | "digest", 458 | ] 459 | 460 | [[package]] 461 | name = "sized-chunks" 462 | version = "0.6.5" 463 | source = "registry+https://github.com/rust-lang/crates.io-index" 464 | checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" 465 | dependencies = [ 466 | "bitmaps", 467 | "typenum", 468 | ] 469 | 470 | [[package]] 471 | name = "smallvec" 472 | version = "1.11.1" 473 | source = "registry+https://github.com/rust-lang/crates.io-index" 474 | checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" 475 | 476 | [[package]] 477 | name = "str-buf" 478 | version = "1.0.6" 479 | source = "registry+https://github.com/rust-lang/crates.io-index" 480 | checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0" 481 | 482 | [[package]] 483 | name = "strsim" 484 | version = "0.10.0" 485 | source = "registry+https://github.com/rust-lang/crates.io-index" 486 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 487 | 488 | [[package]] 489 | name = "syn" 490 | version = "2.0.38" 491 | source = "registry+https://github.com/rust-lang/crates.io-index" 492 | checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" 493 | dependencies = [ 494 | "proc-macro2", 495 | "quote", 496 | "unicode-ident", 497 | ] 498 | 499 | [[package]] 500 | name = "thiserror" 501 | version = "1.0.50" 502 | source = "registry+https://github.com/rust-lang/crates.io-index" 503 | checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" 504 | dependencies = [ 505 | "thiserror-impl", 506 | ] 507 | 508 | [[package]] 509 | name = "thiserror-impl" 510 | version = "1.0.50" 511 | source = "registry+https://github.com/rust-lang/crates.io-index" 512 | checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" 513 | dependencies = [ 514 | "proc-macro2", 515 | "quote", 516 | "syn", 517 | ] 518 | 519 | [[package]] 520 | name = "typenum" 521 | version = "1.17.0" 522 | source = "registry+https://github.com/rust-lang/crates.io-index" 523 | checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" 524 | 525 | [[package]] 526 | name = "ucd-trie" 527 | version = "0.1.6" 528 | source = "registry+https://github.com/rust-lang/crates.io-index" 529 | checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" 530 | 531 | [[package]] 532 | name = "unicode-ident" 533 | version = "1.0.12" 534 | source = "registry+https://github.com/rust-lang/crates.io-index" 535 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 536 | 537 | [[package]] 538 | name = "unicode-segmentation" 539 | version = "1.10.1" 540 | source = "registry+https://github.com/rust-lang/crates.io-index" 541 | checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" 542 | 543 | [[package]] 544 | name = "unicode-width" 545 | version = "0.1.11" 546 | source = "registry+https://github.com/rust-lang/crates.io-index" 547 | checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" 548 | 549 | [[package]] 550 | name = "utf8parse" 551 | version = "0.2.1" 552 | source = "registry+https://github.com/rust-lang/crates.io-index" 553 | checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" 554 | 555 | [[package]] 556 | name = "version_check" 557 | version = "0.9.4" 558 | source = "registry+https://github.com/rust-lang/crates.io-index" 559 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 560 | 561 | [[package]] 562 | name = "winapi" 563 | version = "0.3.9" 564 | source = "registry+https://github.com/rust-lang/crates.io-index" 565 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 566 | dependencies = [ 567 | "winapi-i686-pc-windows-gnu", 568 | "winapi-x86_64-pc-windows-gnu", 569 | ] 570 | 571 | [[package]] 572 | name = "winapi-i686-pc-windows-gnu" 573 | version = "0.4.0" 574 | source = "registry+https://github.com/rust-lang/crates.io-index" 575 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 576 | 577 | [[package]] 578 | name = "winapi-x86_64-pc-windows-gnu" 579 | version = "0.4.0" 580 | source = "registry+https://github.com/rust-lang/crates.io-index" 581 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 582 | 583 | [[package]] 584 | name = "windows-sys" 585 | version = "0.48.0" 586 | source = "registry+https://github.com/rust-lang/crates.io-index" 587 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 588 | dependencies = [ 589 | "windows-targets", 590 | ] 591 | 592 | [[package]] 593 | name = "windows-targets" 594 | version = "0.48.5" 595 | source = "registry+https://github.com/rust-lang/crates.io-index" 596 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 597 | dependencies = [ 598 | "windows_aarch64_gnullvm", 599 | "windows_aarch64_msvc", 600 | "windows_i686_gnu", 601 | "windows_i686_msvc", 602 | "windows_x86_64_gnu", 603 | "windows_x86_64_gnullvm", 604 | "windows_x86_64_msvc", 605 | ] 606 | 607 | [[package]] 608 | name = "windows_aarch64_gnullvm" 609 | version = "0.48.5" 610 | source = "registry+https://github.com/rust-lang/crates.io-index" 611 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 612 | 613 | [[package]] 614 | name = "windows_aarch64_msvc" 615 | version = "0.48.5" 616 | source = "registry+https://github.com/rust-lang/crates.io-index" 617 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 618 | 619 | [[package]] 620 | name = "windows_i686_gnu" 621 | version = "0.48.5" 622 | source = "registry+https://github.com/rust-lang/crates.io-index" 623 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 624 | 625 | [[package]] 626 | name = "windows_i686_msvc" 627 | version = "0.48.5" 628 | source = "registry+https://github.com/rust-lang/crates.io-index" 629 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 630 | 631 | [[package]] 632 | name = "windows_x86_64_gnu" 633 | version = "0.48.5" 634 | source = "registry+https://github.com/rust-lang/crates.io-index" 635 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 636 | 637 | [[package]] 638 | name = "windows_x86_64_gnullvm" 639 | version = "0.48.5" 640 | source = "registry+https://github.com/rust-lang/crates.io-index" 641 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 642 | 643 | [[package]] 644 | name = "windows_x86_64_msvc" 645 | version = "0.48.5" 646 | source = "registry+https://github.com/rust-lang/crates.io-index" 647 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 648 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "anstream" 7 | version = "0.6.19" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" 10 | dependencies = [ 11 | "anstyle", 12 | "anstyle-parse", 13 | "anstyle-query", 14 | "anstyle-wincon", 15 | "colorchoice", 16 | "is_terminal_polyfill", 17 | "utf8parse", 18 | ] 19 | 20 | [[package]] 21 | name = "anstyle" 22 | version = "1.0.11" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" 25 | 26 | [[package]] 27 | name = "anstyle-parse" 28 | version = "0.2.7" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" 31 | dependencies = [ 32 | "utf8parse", 33 | ] 34 | 35 | [[package]] 36 | name = "anstyle-query" 37 | version = "1.1.3" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" 40 | dependencies = [ 41 | "windows-sys 0.59.0", 42 | ] 43 | 44 | [[package]] 45 | name = "anstyle-wincon" 46 | version = "3.0.9" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" 49 | dependencies = [ 50 | "anstyle", 51 | "once_cell_polyfill", 52 | "windows-sys 0.59.0", 53 | ] 54 | 55 | [[package]] 56 | name = "anyhow" 57 | version = "1.0.100" 58 | source = "registry+https://github.com/rust-lang/crates.io-index" 59 | checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" 60 | 61 | [[package]] 62 | name = "bitflags" 63 | version = "2.9.1" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" 66 | 67 | [[package]] 68 | name = "bitmaps" 69 | version = "2.1.0" 70 | source = "registry+https://github.com/rust-lang/crates.io-index" 71 | checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" 72 | dependencies = [ 73 | "typenum", 74 | ] 75 | 76 | [[package]] 77 | name = "block-buffer" 78 | version = "0.10.4" 79 | source = "registry+https://github.com/rust-lang/crates.io-index" 80 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 81 | dependencies = [ 82 | "generic-array", 83 | ] 84 | 85 | [[package]] 86 | name = "bumpalo" 87 | version = "3.14.0" 88 | source = "registry+https://github.com/rust-lang/crates.io-index" 89 | checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" 90 | 91 | [[package]] 92 | name = "cfg-if" 93 | version = "1.0.1" 94 | source = "registry+https://github.com/rust-lang/crates.io-index" 95 | checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" 96 | 97 | [[package]] 98 | name = "cfg_aliases" 99 | version = "0.2.1" 100 | source = "registry+https://github.com/rust-lang/crates.io-index" 101 | checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" 102 | 103 | [[package]] 104 | name = "cidr-calculator" 105 | version = "0.2.0" 106 | dependencies = [ 107 | "anyhow", 108 | "clap", 109 | "im", 110 | "pest", 111 | "pest_derive", 112 | "rustyline", 113 | ] 114 | 115 | [[package]] 116 | name = "cidr-calculator-web" 117 | version = "0.1.0" 118 | dependencies = [ 119 | "cidr-calculator", 120 | "console_error_panic_hook", 121 | "wasm-bindgen", 122 | ] 123 | 124 | [[package]] 125 | name = "clap" 126 | version = "4.5.48" 127 | source = "registry+https://github.com/rust-lang/crates.io-index" 128 | checksum = "e2134bb3ea021b78629caa971416385309e0131b351b25e01dc16fb54e1b5fae" 129 | dependencies = [ 130 | "clap_builder", 131 | "clap_derive", 132 | ] 133 | 134 | [[package]] 135 | name = "clap_builder" 136 | version = "4.5.48" 137 | source = "registry+https://github.com/rust-lang/crates.io-index" 138 | checksum = "c2ba64afa3c0a6df7fa517765e31314e983f51dda798ffba27b988194fb65dc9" 139 | dependencies = [ 140 | "anstream", 141 | "anstyle", 142 | "clap_lex", 143 | "strsim", 144 | ] 145 | 146 | [[package]] 147 | name = "clap_derive" 148 | version = "4.5.47" 149 | source = "registry+https://github.com/rust-lang/crates.io-index" 150 | checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" 151 | dependencies = [ 152 | "heck", 153 | "proc-macro2", 154 | "quote", 155 | "syn", 156 | ] 157 | 158 | [[package]] 159 | name = "clap_lex" 160 | version = "0.7.5" 161 | source = "registry+https://github.com/rust-lang/crates.io-index" 162 | checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" 163 | 164 | [[package]] 165 | name = "clipboard-win" 166 | version = "5.2.0" 167 | source = "registry+https://github.com/rust-lang/crates.io-index" 168 | checksum = "12f9a0700e0127ba15d1d52dd742097f821cd9c65939303a44d970465040a297" 169 | dependencies = [ 170 | "error-code", 171 | ] 172 | 173 | [[package]] 174 | name = "colorchoice" 175 | version = "1.0.4" 176 | source = "registry+https://github.com/rust-lang/crates.io-index" 177 | checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" 178 | 179 | [[package]] 180 | name = "console_error_panic_hook" 181 | version = "0.1.7" 182 | source = "registry+https://github.com/rust-lang/crates.io-index" 183 | checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" 184 | dependencies = [ 185 | "cfg-if", 186 | "wasm-bindgen", 187 | ] 188 | 189 | [[package]] 190 | name = "cpufeatures" 191 | version = "0.2.12" 192 | source = "registry+https://github.com/rust-lang/crates.io-index" 193 | checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" 194 | dependencies = [ 195 | "libc", 196 | ] 197 | 198 | [[package]] 199 | name = "crypto-common" 200 | version = "0.1.6" 201 | source = "registry+https://github.com/rust-lang/crates.io-index" 202 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 203 | dependencies = [ 204 | "generic-array", 205 | "typenum", 206 | ] 207 | 208 | [[package]] 209 | name = "digest" 210 | version = "0.10.7" 211 | source = "registry+https://github.com/rust-lang/crates.io-index" 212 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 213 | dependencies = [ 214 | "block-buffer", 215 | "crypto-common", 216 | ] 217 | 218 | [[package]] 219 | name = "endian-type" 220 | version = "0.1.2" 221 | source = "registry+https://github.com/rust-lang/crates.io-index" 222 | checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" 223 | 224 | [[package]] 225 | name = "errno" 226 | version = "0.3.13" 227 | source = "registry+https://github.com/rust-lang/crates.io-index" 228 | checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" 229 | dependencies = [ 230 | "libc", 231 | "windows-sys 0.60.2", 232 | ] 233 | 234 | [[package]] 235 | name = "error-code" 236 | version = "3.2.0" 237 | source = "registry+https://github.com/rust-lang/crates.io-index" 238 | checksum = "a0474425d51df81997e2f90a21591180b38eccf27292d755f3e30750225c175b" 239 | 240 | [[package]] 241 | name = "fd-lock" 242 | version = "4.0.2" 243 | source = "registry+https://github.com/rust-lang/crates.io-index" 244 | checksum = "7e5768da2206272c81ef0b5e951a41862938a6070da63bcea197899942d3b947" 245 | dependencies = [ 246 | "cfg-if", 247 | "rustix", 248 | "windows-sys 0.52.0", 249 | ] 250 | 251 | [[package]] 252 | name = "generic-array" 253 | version = "0.14.7" 254 | source = "registry+https://github.com/rust-lang/crates.io-index" 255 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 256 | dependencies = [ 257 | "typenum", 258 | "version_check", 259 | ] 260 | 261 | [[package]] 262 | name = "heck" 263 | version = "0.5.0" 264 | source = "registry+https://github.com/rust-lang/crates.io-index" 265 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 266 | 267 | [[package]] 268 | name = "home" 269 | version = "0.5.9" 270 | source = "registry+https://github.com/rust-lang/crates.io-index" 271 | checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" 272 | dependencies = [ 273 | "windows-sys 0.52.0", 274 | ] 275 | 276 | [[package]] 277 | name = "im" 278 | version = "15.1.0" 279 | source = "registry+https://github.com/rust-lang/crates.io-index" 280 | checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9" 281 | dependencies = [ 282 | "bitmaps", 283 | "rand_core", 284 | "rand_xoshiro", 285 | "sized-chunks", 286 | "typenum", 287 | "version_check", 288 | ] 289 | 290 | [[package]] 291 | name = "is_terminal_polyfill" 292 | version = "1.70.1" 293 | source = "registry+https://github.com/rust-lang/crates.io-index" 294 | checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" 295 | 296 | [[package]] 297 | name = "libc" 298 | version = "0.2.174" 299 | source = "registry+https://github.com/rust-lang/crates.io-index" 300 | checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" 301 | 302 | [[package]] 303 | name = "linux-raw-sys" 304 | version = "0.4.15" 305 | source = "registry+https://github.com/rust-lang/crates.io-index" 306 | checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" 307 | 308 | [[package]] 309 | name = "log" 310 | version = "0.4.27" 311 | source = "registry+https://github.com/rust-lang/crates.io-index" 312 | checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" 313 | 314 | [[package]] 315 | name = "memchr" 316 | version = "2.7.5" 317 | source = "registry+https://github.com/rust-lang/crates.io-index" 318 | checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" 319 | 320 | [[package]] 321 | name = "nibble_vec" 322 | version = "0.1.0" 323 | source = "registry+https://github.com/rust-lang/crates.io-index" 324 | checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" 325 | dependencies = [ 326 | "smallvec", 327 | ] 328 | 329 | [[package]] 330 | name = "nix" 331 | version = "0.30.1" 332 | source = "registry+https://github.com/rust-lang/crates.io-index" 333 | checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" 334 | dependencies = [ 335 | "bitflags", 336 | "cfg-if", 337 | "cfg_aliases", 338 | "libc", 339 | ] 340 | 341 | [[package]] 342 | name = "once_cell" 343 | version = "1.19.0" 344 | source = "registry+https://github.com/rust-lang/crates.io-index" 345 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" 346 | 347 | [[package]] 348 | name = "once_cell_polyfill" 349 | version = "1.70.1" 350 | source = "registry+https://github.com/rust-lang/crates.io-index" 351 | checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" 352 | 353 | [[package]] 354 | name = "pest" 355 | version = "2.8.2" 356 | source = "registry+https://github.com/rust-lang/crates.io-index" 357 | checksum = "21e0a3a33733faeaf8651dfee72dd0f388f0c8e5ad496a3478fa5a922f49cfa8" 358 | dependencies = [ 359 | "memchr", 360 | "thiserror", 361 | "ucd-trie", 362 | ] 363 | 364 | [[package]] 365 | name = "pest_derive" 366 | version = "2.8.2" 367 | source = "registry+https://github.com/rust-lang/crates.io-index" 368 | checksum = "bc58706f770acb1dbd0973e6530a3cff4746fb721207feb3a8a6064cd0b6c663" 369 | dependencies = [ 370 | "pest", 371 | "pest_generator", 372 | ] 373 | 374 | [[package]] 375 | name = "pest_generator" 376 | version = "2.8.2" 377 | source = "registry+https://github.com/rust-lang/crates.io-index" 378 | checksum = "6d4f36811dfe07f7b8573462465d5cb8965fffc2e71ae377a33aecf14c2c9a2f" 379 | dependencies = [ 380 | "pest", 381 | "pest_meta", 382 | "proc-macro2", 383 | "quote", 384 | "syn", 385 | ] 386 | 387 | [[package]] 388 | name = "pest_meta" 389 | version = "2.8.2" 390 | source = "registry+https://github.com/rust-lang/crates.io-index" 391 | checksum = "42919b05089acbd0a5dcd5405fb304d17d1053847b81163d09c4ad18ce8e8420" 392 | dependencies = [ 393 | "pest", 394 | "sha2", 395 | ] 396 | 397 | [[package]] 398 | name = "proc-macro2" 399 | version = "1.0.95" 400 | source = "registry+https://github.com/rust-lang/crates.io-index" 401 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 402 | dependencies = [ 403 | "unicode-ident", 404 | ] 405 | 406 | [[package]] 407 | name = "quote" 408 | version = "1.0.40" 409 | source = "registry+https://github.com/rust-lang/crates.io-index" 410 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 411 | dependencies = [ 412 | "proc-macro2", 413 | ] 414 | 415 | [[package]] 416 | name = "radix_trie" 417 | version = "0.2.1" 418 | source = "registry+https://github.com/rust-lang/crates.io-index" 419 | checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" 420 | dependencies = [ 421 | "endian-type", 422 | "nibble_vec", 423 | ] 424 | 425 | [[package]] 426 | name = "rand_core" 427 | version = "0.6.4" 428 | source = "registry+https://github.com/rust-lang/crates.io-index" 429 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 430 | 431 | [[package]] 432 | name = "rand_xoshiro" 433 | version = "0.6.0" 434 | source = "registry+https://github.com/rust-lang/crates.io-index" 435 | checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" 436 | dependencies = [ 437 | "rand_core", 438 | ] 439 | 440 | [[package]] 441 | name = "rustix" 442 | version = "0.38.44" 443 | source = "registry+https://github.com/rust-lang/crates.io-index" 444 | checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" 445 | dependencies = [ 446 | "bitflags", 447 | "errno", 448 | "libc", 449 | "linux-raw-sys", 450 | "windows-sys 0.59.0", 451 | ] 452 | 453 | [[package]] 454 | name = "rustversion" 455 | version = "1.0.19" 456 | source = "registry+https://github.com/rust-lang/crates.io-index" 457 | checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" 458 | 459 | [[package]] 460 | name = "rustyline" 461 | version = "17.0.1" 462 | source = "registry+https://github.com/rust-lang/crates.io-index" 463 | checksum = "a6614df0b6d4cfb20d1d5e295332921793ce499af3ebc011bf1e393380e1e492" 464 | dependencies = [ 465 | "bitflags", 466 | "cfg-if", 467 | "clipboard-win", 468 | "fd-lock", 469 | "home", 470 | "libc", 471 | "log", 472 | "memchr", 473 | "nix", 474 | "radix_trie", 475 | "unicode-segmentation", 476 | "unicode-width", 477 | "utf8parse", 478 | "windows-sys 0.60.2", 479 | ] 480 | 481 | [[package]] 482 | name = "sha2" 483 | version = "0.10.8" 484 | source = "registry+https://github.com/rust-lang/crates.io-index" 485 | checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" 486 | dependencies = [ 487 | "cfg-if", 488 | "cpufeatures", 489 | "digest", 490 | ] 491 | 492 | [[package]] 493 | name = "sized-chunks" 494 | version = "0.6.5" 495 | source = "registry+https://github.com/rust-lang/crates.io-index" 496 | checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" 497 | dependencies = [ 498 | "bitmaps", 499 | "typenum", 500 | ] 501 | 502 | [[package]] 503 | name = "smallvec" 504 | version = "1.15.1" 505 | source = "registry+https://github.com/rust-lang/crates.io-index" 506 | checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" 507 | 508 | [[package]] 509 | name = "strsim" 510 | version = "0.11.1" 511 | source = "registry+https://github.com/rust-lang/crates.io-index" 512 | checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" 513 | 514 | [[package]] 515 | name = "syn" 516 | version = "2.0.104" 517 | source = "registry+https://github.com/rust-lang/crates.io-index" 518 | checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" 519 | dependencies = [ 520 | "proc-macro2", 521 | "quote", 522 | "unicode-ident", 523 | ] 524 | 525 | [[package]] 526 | name = "thiserror" 527 | version = "2.0.12" 528 | source = "registry+https://github.com/rust-lang/crates.io-index" 529 | checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" 530 | dependencies = [ 531 | "thiserror-impl", 532 | ] 533 | 534 | [[package]] 535 | name = "thiserror-impl" 536 | version = "2.0.12" 537 | source = "registry+https://github.com/rust-lang/crates.io-index" 538 | checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" 539 | dependencies = [ 540 | "proc-macro2", 541 | "quote", 542 | "syn", 543 | ] 544 | 545 | [[package]] 546 | name = "typenum" 547 | version = "1.17.0" 548 | source = "registry+https://github.com/rust-lang/crates.io-index" 549 | checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" 550 | 551 | [[package]] 552 | name = "ucd-trie" 553 | version = "0.1.6" 554 | source = "registry+https://github.com/rust-lang/crates.io-index" 555 | checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" 556 | 557 | [[package]] 558 | name = "unicode-ident" 559 | version = "1.0.18" 560 | source = "registry+https://github.com/rust-lang/crates.io-index" 561 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 562 | 563 | [[package]] 564 | name = "unicode-segmentation" 565 | version = "1.12.0" 566 | source = "registry+https://github.com/rust-lang/crates.io-index" 567 | checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" 568 | 569 | [[package]] 570 | name = "unicode-width" 571 | version = "0.2.1" 572 | source = "registry+https://github.com/rust-lang/crates.io-index" 573 | checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" 574 | 575 | [[package]] 576 | name = "utf8parse" 577 | version = "0.2.2" 578 | source = "registry+https://github.com/rust-lang/crates.io-index" 579 | checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" 580 | 581 | [[package]] 582 | name = "version_check" 583 | version = "0.9.5" 584 | source = "registry+https://github.com/rust-lang/crates.io-index" 585 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 586 | 587 | [[package]] 588 | name = "wasm-bindgen" 589 | version = "0.2.104" 590 | source = "registry+https://github.com/rust-lang/crates.io-index" 591 | checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" 592 | dependencies = [ 593 | "cfg-if", 594 | "once_cell", 595 | "rustversion", 596 | "wasm-bindgen-macro", 597 | "wasm-bindgen-shared", 598 | ] 599 | 600 | [[package]] 601 | name = "wasm-bindgen-backend" 602 | version = "0.2.104" 603 | source = "registry+https://github.com/rust-lang/crates.io-index" 604 | checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" 605 | dependencies = [ 606 | "bumpalo", 607 | "log", 608 | "proc-macro2", 609 | "quote", 610 | "syn", 611 | "wasm-bindgen-shared", 612 | ] 613 | 614 | [[package]] 615 | name = "wasm-bindgen-macro" 616 | version = "0.2.104" 617 | source = "registry+https://github.com/rust-lang/crates.io-index" 618 | checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" 619 | dependencies = [ 620 | "quote", 621 | "wasm-bindgen-macro-support", 622 | ] 623 | 624 | [[package]] 625 | name = "wasm-bindgen-macro-support" 626 | version = "0.2.104" 627 | source = "registry+https://github.com/rust-lang/crates.io-index" 628 | checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" 629 | dependencies = [ 630 | "proc-macro2", 631 | "quote", 632 | "syn", 633 | "wasm-bindgen-backend", 634 | "wasm-bindgen-shared", 635 | ] 636 | 637 | [[package]] 638 | name = "wasm-bindgen-shared" 639 | version = "0.2.104" 640 | source = "registry+https://github.com/rust-lang/crates.io-index" 641 | checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" 642 | dependencies = [ 643 | "unicode-ident", 644 | ] 645 | 646 | [[package]] 647 | name = "windows-link" 648 | version = "0.1.3" 649 | source = "registry+https://github.com/rust-lang/crates.io-index" 650 | checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" 651 | 652 | [[package]] 653 | name = "windows-sys" 654 | version = "0.52.0" 655 | source = "registry+https://github.com/rust-lang/crates.io-index" 656 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 657 | dependencies = [ 658 | "windows-targets 0.52.6", 659 | ] 660 | 661 | [[package]] 662 | name = "windows-sys" 663 | version = "0.59.0" 664 | source = "registry+https://github.com/rust-lang/crates.io-index" 665 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 666 | dependencies = [ 667 | "windows-targets 0.52.6", 668 | ] 669 | 670 | [[package]] 671 | name = "windows-sys" 672 | version = "0.60.2" 673 | source = "registry+https://github.com/rust-lang/crates.io-index" 674 | checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" 675 | dependencies = [ 676 | "windows-targets 0.53.3", 677 | ] 678 | 679 | [[package]] 680 | name = "windows-targets" 681 | version = "0.52.6" 682 | source = "registry+https://github.com/rust-lang/crates.io-index" 683 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 684 | dependencies = [ 685 | "windows_aarch64_gnullvm 0.52.6", 686 | "windows_aarch64_msvc 0.52.6", 687 | "windows_i686_gnu 0.52.6", 688 | "windows_i686_gnullvm 0.52.6", 689 | "windows_i686_msvc 0.52.6", 690 | "windows_x86_64_gnu 0.52.6", 691 | "windows_x86_64_gnullvm 0.52.6", 692 | "windows_x86_64_msvc 0.52.6", 693 | ] 694 | 695 | [[package]] 696 | name = "windows-targets" 697 | version = "0.53.3" 698 | source = "registry+https://github.com/rust-lang/crates.io-index" 699 | checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" 700 | dependencies = [ 701 | "windows-link", 702 | "windows_aarch64_gnullvm 0.53.0", 703 | "windows_aarch64_msvc 0.53.0", 704 | "windows_i686_gnu 0.53.0", 705 | "windows_i686_gnullvm 0.53.0", 706 | "windows_i686_msvc 0.53.0", 707 | "windows_x86_64_gnu 0.53.0", 708 | "windows_x86_64_gnullvm 0.53.0", 709 | "windows_x86_64_msvc 0.53.0", 710 | ] 711 | 712 | [[package]] 713 | name = "windows_aarch64_gnullvm" 714 | version = "0.52.6" 715 | source = "registry+https://github.com/rust-lang/crates.io-index" 716 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 717 | 718 | [[package]] 719 | name = "windows_aarch64_gnullvm" 720 | version = "0.53.0" 721 | source = "registry+https://github.com/rust-lang/crates.io-index" 722 | checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" 723 | 724 | [[package]] 725 | name = "windows_aarch64_msvc" 726 | version = "0.52.6" 727 | source = "registry+https://github.com/rust-lang/crates.io-index" 728 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 729 | 730 | [[package]] 731 | name = "windows_aarch64_msvc" 732 | version = "0.53.0" 733 | source = "registry+https://github.com/rust-lang/crates.io-index" 734 | checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" 735 | 736 | [[package]] 737 | name = "windows_i686_gnu" 738 | version = "0.52.6" 739 | source = "registry+https://github.com/rust-lang/crates.io-index" 740 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 741 | 742 | [[package]] 743 | name = "windows_i686_gnu" 744 | version = "0.53.0" 745 | source = "registry+https://github.com/rust-lang/crates.io-index" 746 | checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" 747 | 748 | [[package]] 749 | name = "windows_i686_gnullvm" 750 | version = "0.52.6" 751 | source = "registry+https://github.com/rust-lang/crates.io-index" 752 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 753 | 754 | [[package]] 755 | name = "windows_i686_gnullvm" 756 | version = "0.53.0" 757 | source = "registry+https://github.com/rust-lang/crates.io-index" 758 | checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" 759 | 760 | [[package]] 761 | name = "windows_i686_msvc" 762 | version = "0.52.6" 763 | source = "registry+https://github.com/rust-lang/crates.io-index" 764 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 765 | 766 | [[package]] 767 | name = "windows_i686_msvc" 768 | version = "0.53.0" 769 | source = "registry+https://github.com/rust-lang/crates.io-index" 770 | checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" 771 | 772 | [[package]] 773 | name = "windows_x86_64_gnu" 774 | version = "0.52.6" 775 | source = "registry+https://github.com/rust-lang/crates.io-index" 776 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 777 | 778 | [[package]] 779 | name = "windows_x86_64_gnu" 780 | version = "0.53.0" 781 | source = "registry+https://github.com/rust-lang/crates.io-index" 782 | checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" 783 | 784 | [[package]] 785 | name = "windows_x86_64_gnullvm" 786 | version = "0.52.6" 787 | source = "registry+https://github.com/rust-lang/crates.io-index" 788 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 789 | 790 | [[package]] 791 | name = "windows_x86_64_gnullvm" 792 | version = "0.53.0" 793 | source = "registry+https://github.com/rust-lang/crates.io-index" 794 | checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" 795 | 796 | [[package]] 797 | name = "windows_x86_64_msvc" 798 | version = "0.52.6" 799 | source = "registry+https://github.com/rust-lang/crates.io-index" 800 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 801 | 802 | [[package]] 803 | name = "windows_x86_64_msvc" 804 | version = "0.53.0" 805 | source = "registry+https://github.com/rust-lang/crates.io-index" 806 | checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" 807 | --------------------------------------------------------------------------------