1pub mod controller;
168pub mod detached_command;
169
170#[derive(Debug, Clone, Copy, PartialEq)]
172pub enum Color {
173 W,
174 B,
175}
176
177#[derive(Debug, Clone, PartialEq, Default)]
195pub struct EntityBuilder {
196 list: Vec<Entity>,
197 current: Option<Entity>,
198}
199
200pub fn entity<T>(f: T) -> Entity
210 where T: Fn(&mut EntityBuilder) -> &mut EntityBuilder {
211 let mut b = EntityBuilder::new();
212 f(&mut b);
213 if b.has_any() {
214 b.build()
215 } else {
216 Entity::String(String::from(""))
217 }
218}
219
220impl EntityBuilder {
221 pub fn new() -> EntityBuilder {
226 EntityBuilder::default()
227 }
228
229 pub fn i(&mut self, i: u32) -> &mut Self {
230 if self.current.is_some() { self.list.push(self.current.take().unwrap()); }
231
232 self.current = Some(Entity::Int(i));
233 self
234 }
235
236 pub fn f(&mut self, f: f32) -> &mut Self {
237 if self.current.is_some() { self.list.push(self.current.take().unwrap()); }
238
239 self.current = Some(Entity::Float(f));
240 self
241 }
242
243 pub fn s(&mut self, s: &str) -> &mut Self {
244 if self.current.is_some() { self.list.push(self.current.take().unwrap()); }
245
246 self.current = Some(Entity::String(s.to_string()));
247 self
248 }
249
250 pub fn v_pass(&mut self) -> &mut Self {
251 if self.current.is_some() { self.list.push(self.current.take().unwrap()); }
252
253 self.current = Some(Entity::Vertex((0, 0)));
254 self
255 }
256
257 pub fn v(&mut self, v: (i32, i32)) -> &mut Self {
258 if self.current.is_some() { self.list.push(self.current.take().unwrap()); }
259
260 self.current = Some(Entity::Vertex(v));
261 self
262 }
263
264 pub fn w(&mut self) -> &mut Self {
265 if self.current.is_some() { self.list.push(self.current.take().unwrap()); }
266
267 self.current = Some(Entity::Color(Color::W));
268 self
269 }
270
271 pub fn b(&mut self) -> &mut Self {
272 if self.current.is_some() { self.list.push(self.current.take().unwrap()); }
273
274 self.current = Some(Entity::Color(Color::B));
275 self
276 }
277
278 pub fn bool(&mut self, b: bool) -> &mut Self {
279 if self.current.is_some() { self.list.push(self.current.take().unwrap()); }
280
281 self.current = Some(Entity::Boolean(b));
282 self
283 }
284
285 pub fn color(&mut self, b: bool) -> &mut Self {
286 if self.current.is_some() { self.list.push(self.current.take().unwrap()); }
287
288 self.current = Some(Entity::Color(if b { Color::W } else { Color::B }));
289 self
290 }
291
292 pub fn mv_w(&mut self, v: (i32, i32)) -> &mut Self {
293 if self.current.is_some() { self.list.push(self.current.take().unwrap()); }
294
295 self.current = Some(Entity::Move((Color::W, v)));
296 self
297 }
298
299 pub fn mv_b(&mut self, v: (i32, i32)) -> &mut Self {
300 if self.current.is_some() { self.list.push(self.current.take().unwrap()); }
301
302 self.current = Some(Entity::Move((Color::B, v)));
303 self
304 }
305
306 pub fn mv(&mut self, color: bool, v: (i32, i32)) -> &mut Self {
307 if self.current.is_some() { self.list.push(self.current.take().unwrap()); }
308
309 self.current = Some(Entity::Move((if color { Color::W } else { Color::B }, v)));
310 self
311 }
312
313 pub fn list(&mut self) -> &mut Self {
314 if self.current.is_some() { self.list.push(self.current.take().unwrap()); }
315
316 self.current = Some(Entity::List(self.list.clone()));
317 self.list = Vec::new();
318 self
319 }
320
321 pub fn has_any(&self) -> bool { self.current.is_some() }
322
323 pub fn build(&self) -> Entity {
324 self.current.clone().expect("Did not setup any entitiy in EntityBuilder!")
325 }
326}
327
328#[derive(Debug, Clone, PartialEq)]
329pub enum Entity {
330 Int(u32),
331 Float(f32),
332 String(String),
333 Vertex((i32, i32)),
334 Color(Color),
335 Move((Color, (i32, i32))),
336 Boolean(bool),
337 List(Vec<Entity>),
338}
339
340fn gen_move_char(i: u32) -> char {
341 let c = if i <= 8 {
342 ('A' as u32) + (i - 1)
343 } else {
344 ('A' as u32) + i
345 };
346 if let Some(c) = std::char::from_u32(c) {
347 c
348 } else {
349 'Z'
350 }
351}
352
353impl std::fmt::Display for Entity {
354 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
355 match self {
356 Entity::Int(i) => write!(f, "{}", i),
357 Entity::Float(n) => write!(f, "{}", n),
358 Entity::String(s) => write!(f, "{}", s),
359 Entity::Vertex((h, v)) => {
360 let mut s = String::from("");
361 if *h <= 0 || *v <= 0 {
362 s += &"pass".to_string();
363 } else {
364 s += &format!("{}", gen_move_char(*h as u32));
365 s += &format!("{}", v);
366 }
367 write!(f, "{}", s)
368 },
369 Entity::Color(Color::W) => write!(f, "w"),
370 Entity::Color(Color::B) => write!(f, "b"),
371 Entity::Move((Color::W, (h, v))) => {
372 let mut s = String::from("");
373 if *h <= 0 || *v <= 0 {
374 s += &"w pass".to_string();
375 } else {
376 s += &format!("w {}", gen_move_char(*h as u32));
377 s += &format!("{}", v);
378 }
379 write!(f, "{}", s)
380 },
381 Entity::Move((Color::B, (h, v))) => {
382 let mut s = String::from("");
383 if *h <= 0 || *v <= 0 {
384 s += &"b pass".to_string();
385 } else {
386 s += &format!("b {}", gen_move_char(*h as u32));
387 s += &format!("{}", v);
388 }
389 write!(f, "{}", s)
390 },
391 Entity::Boolean(true) => write!(f, "true"),
392 Entity::Boolean(false) => write!(f, "false"),
393 Entity::List(vec) => {
394
395 let mut s = String::from("");
396 if vec.is_empty() { return write!(f, ""); }
397
398 let sep = if let Entity::List(_) = vec[0] {
401 "\n"
402 } else {
403 " "
404 };
405
406 for (i, e) in vec.iter().enumerate() {
407 if i > 0 { s += sep; }
408 s += &e.to_string();
409 }
410 write!(f, "{}", s)
411 }
412 }
413 }
414}
415
416#[derive(Debug, Clone, PartialEq)]
417pub struct EntityParser {
418 buffer: String,
419 entities: Vec<Entity>,
420 parse_error: bool,
421}
422
423impl std::iter::Iterator for EntityParser {
424 type Item = String;
425
426 fn next(&mut self) -> Option<String> {
427 self.buffer = self.buffer.chars().skip_while(|c| *c == ' ' || *c == '\n').collect();
428
429 let mut s = String::from("");
430 let mut skip_count = 0;
431 for c in self.buffer.chars() {
432 skip_count += 1;
433 if c == ' ' || c == '\n' { break; }
434 s.push(c);
435 }
436
437 self.buffer = self.buffer.chars().skip(skip_count).collect();
438
439 if s.is_empty() { None } else { Some(s) }
440 }
441
442}
443
444impl EntityParser {
445 pub fn new(s: &str) -> Self {
446 EntityParser {
447 buffer: String::from(s),
448 entities: Vec::new(),
449 parse_error: false,
450 }
451 }
452
453 pub fn result(&self) -> Option<Vec<Entity>> {
454 if self.parse_error { return None; }
455 Some(self.entities.clone())
456 }
457
458 pub fn is_eof(&self) -> bool { self.buffer.is_empty() }
459 pub fn had_parse_error(&self) -> bool { self.parse_error }
460
461 pub fn s(&mut self) -> &mut Self {
462 let s = self.next().unwrap_or_else(|| String::from(""));
463 if s.is_empty() { self.parse_error = true; return self; }
464 self.entities.push(Entity::String(s));
465 self
466 }
467
468 pub fn i(&mut self) -> &mut Self {
469 let s = self.next().unwrap_or_else(|| String::from(""));
470 if let Ok(i) = s.parse::<u32>() {
471 self.entities.push(Entity::Int(i));
472 } else {
473 self.parse_error = true;
474 }
475 self
476 }
477
478 pub fn f(&mut self) -> &mut Self {
479 let s = self.next().unwrap_or_else(|| String::from(""));
480 if let Ok(f) = s.parse::<f32>() {
481 self.entities.push(Entity::Float(f));
482 } else {
483 self.parse_error = true;
484 }
485 self
486 }
487
488 pub fn color(&mut self) -> &mut Self {
489 let s = self.next().unwrap_or_else(|| String::from(""));
490 let s = s.to_lowercase();
491 if s == "w" || s == "white" { self.entities.push(Entity::Color(Color::W)); return self; }
492 if s == "b" || s == "black" { self.entities.push(Entity::Color(Color::B)); return self; }
493 self.parse_error = true;
494 self
495 }
496
497 pub fn vertex(&mut self) -> &mut Self {
498 let s = self.next().unwrap_or_else(|| String::from(""));
499 let s = s.to_uppercase();
500 if s == "PASS" { self.entities.push(Entity::Vertex((0, 0))); return self; }
501 if s.len() < 2 || s.len() > 3 {
502 self.parse_error = true;
503 return self;
504 }
505
506 let h = s.chars().nth(0).unwrap();
507 if !h.is_ascii_alphabetic() {
508 self.parse_error = true;
509 return self;
510 }
511 let h = h as u32;
512 let mut h = (h - ('A' as u32)) + 1;
513 if h > 8 { h -= 1; }
514
515 let v : String = s.chars().skip(1).collect();
516 if let Ok(v) = i32::from_str_radix(&v, 10) {
517 self.entities.push(Entity::Vertex((h as i32, v)));
518 } else {
519 self.parse_error = true;
520 }
521
522 self
523 }
524
525 pub fn mv(&mut self) -> &mut Self {
526 self.color();
527 if self.parse_error { return self; }
528 self.vertex();
529 if self.parse_error { self.entities.pop(); }
530
531 let m = self.entities.pop().unwrap();
532 let c = self.entities.pop().unwrap();
533
534 if let Entity::Vertex((h, v)) = m {
535 if let Entity::Color(c) = c {
536 self.entities.push(Entity::Move((c, (h, v))));
537 return self;
538 }
539 }
540
541 self.parse_error = true;
542 self
543 }
544
545 pub fn bool(&mut self) -> &mut Self {
546 let s = self.next().unwrap_or_else(|| String::from(""));
547 let s = s.to_uppercase();
548 if s == "TRUE" { self.entities.push(Entity::Boolean(true)); return self; }
549 if s == "FALSE" { self.entities.push(Entity::Boolean(false)); return self; }
550 self.parse_error = true;
551 self
552 }
553}
554
555#[derive(Debug, Clone, PartialEq)]
557pub struct Command {
558 id: Option<u32>,
559 name: String,
560 args: Option<Entity>,
561}
562
563impl Command {
564 pub fn new(name: &str) -> Command {
578 Command {
579 name: String::from(name),
580 id: None,
581 args: None,
582 }
583 }
584
585 pub fn new_with_args<T>(name: &str, args: T) -> Command
594 where T: Fn(&mut EntityBuilder) -> &mut EntityBuilder {
595 let mut cmd = Self::new(name);
596 cmd.args(args);
597 cmd
598 }
599
600 pub fn cmd<T>(name: &str, args: T) -> Command
602 where T: Fn(&mut EntityBuilder) -> &mut EntityBuilder {
603 Command::new_with_args(name, args)
604 }
605
606 pub fn set_id(&mut self, id: u32) {
616 self.id = Some(id);
617 }
618
619 pub fn args<T>(&mut self, f: T)
629 where T: Fn(&mut EntityBuilder) -> &mut EntityBuilder {
630 let mut b = EntityBuilder::new();
631 f(&mut b);
632 if b.has_any() {
633 self.set_args(&b.build());
634 }
635 }
636
637
638 pub fn set_args(&mut self, args: &Entity) {
647 self.args = Some(args.clone());
648 }
649
650 pub fn to_string(&self) -> String {
652 let mut out = String::from("");
653 if self.id.is_some() {
654 out += &format!("{}", self.id.unwrap());
655 out += " ";
656 }
657 out += &self.name;
658
659 if self.args.is_some() {
660 out += " ";
661 out += &self.args.as_ref().unwrap().to_string();
662 }
663 out += "\n";
664 out
665 }
666
667 #[allow(dead_code)]
670 pub fn to_bytes(&self) -> Vec<u8> {
671 Vec::from(self.to_string().as_bytes())
672 }
673}
674
675#[derive(Debug, Clone, PartialEq)]
677pub enum Response {
678 Error((Option<u32>, String)),
679 Result((Option<u32>, String)),
680}
681
682#[derive(Debug)]
683pub enum ResponseParseError {
684 NoInput,
685 BadEntityInput,
686 BadResponse
687}
688
689impl Response {
690 pub fn text(&self) -> String {
694 match self {
695 Response::Error((_, t)) => t.clone(),
696 Response::Result((_, t)) => t.clone(),
697 }
698 }
699
700 pub fn id_0(&self) -> u32 {
703 match self {
704 Response::Error((None, _)) => 0,
705 Response::Result((None, _)) => 0,
706 Response::Error((Some(id), _)) => *id,
707 Response::Result((Some(id), _)) => *id,
708 }
709 }
710
711 pub fn entities<T>(&self, parse_fn: T) -> Result<Vec<Entity>, ResponseParseError>
741 where T: Fn(&mut EntityParser) -> &mut EntityParser {
742
743 let response = match self {
744 Response::Result((_, res)) => res.to_string(),
745 Response::Error((_, res)) => res.to_string(),
746 };
747
748 let mut ep = EntityParser::new(&response);
749 parse_fn(&mut ep);
750 if ep.had_parse_error() {
751 return Err(ResponseParseError::BadEntityInput);
752 }
753 Ok(ep.result().unwrap())
754 }
755}
756
757#[derive(Debug, Clone, PartialEq, Default)]
759pub struct ResponseParser {
760 buffer: String,
761}
762
763#[derive(Debug, Clone, PartialEq)]
765pub enum ResponseError {
766 IncompleteResponse,
767 BadResponse(String),
768}
769
770fn refine_input(s: String) -> String {
771 let mut ret : String =
772 s.chars()
773 .filter(|c| *c != '\r')
774 .map(|c| if c == '\x09' { ' ' } else { c })
775 .skip_while(|c| *c == '\n' || *c == ' ' || *c == '\x09')
776 .collect();
777
778 loop {
779 let comment_pos = ret.find('#');
780 if comment_pos.is_some() {
781 let end_comment_pos = (&ret[comment_pos.unwrap()..]).find('\n');
782 if end_comment_pos.is_some() {
783 ret = String::from(&ret[..comment_pos.unwrap()])
784 + &ret[comment_pos.unwrap() + end_comment_pos.unwrap() + 1..];
785 } else {
786 break;
787 }
788 } else {
789 break;
790 }
791 }
792
793 ret
794}
795
796impl ResponseParser {
797 pub fn new() -> ResponseParser {
806 ResponseParser::default()
807 }
808
809 pub fn feed(&mut self, s: &str) {
811 self.buffer += s;
812 }
813
814 #[allow(unused_assignments, clippy::collapsible_if)]
820 pub fn get_response(&mut self) -> Result<Response, ResponseError> {
821 self.buffer = refine_input(self.buffer.to_string());
822 if self.buffer.is_empty() { return Err(ResponseError::IncompleteResponse); }
823
824 let is_error = self.buffer.chars().nth(0).unwrap() != '=';
825
826 let mut id_str = String::from("");
827 let mut response = String::from("");
828
829 let mut read_id =
830 !( self.buffer.len() > 1
831 && self.buffer.chars().nth(1).unwrap() == ' ');
832
833 let mut found_start = false;
834 let mut found_end = false;
835 let mut last_was_newline = false;
836 let mut skip_count = 1;
837
838 for c in self.buffer.chars().skip(1) {
839 skip_count += 1;
840
841 if read_id {
842 match c {
843 c if c.is_ascii_digit() => {
844 id_str.push(c);
845 },
846 ' ' => {
847 found_start = true;
848 read_id = false;
849 },
850 _ => { return Err(ResponseError::BadResponse(self.buffer.to_string())); }
851 }
852 } else if !found_start {
853 if c == ' ' {
854 found_start = true;
855 } else {
856 return Err(ResponseError::BadResponse(self.buffer.to_string()));
857 }
858 } else {
859 if c == '\n' {
860 if last_was_newline {
861 found_end = true;
862 break;
863 } else {
864 last_was_newline = true;
865 }
866 } else {
867 if last_was_newline {
868 response.push('\n');
869 }
870 last_was_newline = false;
871 response.push(c);
872 }
873 }
874 }
875
876 if found_end {
877 self.buffer = self.buffer.chars().skip(skip_count).collect();
878 } else {
879 return Err(ResponseError::IncompleteResponse);
880 }
881
882 let id = if !id_str.is_empty() {
883 if let Ok(cn) = u32::from_str_radix(&id_str, 10) {
884 Some(cn)
885 } else {
886 None
887 }
888 } else {
889 None
890 };
891
892 if is_error {
893 Ok(Response::Error((id, response)))
894 } else {
895 Ok(Response::Result((id, response)))
896 }
897 }
898}
899
900#[cfg(test)]
901mod tests {
902 use super::*;
903
904 #[test]
905 fn check_printing() {
906 assert_eq!(Entity::Int(10).to_string(), "10");
907 assert_eq!(Entity::Float(10.12).to_string(), "10.12");
908 assert_eq!(Entity::String(String::from("Test")).to_string(), "Test");
909 assert_eq!(Entity::Vertex((-1, -1)).to_string(), "pass");
910 assert_eq!(Entity::Vertex((1, 1)).to_string(), "A1");
911 assert_eq!(Entity::Vertex((19, 19)).to_string(), "T19");
912 assert_eq!(Entity::Vertex((8, 19)).to_string(), "H19");
913 assert_eq!(Entity::Vertex((9, 19)).to_string(), "J19");
914 assert_eq!(Entity::Color(Color::W).to_string(), "w");
915 assert_eq!(Entity::Color(Color::B).to_string(), "b");
916 assert_eq!(Entity::Move((Color::B, (0, 0))).to_string(), "b pass");
917 assert_eq!(Entity::Move((Color::W, (0, 0))).to_string(), "w pass");
918 assert_eq!(Entity::Move((Color::B, (8, 1))).to_string(), "b H1");
919 assert_eq!(Entity::Move((Color::W, (9, 1))).to_string(), "w J1");
920 assert_eq!(Entity::Move((Color::B, (19, 1))).to_string(), "b T1");
921 assert_eq!(Entity::Move((Color::W, (19, 19))).to_string(), "w T19");
922 assert_eq!(Entity::Boolean(true).to_string(), "true");
923 assert_eq!(Entity::Boolean(false).to_string(), "false");
924 assert_eq!(Entity::List(vec![Entity::Int(1), Entity::Int(2)]).to_string(),
925 "1 2");
926 assert_eq!(Entity::List(vec![
927 Entity::List(vec![Entity::Int(1), Entity::Int(2)]),
928 Entity::List(vec![Entity::Int(3), Entity::Int(4)])]).to_string(),
929 "1 2\n3 4");
930 }
931
932 #[test]
933 fn check_entity_builder() {
934 assert_eq!(entity(|eb| eb.i(10)).to_string(), "10");
935 assert_eq!(entity(|eb| eb.f(10.12)).to_string(), "10.12");
936 assert_eq!(entity(|eb| eb.s("ok")).to_string(), "ok");
937 assert_eq!(entity(|eb| eb.v_pass()).to_string(), "pass");
938 assert_eq!(entity(|eb| eb.v((19, 19))).to_string(), "T19");
939 assert_eq!(entity(|eb| eb.bool(false)).to_string(), "false");
940 assert_eq!(entity(|eb| eb.w()).to_string(), "w");
941 assert_eq!(entity(|eb| eb.b()).to_string(), "b");
942 assert_eq!(entity(|eb| eb.color(true)).to_string(), "w");
943 assert_eq!(entity(|eb| eb.color(false)).to_string(), "b");
944 assert_eq!(entity(|eb| eb.mv_w((8, 8))).to_string(), "w H8");
945 assert_eq!(entity(|eb| eb.mv_b((8, 8))).to_string(), "b H8");
946 assert_eq!(entity(|eb| eb.mv(true, (8, 8))).to_string(),"w H8");
947 assert_eq!(entity(|eb| eb.mv_w((8, 8)).mv_b((9, 9)).list()).to_string(),
948 "w H8 b J9");
949 }
950
951 #[test]
952 fn check_entity_parser() {
953 let mut ep = EntityParser::new("10 10.2 ok WHite t19 false");
954 ep.i().f().s().mv().bool();
955 let res = ep.result().unwrap();
956 assert_eq!(res[0].to_string(), "10");
957 assert_eq!(res[1].to_string(), "10.2");
958 assert_eq!(res[2].to_string(), "ok");
959 assert_eq!(res[3].to_string(), "w T19");
960 assert_eq!(res[4].to_string(), "false");
961 }
962
963 #[test]
964 fn check_eof() {
965 let mut ep = EntityParser::new("t19 b10 a1 d2");
966 while !ep.is_eof() {
967 ep.vertex();
968 }
969 let res = ep.result().unwrap();
970 assert_eq!(res[3].to_string(), "D2");
971 }
972
973 #[test]
974 fn check_build_command() {
975 let mut c = Command::new("list_commands");
976 c.args(|eb| eb.i(10).f(10.20).s("OK").list());
977 assert_eq!(c.to_string(), "list_commands 10 10.2 OK\n");
978
979 assert_eq!(
980 Command::new_with_args("boardsize", |eb| eb.i(9)).to_string(),
981 "boardsize 9\n");
982 }
983
984 #[test]
985 fn check_setid_command() {
986 let mut c = Command::new("list_commands");
987 c.set_id(12);
988 assert_eq!(c.to_string(), "12 list_commands\n");
989 }
990
991 fn must_parse(s: &str) -> Response {
992 let mut rp = ResponseParser::new();
993 rp.feed(s);
994 let s = rp.get_response().unwrap();
995 s
996 }
997
998 #[test]
999 fn check_parser() {
1000 {
1001 let mut rp = ResponseParser::new();
1002 rp.feed("= ok\n\n");
1003 let s = rp.get_response().unwrap();
1004 assert_eq!(format!("{:?}", s), "Result((None, \"ok\"))");
1005 }
1006
1007 {
1008 let mut rp = ResponseParser::new();
1009 rp.feed("= ok\n\n");
1010 rp.feed("= \n\n");
1011
1012 assert_eq!(rp.get_response().unwrap().text(), "ok");
1013 }
1014
1015 {
1016 let mut rp = ResponseParser::new();
1017 rp.feed("= ok\n");
1018
1019 assert!(rp.get_response().is_err());
1020 }
1021
1022 let res = must_parse("= ok\nfoobar\n\n");
1023 assert_eq!(res.text(), "ok\nfoobar");
1024
1025 assert_eq!(format!("{:?}", must_parse("=10 ok\n\n")),
1026 "Result((Some(10), \"ok\"))");
1027
1028 assert_eq!(format!("{:?}", must_parse("#\n=10 ok\n\n")),
1029 "Result((Some(10), \"ok\"))");
1030
1031 assert_eq!(format!("{:?}", must_parse("= ok\n\n")),
1032 "Result((None, \"ok\"))");
1033
1034 assert_eq!(format!("{:?}", must_parse("= \n\n")),
1035 "Result((None, \"\"))");
1036
1037 assert_eq!(format!("{:?}", must_parse("= \na\nb\nc\n\n")),
1038 "Result((None, \"\\na\\nb\\nc\"))");
1039
1040 assert_eq!(format!("{:?}", must_parse("= foo # all ok\n\n\n")),
1041 "Result((None, \"foo \"))");
1042
1043 assert_eq!(format!("{:?}", must_parse("= \na\nb fooo #fewiofw jfw\nc\n\n")),
1044 "Result((None, \"\\na\\nb fooo c\"))");
1045 }
1046
1047}