gdritter repos utmyen / 2596b67
Some inital work towards model-loading; two small configuration languages Getty Ritter 8 years ago
7 changed file(s) with 380 addition(s) and 0 deletion(s). Collapse all Expand all
1 [package]
2 name = "utmyen"
3 version = "0.1.0"
4 authors = ["Getty Ritter <gdritter@galois.com>"]
5
6 [dependencies]
1 # strawman configuration example.
2 # Every crop will have:
3 {
4 # ...a name
5 name "Starberry"
6 # ...the number of days it takes to grow
7 growth_time 7
8 # ...a set of properties
9 properties {
10 light true
11 fruit true
12 }
13 # ...a bit of descriptive in-game text
14 description [
15 "The starberry is a beautiful, bright yellow fruit that glows "
16 "ever-so-slightly in the darkness."
17 ]
18 }
1 use std::collections::HashMap;
2 use std::iter::Peekable;
3 use std::str::{Chars,FromStr};
4
5 #[derive(Clone,Debug,PartialEq)]
6 pub enum Adnot {
7 Sum(String, Vec<Adnot>),
8 Prod(HashMap<String, Adnot>),
9 List(Vec<Adnot>),
10 Str(String),
11 Sym(String),
12 Num(i64),
13 Dbl(f64),
14 }
15
16 #[derive(Debug)]
17 pub struct AdnotError {
18 message: String,
19 }
20
21 type Stream<'a> = Peekable<Chars<'a>>;
22
23 fn fail<T>(s: &str) -> Result<T, AdnotError> {
24 Err(AdnotError { message: s.to_string()})
25 }
26
27 fn parse_val(s: &mut Stream) -> Result<Adnot, AdnotError> {
28 if let Some(c) = s.next() {
29 match c {
30 '[' => parse_list(s),
31 '(' => parse_sum(s),
32 '{' => parse_prod(s),
33 '"' => parse_string(s),
34 _ if c.is_digit(10) || c == '-' => parse_num(c, s),
35 _ if c.is_alphabetic() =>
36 Ok(Adnot::Sym(try!(parse_sym(c, s)))),
37 _ => fail(&format!("Invalid character: {:?}", c)),
38 }
39 } else {
40 fail("Unexpected end of input")
41 }
42 }
43
44 fn parse_list(s: &mut Stream) -> Result<Adnot, AdnotError> {
45 let mut vec = vec![];
46 loop {
47 skip_space(s);
48 if let Some(&']') = s.peek() {
49 s.next();
50 return Ok(Adnot::List(vec));
51 } else {
52 vec.push(try!(parse_val(s)));
53 }
54 }
55 }
56
57 fn parse_sum(s: &mut Stream) -> Result<Adnot, AdnotError> {
58 let mut vec = vec![];
59 skip_space(s);
60 let first = match s.next() {
61 Some(c) if c.is_alphabetic() => c,
62 Some(c) => { return fail("Expected a tagname character") }
63 None => { return fail("Unexpected end of input") }
64 };
65 let name = try!(parse_sym(first, s));
66 loop {
67 skip_space(s);
68 if let Some(&')') = s.peek() {
69 s.next();
70 return Ok(Adnot::Sum(name, vec));
71 } else {
72 vec.push(try!(parse_val(s)));
73 }
74 }
75 }
76
77 fn parse_prod(s: &mut Stream) -> Result<Adnot, AdnotError> {
78 let mut map = HashMap::new();
79 loop {
80 skip_space(s);
81 if let Some(&'}') = s.peek() {
82 s.next();
83 return Ok(Adnot::Prod(map));
84 } else {
85 skip_space(s);
86 let first = match s.next() {
87 Some(c) if c.is_alphabetic() => c,
88 Some(c) => { return fail("Expected a tagname character") }
89 None => { return fail("Unexpected end of input") }
90 };
91 let key = try!(parse_sym(first, s));
92 skip_space(s);
93 let val = try!(parse_val(s));
94 map.insert(key, val);
95 }
96 }
97 }
98
99 fn parse_string(s: &mut Stream) -> Result<Adnot, AdnotError> {
100 let mut chars = Vec::new();
101 while let Some(c) = s.next() {
102 if c == '"' {
103 break;
104 } else if c == '\\' {
105 match s.next() {
106 Some('n') => chars.push('\n'),
107 Some('r') => chars.push('\r'),
108 Some('t') => chars.push('\t'),
109 Some('\'') => chars.push('\''),
110 Some('\"') => chars.push('\"'),
111 Some('\\') => chars.push('\\'),
112 _ => return fail("Invalid escape sequence"),
113 }
114 } else {
115 chars.push(c);
116 }
117 };
118 Ok(Adnot::Str(chars.iter().cloned().collect()))
119 }
120
121 fn parse_num(c: char, s: &mut Stream) -> Result<Adnot, AdnotError> {
122 let mut str = vec![c];
123 str.extend(s.take_while(|c| c.is_digit(10)));
124 let string: String = str.iter().cloned().collect();
125 Ok(Adnot::Num(i64::from_str(&string).unwrap()))
126 }
127
128 fn parse_sym(c: char, s: &mut Stream) -> Result<String, AdnotError> {
129 let mut chars = vec![c];
130 while let Some(&c) = s.peek() {
131 if c.is_alphanumeric() || c == '_' {
132 chars.push(s.next().unwrap());
133 } else {
134 break;
135 }
136 };
137 Ok(chars.iter().cloned().collect())
138 }
139
140 fn skip_space(s: &mut Stream) {
141 while let Some(&c) = s.peek() {
142 match c {
143 '#' => { skip_comment(s); }
144 _ if c.is_whitespace() => { s.next(); }
145 _ => break,
146 }
147 }
148 }
149
150 fn skip_comment(s: &mut Stream) {
151 s.next();
152 while let Some(&c) = s.peek() {
153 if c == '\n' || c == '\r' {
154 s.next();
155 return;
156 } else {
157 s.next();
158 }
159 }
160 }
161
162 impl Adnot {
163 pub fn parse(s: &str) -> Result<Adnot, AdnotError> {
164 let mut stream = s.chars().peekable();
165 skip_space(&mut stream);
166 parse_val(&mut stream)
167 }
168 }
1 use core::slice::Iter;
2 use std::collections::HashMap;
3 use std::iter::Peekable;
4
5 #[derive(Clone,Debug,PartialEq,Eq)]
6 pub enum Bencode {
7 Int(i64),
8 Str(Vec<u8>),
9 List(Vec<Bencode>),
10 Dict(HashMap<Vec<u8>, Bencode>),
11 }
12
13 type Stream<'a> = Peekable<Iter<'a, u8>>;
14
15 fn fail<T>(s: &str) -> Result<T, String> {
16 Err(s.to_string())
17 }
18
19 fn is_digit(b: u8) -> bool {
20 b >= 0x30 && b < 0x3a
21 }
22
23 fn to_digit_usize(b: u8) -> usize {
24 (b - 0x30) as usize
25 }
26
27 fn to_digit_i64(b: u8) -> i64 {
28 (b - 0x30) as i64
29 }
30
31 fn parse_helper(is: &mut Stream) -> Result<Bencode, String> {
32 match is.next() {
33 Some(&0x69) => {
34 let mut num = 0;
35 for &n in is.take_while(|&&x| is_digit(x)) {
36 num = num * 10 + to_digit_i64(n);
37 }
38 Ok(Bencode::Int(num))
39 },
40 Some(&0x6c) => {
41 let mut list = Vec::new();
42 loop {
43 match is.peek() {
44 Some(&&0x65) => {
45 let _ = is.next();
46 break;
47 }
48 _ => {
49 list.push(try!(parse_helper(is)));
50 }
51 }
52 };
53 Ok(Bencode::List(list))
54 },
55 Some(&0x64) => {
56 let mut dict = HashMap::new();
57 loop {
58 match is.peek() {
59 Some(&&0x65) => {
60 let _ = is.next();
61 break;
62 }
63 Some(&&d) if is_digit(d) => {
64 let _ = is.next();
65 let key = try!(parse_string(d, is));
66 let val = try!(parse_helper(is));
67 dict.insert(key, val);
68 }
69 _ => {
70 return fail("error while parsing dictionary key");
71 }
72 }
73 }
74 Ok(Bencode::Dict(dict))
75 },
76 Some(&c) if is_digit(c) => {
77 Ok(Bencode::Str(try!(parse_string(c, is))))
78 },
79 _ => fail("error while parsing expression"),
80 }
81 }
82
83 fn parse_string(init: u8, is: &mut Stream) -> Result<Vec<u8>, String> {
84 let mut size = to_digit_usize(init);
85 for &n in is.take_while(|&&x| is_digit(x)) {
86 size = size * 10 + to_digit_usize(n);
87 }
88 Ok(is.take(size).cloned().collect())
89 }
90
91 impl Bencode {
92 pub fn parse(bs: &[u8]) -> Result<Bencode, String> {
93 parse_helper(&mut bs.iter().peekable())
94 }
95
96 pub fn get_field(&self, name: &str) -> Result<&Bencode, String> {
97 match self {
98 &Bencode::Dict(ref ds) => {
99 let key = name.as_bytes().to_vec();
100 match ds.get(&key) {
101 Some(r) => Ok(r),
102 None => fail(&format!("no such key: {:?}", name)),
103 }
104 }
105 _ => fail("not a dictionary"),
106 }
107 }
108
109 pub fn get_idx(&self, idx: usize) -> Result<&Bencode, String> {
110 match self {
111 &Bencode::List(ref ds) => {
112 match ds.get(idx) {
113 Some(r) => Ok(r),
114 None => fail(&format!("no such index: {:?}", idx)),
115 }
116 }
117 _ => fail("not a list"),
118 }
119 }
120
121 pub fn as_num(&self) -> Result<i64, String> {
122 match self {
123 &Bencode::Int(n) => Ok(n),
124 _ => fail("not a number"),
125 }
126 }
127 }
1 #[derive(Copy, Clone, Debug)]
2 struct V3 {
3 position: [f32; 3],
4 }
5
6 implement_vertex!(V3, position);
7
8 enum SceneGraph {
9 }
10
11 struct Model {
12 }
1 extern crate core;
2
3 mod adnot;
4 mod bencode;
5 mod model;
6
7 use bencode::Bencode;
8
9 fn main() {
10 let input = "d3:foo3:bare";
11 println!("{:?}", Bencode::parse(&input.to_string().into_bytes()));
12 }
1 use bencode::Bencode;
2
3 #[derive(Copy, Clone)]
4 pub struct V3D {
5 pub pos: [f32; 3],
6 pub tex: [f32; 2],
7 }
8
9 #[derive(Clone)]
10 pub struct Model {
11 pub points: Vec<V3D>,
12 pub tris: Vec<usize>,
13 }
14
15 pub fn load_model(is: &[u8]) -> Result<Model, String> {
16 let bs = try!(Bencode::parse(is));
17 let points_b = try!(bs.get_field("points"));
18 let tris_b = try!(bs.get_field("tris"));
19 let points = vec![];
20 let tris = vec![];
21 Ok(Model {
22 points: points,
23 tris: tris,
24 })
25 }
26
27 fn load_v3d(bs: &Bencode) -> Result<V3D, String> {
28 Ok(V3D {
29 pos: [ try!(try!(bs.get_idx(0)).as_num()) as f32,
30 try!(try!(bs.get_idx(1)).as_num()) as f32,
31 try!(try!(bs.get_idx(2)).as_num()) as f32,
32 ],
33 tex: [ try!(try!(bs.get_idx(3)).as_num()) as f32,
34 try!(try!(bs.get_idx(5)).as_num()) as f32,
35 ]
36 })
37 }