common.rs (2149B)
1 use std::cmp::Ordering; 2 3 #[derive(Debug)] 4 pub enum Packet { 5 Number(i64), 6 List(Vec<Packet>) 7 } 8 9 fn compare_lists(l: &Vec<Packet>, k: &Vec<Packet>) -> Ordering { 10 for i in 0..std::cmp::min(l.len(), k.len()) { 11 let ord = compare(&l[i], &k[i]); 12 if ord != Ordering::Equal { return ord; } 13 } 14 l.len().cmp(&k.len()) 15 } 16 17 fn compare_list_single(l: &Vec<Packet>, p: &Packet) -> Ordering { 18 if l.len() == 0 { return Ordering::Less; } 19 let ord = compare(&l[0], p); 20 if ord != Ordering::Equal { return ord; } 21 l.len().cmp(&1) 22 } 23 24 pub fn compare(p: &Packet, q: &Packet) -> Ordering { 25 match p { 26 Packet::Number(n) => { 27 match q { 28 Packet::Number(m) => n.cmp(&m), 29 Packet::List(k) => compare_list_single(k, p).reverse() 30 } 31 }, 32 Packet::List(l) => { 33 match q { 34 Packet::Number(_) => compare_list_single(l, q), 35 Packet::List(k) => compare_lists(l, k) 36 } 37 } 38 } 39 } 40 41 fn parse_int(line: &[u8], i: &mut usize) -> i64 { 42 let mut r: i64 = 0; 43 loop { 44 match line[*i] { 45 b'0'..=b'9' => r = r * 10 + (line[*i] as i64) - ('0' as i64), 46 b',' | b']' => return r, 47 x => panic!("Error: unexpected '{}' at position {} in parse_int", 48 x as char, *i) 49 } 50 *i += 1; 51 } 52 } 53 54 fn parse_list(line: &[u8], i: &mut usize) -> Packet { 55 if line[*i] != b'[' { 56 panic!("Error: sub-list at {} does not start with '['", *i); 57 } 58 *i += 1; 59 let mut v = Vec::<Packet>::new(); 60 while *i < line.len() && line[*i] != b'\n' { 61 match line[*i] { 62 b']' => { *i += 1; return Packet::List(v); }, 63 b'[' => v.push(parse_list(line, i)), 64 b'0'..=b'9' => v.push(Packet::Number(parse_int(line, i))), 65 b' ' | b',' => *i += 1, 66 x => panic!("Error: unexpected '{}' at position {}", x as char, *i) 67 } 68 } 69 panic!("Error: finished parsing at {}, but ']' not found", *i); 70 } 71 72 pub fn parse(line: &[u8]) -> Packet { 73 let mut i = 0; 74 parse_list(line, &mut i) 75 }