1use std::collections::HashMap;
2use std::hash::Hasher;
3use std::rc::Rc;
4use std::cell::{Cell, RefCell};
5use std::fmt;
6use std::error::Error;
7use std::fmt::Display;
8use std::str::FromStr;
9use std::borrow::Cow;
10use internals::parser::Parser;
11use nom::IResult;
12
13#[derive(Debug, Eq, PartialEq, Clone)]
15pub enum ParseResult<'a> {
16 Full,
18 FullError(Rc<RefCell<Vec<ParseError<'a>>>>),
20 Partial(Cow<'a, str>, usize, usize),
24 PartialError(Cow<'a, str>, usize, usize, Rc<RefCell<Vec<ParseError<'a>>>>),
28 Failure(usize, usize),
31}
32
33#[derive(Debug, Eq, PartialEq, Clone)]
35pub enum ParseError<'a> {
36 MixedArray(String, usize, usize),
41 DuplicateKey(String, usize, usize, Value<'a>),
45 InvalidTable(String, usize, usize, RefCell<HashMap<String, Value<'a>>>),
50 InvalidDateTime(String, usize, usize, Cow<'a, str>),
65 IntegerOverflow(String, usize, usize, Cow<'a, str>),
67 IntegerUnderflow(String, usize, usize, Cow<'a, str>),
69 InvalidInteger(String, usize, usize, Cow<'a, str>),
71 Infinity(String, usize, usize, Cow<'a, str>),
73 NegativeInfinity(String, usize, usize, Cow<'a, str>),
75 LossOfPrecision(String, usize, usize, Cow<'a, str>),
78 InvalidFloat(String, usize, usize, Cow<'a, str>),
80 InvalidBoolean(String, usize, usize, Cow<'a, str>),
82 InvalidString(String, usize, usize, Cow<'a, str>, StrType),
84 GenericError(String, usize, usize, Option<Cow<'a, str>>, String),
87}
88
89#[derive(Debug, PartialEq, Eq, Clone)]
91pub enum Value<'a> {
92 Integer(Cow<'a, str>),
94 Float(Cow<'a, str>),
97 Boolean(bool),
99 DateTime(DateTime<'a>),
102 String(Cow<'a, str>, StrType),
105 Array(Rc<Vec<Value<'a>>>),
107 InlineTable(Rc<Vec<(Cow<'a, str>, Value<'a>)>>)
110}
111
112#[derive(Debug, Eq, PartialEq, Copy, Clone)]
114pub enum StrType {
115 Basic,
117 MLBasic,
119 Literal,
121 MLLiteral,
123}
124
125#[derive(Debug, Eq, PartialEq, Clone)]
127pub enum Children {
128 Count(Cell<usize>),
146 Keys(RefCell<Vec<String>>)
160}
161
162impl Children {
164
165 pub fn combine_keys<S>(base_key: S, child_key: S) -> String where S: Into<String> {
187 let mut full_key;
188 let base = base_key.into();
189 let child = child_key.into();
190 if base != "" {
191 full_key = base.clone();
192 full_key.push('.');
193 full_key.push_str(&child);
194 } else {
195 full_key = child.clone();
196 }
197 return full_key;
198 }
199
200 pub fn combine_keys_index<S>(base_key: S, child_key: usize) -> String where S: Into<String> {
221 return format!("{}[{}]", base_key.into(), child_key);
222 }
223
224 pub fn combine_child_keys<S>(&self, base_key: S) -> Vec<String> where S: Into<String> {
245 let mut all_keys = vec![];
246 let base = base_key.into();
247 match self {
248 &Children::Count(ref c) => {
249 for i in 0..c.get() {
250 all_keys.push(format!("{}[{}]", base, i));
251 }
252 },
253 &Children::Keys(ref hs_rc) => {
254 for subkey in hs_rc.borrow().iter() {
255 if base != "" {
256 let mut full_key = base.clone();
257 full_key.push('.');
258 full_key.push_str(&subkey);
259 all_keys.push(full_key);
260 } else {
261 all_keys.push(subkey.clone());
262 }
263 }
264 },
265 }
266 return all_keys;
267 }
268}
269
270impl<'a> Display for Value<'a> {
275 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
276 match self {
277 &Value::Integer(ref v) | &Value::Float(ref v) =>
278 write!(f, "{}", v),
279 &Value::Boolean(ref b) => write!(f, "{}", b),
280 &Value::DateTime(ref v) => write!(f, "{}", v),
281 &Value::Array(ref arr) => {
282 try!(write!(f, "["));
283 for i in 0..arr.len() - 1 {
284 try!(write!(f, "{}, ", arr[i]));
285 }
286 if arr.len() > 0 {
287 try!(write!(f, "{}", arr[arr.len()-1]));
288 }
289 write!(f, "]")
290 },
291 &Value::String(ref s, ref t) => {
292 match t {
293 &StrType::Basic => write!(f, "\"{}\"", s),
294 &StrType::MLBasic => write!(f, "\"\"\"{}\"\"\"", s),
295 &StrType::Literal => write!(f, "'{}'", s),
296 &StrType::MLLiteral => write!(f, "'''{}'''", s),
297 }
298 },
299 &Value::InlineTable(ref it) => {
300 try!(write!(f, "{{"));
301 for i in 0..it.len() - 1 {
302 try!(write!(f, "{} = {}, ", it[i].0, it[i].1));
303 }
304 if it.len() > 0 {
305 try!(write!(f, "{} = {}", it[it.len()-1].0, it[it.len()-1].1));
306 }
307 write!(f, "}}")
308 }
309 }
310 }
311}
312
313impl<'a> Value<'a> {
314
315 pub fn int(int: i64) -> Value<'a> {
326 Value::Integer(format!("{}", int).into())
327 }
328
329 pub fn int_from_str<S>(int: S) -> Result<Value<'a>, TOMLError> where S: Into<String> + Clone {
340 let result = Value::Integer(int.clone().into().into());
341 if result.validate() {
342 return Result::Ok(result);
343 } else {
344 return Result::Err(TOMLError::new(format!("Error parsing int. Argument: {}", int.into())));
345 }
346 }
347
348 pub fn float(float: f64) -> Value<'a> {
359 Value::Float(format!("{}", float).into())
360 }
361
362 pub fn float_from_str<S>(float: S) -> Result<Value<'a>, TOMLError> where S: Into<String> + Clone {
374 let result = Value::Float(float.clone().into().into());
375 if result.validate() {
376 return Result::Ok(result);
377 } else {
378 return Result::Err(TOMLError::new(format!("Error parsing float. Argument: {}", float.into())));
379 }
380 }
381
382 pub fn bool(b: bool) -> Value<'a> {
393 Value::Boolean(b)
394 }
395 pub fn bool_from_str<S>(b: S) -> Result<Value<'a>, TOMLError> where S: Into<String> + Clone {
396 let lower = b.clone().into().to_lowercase();
397 if lower == "true" {
398 Result::Ok(Value::Boolean(true))
399 } else if lower == "false" {
400 Result::Ok(Value::Boolean(false))
401 } else {
402 return Result::Err(TOMLError::new(
403 format!("Error parsing bool. Argument: {}", b.into())
404 ))
405 }
406 }
407
408 pub fn date_from_int(year: usize, month: usize, day: usize) -> Result<Value<'a>, TOMLError> {
420 let y = format!("{:0>4}", year);
421 let m = format!("{:0>2}", month);
422 let d = format!("{:0>2}", day);
423 match Date::from_str(y, m, d) {
424 Ok(date) => {
425 Ok(Value::DateTime(DateTime::new(date, None)))
426 },
427 Err(error) => Err(error),
428 }
429 }
430
431 pub fn date_from_str<S>(year: S, month: S, day: S) -> Result<Value<'a>, TOMLError> where S: Into<String> + Clone {
443 match Date::from_str(year.clone().into(), month.clone().into(), day.clone().into()) {
444 Ok(date) => {
445 Ok(Value::DateTime(DateTime::new(date, None)))
446 },
447 Err(error) => Err(error),
448 }
449 }
450
451 pub fn datetime_from_int(year: usize, month: usize, day: usize, hour: usize, minute: usize, second: usize) -> Result<Value<'a>, TOMLError> {
464 let y = format!("{:0>4}", year);
465 let m = format!("{:0>2}", month);
466 let d = format!("{:0>2}", day);
467 let h = format!("{:0>2}", hour);
468 let min = format!("{:0>2}", minute);
469 let s = format!("{:0>2}", second);
470 match Date::from_str(y, m, d) {
471 Ok(date) => {
472 match Time::from_str(h, min, s, None, None) {
473 Ok(time) => Ok(Value::DateTime(DateTime::new(date, Some(time)))),
474 Err(error) => Err(error),
475 }
476 },
477 Err(error) => Err(error),
478 }
479 }
480
481 pub fn datetime_from_str<S>(year: S, month: S, day: S, hour: S, minute: S, second: S) -> Result<Value<'a>, TOMLError> where S: Into<String> + Clone {
494 match Date::from_str(year.clone().into(), month.clone().into(), day.clone().into()) {
495 Ok(date) => {
496 match Time::from_str(hour.clone().into(), minute.clone().into(), second.clone().into(), None, None) {
497 Ok(time) => Ok(Value::DateTime(DateTime::new(date, Some(time)))),
498 Err(error) => Err(error),
499 }
500 },
501 Err(error) => Err(error),
502 }
503 }
504
505 pub fn datetime_frac_from_int(year: usize, month: usize, day: usize, hour: usize, minute: usize, second: usize, frac: usize) -> Result<Value<'a>, TOMLError> {
520 let y = format!("{:0>4}", year);
521 let m = format!("{:0>2}", month);
522 let d = format!("{:0>2}", day);
523 let h = format!("{:0>2}", hour);
524 let min = format!("{:0>2}", minute);
525 let s = format!("{:0>2}", second);
526 let f = format!("{}", frac);
527 match Date::from_str(y, m, d) {
528 Ok(date) => {
529 match Time::from_str(h, min, s, Some(f), None) {
530 Ok(time) => Ok(Value::DateTime(DateTime::new(date, Some(time)))),
531 Err(error) => Err(error),
532 }
533 },
534 Err(error) => Err(error),
535 }
536 }
537
538 pub fn datetime_frac_from_str<S>(year: S, month: S, day: S, hour: S, minute: S, second: S, frac: S) -> Result<Value<'a>, TOMLError> where S: Into<String> + Clone{
551 match Date::from_str(year.clone().into(), month.clone().into(), day.clone().into()) {
552 Ok(date) => {
553 match Time::from_str(hour.clone().into(), minute.clone().into(), second.clone().into(), Some(frac.clone().into()), None) {
554 Ok(time) => Ok(Value::DateTime(DateTime::new(date, Some(time)))),
555 Err(error) => Err(error),
556 }
557 },
558 Err(error) => Err(error),
559 }
560 }
561
562 pub fn datetime_offset_from_int(year: usize, month: usize, day: usize, hour: usize, minute: usize, second: usize, posneg: char, off_hour: usize, off_minute: usize) -> Result<Value<'a>, TOMLError> {
578 let y = format!("{:0>4}", year);
579 let m = format!("{:0>2}", month);
580 let d = format!("{:0>2}", day);
581 let h = format!("{:0>2}", hour);
582 let min = format!("{:0>2}", minute);
583 let s = format!("{:0>2}", second);
584 let oh = format!("{:0>2}", off_hour);
585 let omin = format!("{:0>2}", off_minute);
586 let mut pn = "".to_string();
587 pn.push(posneg);
588 match Date::from_str(y, m, d) {
589 Ok(date) => {
590 match TimeOffsetAmount::from_str(pn, oh, omin) {
591 Ok(offset) => {
592 match Time::from_str(h, min, s, None, Some(TimeOffset::Time(offset))) {
593 Ok(time) => Ok(Value::DateTime(DateTime::new(date, Some(time)))),
594 Err(error) => Err(error),
595 }
596 },
597 Err(error) => Result::Err(error),
598 }
599 },
600 Err(error) => Err(error),
601 }
602 }
603
604 pub fn datetime_offset_from_str<S>(year: S, month: S, day: S, hour: S, minute: S, second: S, posneg: S, off_hour: S, off_minute: S) -> Result<Value<'a>, TOMLError> where S: Into<String> + Clone{
619 match Date::from_str(year.clone().into(), month.clone().into(), day.clone().into()) {
620 Ok(date) => {
621 match TimeOffsetAmount::from_str(posneg.clone().into(), off_hour.clone().into(), off_minute.clone().into()) {
622 Ok(offset) => {
623 match Time::from_str(hour.clone().into(), minute.clone().into(), second.clone().into(), None, Some(
624 TimeOffset::Time(offset)
625 )) {
626 Ok(time) => Ok(Value::DateTime(DateTime::new(date, Some(time)))),
627 Err(error) => Err(error),
628 }
629 },
630 Err(error) => Result::Err(error),
631 }
632 },
633 Err(error) => Err(error),
634 }
635 }
636
637 pub fn datetime_zulu_from_int(year: usize, month: usize, day: usize, hour: usize, minute: usize, second: usize) -> Result<Value<'a>, TOMLError> {
650 let y = format!("{:0>4}", year);
651 let m = format!("{:0>2}", month);
652 let d = format!("{:0>2}", day);
653 let h = format!("{:0>2}", hour);
654 let min = format!("{:0>2}", minute);
655 let s = format!("{:0>2}", second);
656 match Date::from_str(y, m, d) {
657 Ok(date) => {
658 match Time::from_str(h, min, s, None, Some(TimeOffset::Zulu)) {
659 Ok(time) => Ok(Value::DateTime(DateTime::new(date, Some(time)))),
660 Err(error) => Err(error),
661 }
662 },
663 Err(error) => Err(error),
664 }
665 }
666
667 pub fn datetime_zulu_from_str<S>(year: S, month: S, day: S, hour: S, minute: S, second: S) -> Result<Value<'a>, TOMLError> where S: Into<String> + Clone {
680 match Date::from_str(year.clone().into(), month.clone().into(), day.clone().into()) {
681 Ok(date) => {
682 match Time::from_str(hour.clone().into(), minute.clone().into(), second.clone().into(), None, Some(
683 TimeOffset::Zulu
684 )) {
685 Ok(time) => Ok(Value::DateTime(DateTime::new(date, Some(time)))),
686 Err(error) => Err(error),
687 }
688 },
689 Err(error) => Err(error),
690 }
691 }
692
693 pub fn datetime_full_zulu_from_int(year: usize, month: usize, day: usize, hour: usize, minute: usize, second: usize, frac: u64) -> Result<Value<'a>, TOMLError> {
708 let y = format!("{:0>4}", year);
709 let m = format!("{:0>2}", month);
710 let d = format!("{:0>2}", day);
711 let h = format!("{:0>2}", hour);
712 let min = format!("{:0>2}", minute);
713 let s = format!("{:0>2}", second);
714 let f = format!("{}", frac);
715 match Date::from_str(y, m, d) {
716 Ok(date) => {
717 match Time::from_str(h, min, s, Some(f), Some(TimeOffset::Zulu)) {
718 Ok(time) => Ok(Value::DateTime(DateTime::new(date, Some(time)))),
719 Err(error) => Err(error),
720 }
721 },
722 Err(error) => Err(error),
723 }
724 }
725
726 pub fn datetime_full_zulu_from_str<S>(year: S, month: S, day: S, hour: S, minute: S, second: S, frac: S) -> Result<Value<'a>, TOMLError> where S: Into<String> + Clone {
739 match Date::from_str(year.clone().into(), month.clone().into(), day.clone().into()) {
740 Ok(date) => {
741 match Time::from_str(hour.clone().into(), minute.clone().into(), second.clone().into(), Some(frac.clone().into()), Some(
742 TimeOffset::Zulu
743 )) {
744 Ok(time) => Ok(Value::DateTime(DateTime::new(date, Some(time)))),
745 Err(error) => Err(error),
746 }
747 },
748 Err(error) => Err(error),
749 }
750 }
751
752 pub fn datetime_full_from_int(year: usize, month: usize, day: usize, hour: usize, minute: usize, second: usize, frac: u64, posneg: char, off_hour: usize, off_minute: usize) -> Result<Value<'a>, TOMLError> {
770 let y = format!("{:0>4}", year);
771 let m = format!("{:0>2}", month);
772 let d = format!("{:0>2}", day);
773 let h = format!("{:0>2}", hour);
774 let min = format!("{:0>2}", minute);
775 let s = format!("{:0>2}", second);
776 let f = format!("{}", frac);
777 let oh = format!("{:0>2}", off_hour);
778 let omin = format!("{:0>2}", off_minute);
779 let mut pn = "".to_string();
780 pn.push(posneg);
781 match Date::from_str(y, m, d) {
782 Ok(date) => {
783 match TimeOffsetAmount::from_str(pn, oh, omin) {
784 Ok(offset) => {
785 match Time::from_str(h, min, s, Some(f), Some(TimeOffset::Time(offset))) {
786 Ok(time) => Ok(Value::DateTime(DateTime::new(date, Some(time)))),
787 Err(error) => Err(error),
788 }
789 },
790 Err(error) => Err(error),
791 }
792 },
793 Err(error) => Err(error),
794 }
795 }
796
797 pub fn datetime_full_from_str<S>(year: S, month: S, day: S, hour: S, minute: S, second: S, frac: S, posneg: S, off_hour: S, off_minute: S) -> Result<Value<'a>, TOMLError> where S: Into<String> + Clone {
812 match Date::from_str(year.clone().into(), month.clone().into(), day.clone().into()) {
813 Ok(date) => {
814 match TimeOffsetAmount::from_str(posneg.clone().into(), off_hour.clone().into(), off_minute.clone().into()) {
815 Ok(offset) => {
816 match Time::from_str(hour.clone().into(), minute.clone().into(), second.clone().into(), Some(frac.clone().into()), Some(
817 TimeOffset::Time(offset)
818 )) {
819 Ok(time) => Ok(Value::DateTime(DateTime::new(date, Some(time)))),
820 Err(error) => Err(error),
821 }
822 },
823 Err(error) => Err(error),
824 }
825 },
826 Err(error) => Err(error),
827 }
828 }
829
830 pub fn datetime_parse<S>(dt: S) -> Result<Value<'a>, TOMLError> where S: Into<&'a str> {
844 let datetime = dt.into();
845 let p = Parser::new();
846 match p.date_time(datetime) {
847 (_, IResult::Done(i, o)) => {
848 let result = Value::DateTime(o);
849 if i.len() > 0 || !result.validate() {
850 return Result::Err(TOMLError::new(format!("Error parsing string as datetime. Argument: {}", datetime)));
851 } else {
852 return Result::Ok(result);
853 }
854 },
855 (_,_) => return Result::Err(TOMLError::new(format!("Error parsing string as datetime. Argument: {}", datetime))),
856 }
857 }
858
859 pub fn basic_string<S>(s: S) -> Result<Value<'a>, TOMLError> where S: Into<String> + Clone {
870 let result = Value::String(s.clone().into().into(), StrType::Basic);
871 if result.validate() {
872 return Result::Ok(result);
873 } else {
874 return Result::Err(TOMLError::new(format!("Error parsing string as basic_string. Argument: {}", s.into())));
875 }
876 }
877
878 pub fn ml_basic_string<S>(s: S) -> Result<Value<'a>, TOMLError> where S: Into<String> + Clone {
889 let result = Value::String(s.clone().into().into(), StrType::MLBasic);
890 if result.validate() {
891 return Result::Ok(result);
892 } else {
893 return Result::Err(TOMLError::new(format!("Error parsing string as ml_basic_string. Argument: {}", s.into())));
894 }
895 }
896
897 pub fn literal_string<S>(s: S) -> Result<Value<'a>, TOMLError> where S: Into<String> + Clone {
908 let result = Value::String(s.clone().into().into(), StrType::Literal);
909 if result.validate() {
910 return Result::Ok(result);
911 } else {
912 return Result::Err(TOMLError::new(format!("Error parsing string as literal_string. Argument: {}", s.into())));
913 }
914 }
915
916 pub fn ml_literal_string<S>(s: S) -> Result<Value<'a>, TOMLError> where S: Into<String> + Clone {
928 let result = Value::String(s.clone().into().into(), StrType::MLLiteral);
929 if result.validate() {
930 return Result::Ok(result);
931 } else {
932 return Result::Err(TOMLError::new(format!("Error parsing string as ml_literal_string. Argument: {}", s.into())));
933 }
934 }
935
936 pub fn validate(&self) -> bool{
948 match self {
949 &Value::Integer(ref s) => {
950 let p = Parser::new();
951 match p.integer(s) {
952 (_, IResult::Done(_, _)) => true,
953 (_,_) => false,
954 }
955 },
956 &Value::Float(ref s) => {
957 let p = Parser::new();
958 match p.float(s) {
959 (_, IResult::Done(_, _)) => true,
960 (_,_) => false,
961 }
962 },
963 &Value::DateTime(ref dt) => {dt.validate()},
964 &Value::String(ref s, st) => {
965 match st {
966 StrType::Basic => {
967 match Parser::quoteless_basic_string(s) {
968 IResult::Done(i,_) => i.len() == 0,
969 _ => false,
970 }
971 },
972 StrType::MLBasic => {
973 match Parser::quoteless_ml_basic_string(s) {
974 IResult::Done(i,_) => i.len() == 0,
975 _ => false,
976 }
977 },
978 StrType::Literal => {
979 match Parser::quoteless_literal_string(s) {
980 IResult::Done(i,_) => i.len() == 0,
981 _ => false,
982 }
983 },
984 StrType::MLLiteral => {
985 match Parser::quoteless_ml_literal_string(s) {
986 IResult::Done(i,_) => i.len() == 0,
987 _ => false,
988 }
989 },
990 }
991 },
992 _ => true,
993 }
994 }
995}
996
997#[derive(Debug)]
999pub struct TOMLError {
1000 message: String,
1001}
1002
1003impl Error for TOMLError {
1004
1005 fn description(&self) -> &str {
1021 &self.message
1022 }
1023
1024 fn cause(&self) -> Option<&Error> { None }
1026}
1027
1028impl Display for TOMLError {
1029 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1030 write!(f, "{}", self.message)
1031 }
1032}
1033
1034impl TOMLError {
1035 fn new(msg: String) -> TOMLError {
1036 warn!("{}", msg);
1037 TOMLError{message: msg}
1038 }
1039}
1040
1041#[derive(Debug, Eq, PartialEq, Clone, Copy)]
1043pub enum PosNeg {
1044 Pos,
1046 Neg,
1048}
1049
1050impl Display for PosNeg {
1051 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1052 match self {
1053 &PosNeg::Pos => write!(f, "+"),
1054 &PosNeg::Neg => write!(f, "-"),
1055 }
1056
1057 }
1058}
1059
1060#[derive(Debug, Eq, Clone)]
1062pub enum TimeOffset<'a> {
1063 Zulu,
1066 Time(TimeOffsetAmount<'a>),
1068}
1069
1070impl<'a> PartialEq for TimeOffset<'a> {
1071 fn eq(&self, other: &TimeOffset<'a>) -> bool {
1072 match (self, other) {
1073 (&TimeOffset::Zulu, &TimeOffset::Zulu) => true,
1074 (&TimeOffset::Time(ref i), &TimeOffset::Time(ref j)) if(i == j) => true,
1075 _ => false
1076 }
1077 }
1078}
1079
1080impl<'a> Display for TimeOffset<'a> {
1081 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1082 match self {
1083 &TimeOffset::Zulu => write!(f, "Z"),
1084 &TimeOffset::Time(ref t) => write!(f, "{}", t),
1085 }
1086 }
1087}
1088
1089impl<'a> TimeOffset<'a> {
1090 pub fn validate(&self) -> bool {
1091 match self {
1092 &TimeOffset::Zulu => return true,
1093 &TimeOffset::Time(ref amount) => return amount.validate(),
1094 }
1095 }
1096}
1097
1098#[derive(Debug, Eq, Clone)]
1100pub struct TimeOffsetAmount<'a> {
1101 pub pos_neg: PosNeg,
1103 pub hour: Cow<'a, str>,
1105 pub minute: Cow<'a, str>,
1107}
1108
1109impl<'a> PartialEq for TimeOffsetAmount<'a> {
1110 fn eq(&self, other: &TimeOffsetAmount<'a>) -> bool {
1111 self.pos_neg == other.pos_neg &&
1112 self.hour == other.hour &&
1113 self.minute == other.minute
1114 }
1115}
1116
1117impl<'a> Display for TimeOffsetAmount<'a> {
1118 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1119 write!(f, "{}{}:{}", self.pos_neg, &self.hour, &self.minute)
1120 }
1121}
1122
1123impl<'a> TimeOffsetAmount<'a> {
1124
1125 pub fn from_str<S>(pos_neg: S, hour: S, minute: S) -> Result<TimeOffsetAmount<'a>, TOMLError> where S: Into<String>{
1134 let pn = match pos_neg.into().as_ref() {
1135 "+" => PosNeg::Pos,
1136 "-" => PosNeg::Neg,
1137 _ => return Result::Err(TOMLError::new("pos_neg value is neither a '+' or a '-'.".to_string())),
1138 };
1139 let offset = TimeOffsetAmount{pos_neg: pn, hour: hour.into().into(), minute: minute.into().into()};
1140 if offset.validate() {
1141 return Result::Ok(offset);
1142 } else {
1143 return Result::Err(TOMLError::new("Error validating TimeOffsetAmount.".to_string()));
1144 }
1145 }
1146
1147 pub fn validate(&self) -> bool {
1160 if self.hour.len() != 2 || self.minute.len() != 2 {
1161 return false;
1162 }
1163 return self.validate_numbers();
1164 }
1165
1166 fn validate_numbers(&self) -> bool {
1167 if let Ok(h) = usize::from_str(&self.hour) {
1168 if h > 23 {
1169 return false;
1170 }
1171 } else {
1172 return false;
1173 }
1174 if let Ok(m) = usize::from_str(&self.minute) {
1175 if m > 59 {
1176 return false;
1177 }
1178 } else {
1179 return false;
1180 }
1181 return true;
1182 }
1183}
1184
1185#[derive(Debug, Eq, Clone)]
1188pub struct Date<'a> {
1189 pub year: Cow<'a, str>,
1191 pub month: Cow<'a, str>,
1193 pub day: Cow<'a, str>,
1196}
1197
1198impl<'a> PartialEq for Date<'a> {
1199 fn eq(&self, other: &Date<'a>) -> bool {
1200 self.year == other.year &&
1201 self.month == other.month &&
1202 self.day == other.day
1203 }
1204}
1205
1206impl<'a> Display for Date<'a> {
1207 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1208 write!(f, "{}-{}-{}", self.year, self.month, self.day)
1209 }
1210}
1211
1212impl<'a> Date<'a> {
1213
1214 pub fn from_str<S>(year: S, month: S, day: S) -> Result<Date<'a>, TOMLError> where S: Into<String> {
1223 let date = Date{year: year.into().into(), month: month.into().into(), day: day.into().into()};
1224 if date.validate() {
1225 Ok(date)
1226 } else {
1227 Err(TOMLError::new("Error validating Date.".to_string()))
1228 }
1229 }
1230
1231 pub fn validate(&self) -> bool {
1244 if self.year.len() != 4 || self.month.len() != 2 || self.day.len() != 2 {
1245 return false;
1246 }
1247 return self.validate_numbers();
1248 }
1249
1250 fn validate_numbers(&self) -> bool {
1251 if let Ok(y) = usize::from_str(&self.year) {
1252 if y == 0 || y > 9999{
1253 return false;
1254 }
1255 if let Ok(m) = usize::from_str(&self.month) {
1256 if m < 1 || m > 12 {
1257 return false;
1258 }
1259 if let Ok(d) = usize::from_str(&self.day) {
1260 if d < 1 {
1261 return false;
1262 }
1263 match m {
1264 2 => {
1265 let leap_year;
1266 if y % 4 != 0 {
1267 leap_year = false;
1268 } else if y % 100 != 0 {
1269 leap_year = true;
1270 } else if y % 400 != 0 {
1271 leap_year = false;
1272 } else {
1273 leap_year = true;
1274 }
1275 if leap_year && d > 29 {
1276 return false;
1277 } else if !leap_year && d > 28 {
1278 return false;
1279 }
1280 },
1281 1 | 3 | 5 | 7 | 8 | 10 | 12 => { if d > 31 { return false; } },
1282 _ => { if d > 30 { return false; } },
1283 }
1284 } else {
1285 return false;
1286 }
1287 } else {
1288 return false;
1289 }
1290 } else {
1291 return false;
1292 }
1293 return true;
1294 }
1295}
1296
1297#[derive(Debug, Eq, Clone)]
1299pub struct Time<'a> {
1300 pub hour: Cow<'a, str>,
1302 pub minute: Cow<'a, str>,
1304 pub second: Cow<'a, str>,
1306 pub fraction: Option<Cow<'a, str>>,
1308 pub offset: Option<TimeOffset<'a>>,
1310}
1311
1312impl<'a> PartialEq for Time<'a> {
1313 fn eq(&self, other: &Time<'a>) -> bool {
1314 self.hour == other.hour &&
1315 self.minute == other.minute &&
1316 self.second == other.second &&
1317 self.fraction == other.fraction &&
1318 self.offset == other.offset
1319 }
1320}
1321
1322impl<'a> Display for Time<'a> {
1323 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1324 match (&self.fraction, &self.offset) {
1325 (&Some(ref frac), &Some(ref offset)) => write!(f, "T{}:{}:{}.{}{}", self.hour, self.minute, self.second, frac, offset),
1326 (&Some(ref frac), &None) => write!(f, "T{}:{}:{}.{}", self.hour, self.minute, self.second, frac),
1327 (&None, &Some(ref offset)) => write!(f, "T{}:{}:{}{}", self.hour, self.minute, self.second, offset),
1328 (&None, &None) => write!(f, "T{}:{}:{}", self.hour, self.minute, self.second),
1329 }
1330 }
1331}
1332
1333impl<'a> Time<'a> {
1334
1335 pub fn from_str<S>(hour: S, minute: S, second: S, fraction: Option<S>, offset: Option<TimeOffset<'a>>)
1344 -> Result<Time<'a>, TOMLError> where S: Into<String> {
1345 if let Some(s) = fraction {
1346 let time = Time{hour: hour.into().into(), minute: minute.into().into(), second: second.into().into(),
1347 fraction: Some(s.into().into()), offset: offset};
1348 if time.validate() {
1349 return Ok(time);
1350 } else {
1351 return Err(TOMLError::new("Error validating Time.".to_string()));
1352 }
1353 } else {
1354 let time = Time{hour: hour.into().into(), minute: minute.into().into(), second: second.into().into(),
1355 fraction: None, offset: offset};
1356 if time.validate() {
1357 return Ok(time);
1358 } else {
1359 return Err(TOMLError::new("Error validating Time.".to_string()));
1360 }
1361 }
1362 }
1363
1364 pub fn validate(&self) -> bool {
1379 if self.hour.len() != 2 || self.minute.len() != 2 || self.second.len() != 2 {
1380 return false;
1381 }
1382 return self.validate_numbers();
1383 }
1384
1385 fn validate_numbers(&self) -> bool {
1386 if let Ok(h) = usize::from_str(&self.hour) {
1387 if h > 23 {
1388 return false;
1389 }
1390 } else {
1391 return false;
1392 }
1393 if let Ok(m) = usize::from_str(&self.minute) {
1394 if m > 59 {
1395 return false;
1396 }
1397 } else {
1398 return false;
1399 }
1400 if let Ok(s) = usize::from_str(&self.second) {
1401 if s > 59 {
1402 return false;
1403 }
1404 } else {
1405 return false;
1406 }
1407 if let Some(ref frac) = self.fraction {
1408 if u64::from_str(frac).is_err() {
1409 return false;
1410 }
1411 }
1412 if let Some(ref off) = self.offset {
1413 if !off.validate() {
1414 return false;
1415 }
1416 }
1417 return true;
1418 }
1419}
1420
1421#[derive(Debug, Eq, Clone)]
1423pub struct DateTime<'a> {
1424 pub date: Date<'a>,
1425 pub time: Option<Time<'a>>,
1426}
1427
1428impl<'a> PartialEq for DateTime<'a> {
1429 fn eq(&self, other: &DateTime<'a>) -> bool {
1430 self.date == other.date &&
1431 self.time == other.time
1432 }
1433}
1434
1435impl<'a> Display for DateTime<'a> {
1436 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1437 match &self.time {
1438 &Some(ref time) => write!(f, "{}{}", self.date, time),
1439 &None => write!(f, "{}", self.date),
1440 }
1441 }
1442}
1443
1444impl<'a> DateTime<'a> {
1446 pub fn new(date: Date<'a>, time: Option<Time<'a>>) -> DateTime<'a> {
1447 DateTime{date: date, time: time}
1448 }
1449
1450 pub fn validate(&self) -> bool {
1463 if self.date.validate() {
1464 if let Some(ref time) = self.time {
1465 return time.validate();
1466 }
1467 } else {
1468 return false;
1469 }
1470 return true;
1471 }
1472}
1473
1474#[cfg(test)]
1475mod test {
1476 use std::cell::{Cell, RefCell};
1477 use std::rc::Rc;
1478 use types::{Children, Value, Date, Time, DateTime, TimeOffset, TimeOffsetAmount, StrType};
1479
1480 #[test]
1481 fn test_combine_keys() {
1482 assert_eq!("foo.bar.baz".to_string(), Children::combine_keys("foo.bar", "baz"));
1483 }
1484
1485 #[test]
1486 fn test_combine_keys_index() {
1487 assert_eq!("foo.bar[9]".to_string(), Children::combine_keys_index("foo.bar", 9));
1488 }
1489
1490 #[test]
1491 fn test_combine_child_keys() {
1492 let kids = Children::Keys(RefCell::new(vec!["baz".to_string(), "qux".to_string(), "plugh".to_string(),
1493 "thud".to_string()]));
1494 assert_eq!(vec!["foo.bar.baz".to_string(), "foo.bar.qux".to_string(), "foo.bar.plugh".to_string(),
1495 "foo.bar.thud".to_string()], kids.combine_child_keys("foo.bar".to_string()));
1496 }
1497
1498 #[test]
1499 fn test_combine_child_keys_empty_base() {
1500 let kids = Children::Keys(RefCell::new(vec!["baz".to_string(), "qux".to_string(), "plugh".to_string(),
1501 "thud".to_string()]));
1502 assert_eq!(vec!["baz".to_string(), "qux".to_string(), "plugh".to_string(),
1503 "thud".to_string()], kids.combine_child_keys("".to_string()));
1504 }
1505
1506 #[test]
1507 fn test_combine_child_keys_index() {
1508 let kids = Children::Count(Cell::new(3));
1509 assert_eq!(vec!["foo.bar[0]".to_string(), "foo.bar[1]".to_string(), "foo.bar[2]".to_string()],
1510 kids.combine_child_keys("foo.bar".to_string()));
1511 }
1512
1513 #[test]
1514 fn test_value_display() {
1515 let val_int = Value::Integer("7778877".into());
1516 let val_float = Value::Float("1929.345".into());
1517 let val_true = Value::Boolean(true);
1518 let val_false = Value::Boolean(false);
1519 let val_datetime = Value::DateTime(DateTime::new(Date::new_str("9999", "12", "31"), Some(Time::new_str(
1520 "23", "59", "59", Some("9999999"), Some(TimeOffset::Time(TimeOffsetAmount::new_str(
1521 "-", "00", "00"
1522 )))
1523 ))));
1524 let val_basic_str = Value::String("foobar1".into(), StrType::Basic);
1525 let val_literal_str = Value::String("foobar2".into(), StrType::Literal);
1526 let val_ml_basic_str = Value::String("foobar3".into(), StrType::MLBasic);
1527 let val_ml_literal_str = Value::String("foobar4".into(), StrType::MLLiteral);
1528 let val_array = Value::Array(Rc::new(vec![Value::Integer("3000".into()),
1529 Value::Array(Rc::new(vec![Value::Integer("40000".into()), Value::Float("50.5".into())])),
1530 Value::String("barbaz".into(), StrType::Literal)]));
1531 let val_inline_table = Value::InlineTable(Rc::new(vec![
1532 ("foo".into(), Value::Boolean(true)), ("bar".into(), Value::InlineTable(Rc::new(vec![
1533 ("baz".into(), Value::Boolean(false)), ("qux".into(), Value::Integer("2016".into())),
1534 ]))), ("plugh".into(), Value::Float("3333.444".into()))
1535 ]));
1536
1537 assert_eq!("7778877", &format!("{}", val_int));
1538 assert_eq!("1929.345", &format!("{}", val_float));
1539 assert_eq!("true", &format!("{}", val_true));
1540 assert_eq!("false", &format!("{}", val_false));
1541 assert_eq!("9999-12-31T23:59:59.9999999-00:00", &format!("{}", val_datetime));
1542 assert_eq!("\"foobar1\"", &format!("{}", val_basic_str));
1543 assert_eq!("'foobar2'", &format!("{}", val_literal_str));
1544 assert_eq!("\"\"\"foobar3\"\"\"", &format!("{}", val_ml_basic_str));
1545 assert_eq!("'''foobar4'''", &format!("{}", val_ml_literal_str));
1546 assert_eq!("[3000, [40000, 50.5], 'barbaz']", &format!("{}", val_array));
1547 assert_eq!("{foo = true, bar = {baz = false, qux = 2016}, plugh = 3333.444}",
1548 &format!("{}", val_inline_table));
1549 }
1550
1551 #[test]
1552 fn test_create_int() {
1553 assert_eq!(Value::Integer("9223372036854775807".into()), Value::int(9223372036854775807));
1554 }
1555
1556 #[test]
1557 fn test_create_int_from_str() {
1558 assert_eq!(Value::Integer("-9223372036854775808".into()), Value::int_from_str("-9223372036854775808").unwrap());
1559 }
1560
1561 #[test]
1562 fn test_create_int_from_str_fail() {
1563 assert!(Value::int_from_str("q-9223$37(203)[]M807").is_err());
1564 }
1565
1566 #[test]
1567 fn test_create_float() {
1568 assert_eq!(Value::Float("179769000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into()), Value::float(1.79769e+308));
1569 }
1570
1571 #[test]
1572 fn test_create_float_from_str() {
1573 assert_eq!(Value::Float("2.22507e-308".into()), Value::float_from_str("2.22507e-308").unwrap());
1574 }
1575
1576 #[test]
1577 fn test_create_float_from_str_fail() {
1578 assert!(Value::float_from_str("q2.3e++10eipi").is_err());
1579 }
1580
1581 #[test]
1582 fn test_create_bool() {
1583 assert_eq!(Value::Boolean(false), Value::bool(false));
1584 }
1585
1586 #[test]
1587 fn test_create_bool_from_str() {
1588 assert_eq!(Value::Boolean(true), Value::bool_from_str("TrUe").unwrap());
1589 }
1590
1591 #[test]
1592 fn test_create_bool_from_str_fail() {
1593 assert!(Value::bool_from_str("TFraulese").is_err());
1594 }
1595
1596 #[test]
1597 fn test_create_date_from_int() {
1598 assert_eq!(Value::DateTime(DateTime::new(Date::new_str("2012", "01", "03"), None)),
1599 Value::date_from_int(2012, 1, 3).unwrap());
1600 }
1601
1602 #[test]
1603 fn test_create_date_from_int_fail() {
1604 assert!(Value::date_from_int(0, 2, 20).is_err());
1605 assert!(Value::date_from_int(2016, 0, 20).is_err());
1606 assert!(Value::date_from_int(2016, 1, 0).is_err());
1607 assert!(Value::date_from_int(2016, 1, 32).is_err());
1608 assert!(Value::date_from_int(2016, 4, 31).is_err());
1609 assert!(Value::date_from_int(2016, 2, 30).is_err());
1610 assert!(Value::date_from_int(2015, 2, 29).is_err());
1611 assert!(Value::date_from_int(1900, 2, 29).is_err());
1612 assert!(Value::date_from_int(2000, 2, 30).is_err());
1613 }
1614
1615 #[test]
1616 fn test_create_date_from_str() {
1617 assert_eq!(Value::DateTime(DateTime::new(Date::new_str("2012", "01", "03"), None)),
1618 Value::date_from_str("2012", "01", "03").unwrap());
1619 }
1620
1621 #[test]
1622 fn test_create_date_from_str_fail() {
1623 assert!(Value::date_from_str("12345", "01", "01").is_err());
1624 assert!(Value::date_from_str("2016", "012", "01").is_err());
1625 assert!(Value::date_from_str("2016", "01", "012").is_err());
1626 assert!(Value::date_from_str("201q", "01", "01").is_err());
1627 assert!(Value::date_from_str("2016", "0q", "01").is_err());
1628 assert!(Value::date_from_str("2016", "01", "0q").is_err());
1629 assert!(Value::date_from_str("201", "01", "01").is_err());
1630 assert!(Value::date_from_str("2016", "1", "01").is_err());
1631 assert!(Value::date_from_str("2016", "01", "1").is_err());
1632 }
1633
1634 #[test]
1635 fn test_create_datetime_from_int() {
1636 assert_eq!(Value::DateTime(DateTime::new(Date::new_str("2012", "01", "03"), Some(Time::new_str(
1637 "03", "30", "30", None, None
1638 )))), Value::datetime_from_int(2012, 1, 3, 3, 30, 30).unwrap());
1639 }
1640
1641 #[test]
1642 fn test_create_datetime_from_int_fail() {
1643 assert!(Value::datetime_from_int(2012, 1, 3, 24, 30, 30).is_err());
1644 assert!(Value::datetime_from_int(2012, 1, 3, 3, 60, 30).is_err());
1645 assert!(Value::datetime_from_int(2012, 1, 3, 3, 30, 60).is_err());
1646 }
1647
1648 #[test]
1649 fn test_create_datetime_from_str() {
1650 assert_eq!(Value::DateTime(DateTime::new(Date::new_str("2012", "01", "03"), Some(Time::new_str(
1651 "03", "30", "30", None, None
1652 )))), Value::datetime_from_str("2012", "01", "03", "03", "30", "30").unwrap());
1653 }
1654
1655 #[test]
1656 fn test_create_datetime_from_str_fail() {
1657 assert!(Value::datetime_from_str("2012", "01", "03", "3", "30", "30").is_err());
1658 assert!(Value::datetime_from_str("2012", "01", "03", "03", "3", "30").is_err());
1659 assert!(Value::datetime_from_str("2012", "01", "03", "03", "30", "3").is_err());
1660 assert!(Value::datetime_from_str("2012", "01", "03", "033", "30", "30").is_err());
1661 assert!(Value::datetime_from_str("2012", "01", "03", "03", "303", "303").is_err());
1662 assert!(Value::datetime_from_str("2012", "01", "03", "0q", "30", "30").is_err());
1663 assert!(Value::datetime_from_str("2012", "01", "03", "03", "3q", "30").is_err());
1664 assert!(Value::datetime_from_str("2012", "01", "03", "03", "30", "3q").is_err());
1665 }
1666
1667 #[test]
1668 fn test_create_datetime_frac_from_int() {
1669 assert_eq!(Value::DateTime(DateTime::new(Date::new_str("2012", "01", "03"), Some(Time::new_str(
1670 "03", "30", "30", Some("3030"), None
1671 )))), Value::datetime_frac_from_int(2012, 1, 3, 3, 30, 30, 3030).unwrap());
1672 }
1673
1674 #[test]
1675 fn test_create_datetime_frac_from_int_fail() {
1676 assert!(Value::datetime_frac_from_int(2012, 1, 0, 3, 30, 30, 3030).is_err());
1677 }
1678
1679 #[test]
1680 fn test_create_datetime_frac_from_str() {
1681 assert_eq!(Value::DateTime(DateTime::new(Date::new_str("2012", "01", "03"), Some(Time::new_str(
1682 "03", "30", "30", Some("3030"), None
1683 )))), Value::datetime_frac_from_str("2012", "01", "03", "03", "30", "30", "3030").unwrap());
1684 }
1685
1686 #[test]
1687 fn test_create_datetime_frac_from_str_fail() {
1688 assert!(Value::datetime_frac_from_str("2012", "01", "03", "03", "30", "30", "q3030").is_err());
1689 }
1690
1691 #[test]
1692 fn test_create_datetime_offset_from_int() {
1693 assert_eq!(Value::DateTime(DateTime::new(Date::new_str("2012", "01", "03"), Some(Time::new_str(
1694 "03", "30", "30", None, Some(TimeOffset::Time(TimeOffsetAmount::new_str(
1695 "+", "07", "45"
1696 )))
1697 )))), Value::datetime_offset_from_int(2012, 1, 3, 3, 30, 30, '+', 7, 45).unwrap());
1698 }
1699
1700 #[test]
1701 fn test_create_datetime_offset_from_int_fail() {
1702 assert!(Value::datetime_offset_from_int(2012, 1, 3, 3, 30, 30, 'q', 7, 45).is_err());
1703 assert!(Value::datetime_offset_from_int(2012, 1, 3, 3, 30, 30, '+', 24, 45).is_err());
1704 assert!(Value::datetime_offset_from_int(2012, 1, 3, 3, 30, 30, '+', 7, 60).is_err());
1705 }
1706
1707 #[test]
1708 fn test_create_datetime_offset_from_str() {
1709 assert_eq!(Value::DateTime(DateTime::new(Date::new_str("2012", "01", "03"), Some(Time::new_str(
1710 "03", "30", "30", None, Some(TimeOffset::Time(TimeOffsetAmount::new_str(
1711 "+", "07", "45"
1712 )))
1713 )))), Value::datetime_offset_from_str("2012", "01", "03", "03", "30", "30", "+", "07", "45").unwrap());
1714 }
1715
1716 #[test]
1717 fn test_create_datetime_offset_from_str_fail() {
1718 assert!(Value::datetime_offset_from_str("2012", "01", "03", "03", "30", "30", "+", "077", "45").is_err());
1719 assert!(Value::datetime_offset_from_str("2012", "01", "03", "03", "30", "30", "+", "07", "455").is_err());
1720 assert!(Value::datetime_offset_from_str("2012", "01", "03", "03", "30", "30", "+", "7", "45").is_err());
1721 assert!(Value::datetime_offset_from_str("2012", "01", "03", "03", "30", "30", "+", "07", "5").is_err());
1722 assert!(Value::datetime_offset_from_str("2012", "01", "03", "03", "30", "30", "q", "07", "45").is_err());
1723 }
1724
1725 #[test]
1726 fn test_create_datetime_zulu_from_int() {
1727 assert_eq!(Value::DateTime(DateTime::new(Date::new_str("2012", "01", "03"), Some(Time::new_str(
1728 "03", "30", "30", None, Some(TimeOffset::Zulu)
1729 )))), Value::datetime_zulu_from_int(2012, 1, 3, 3, 30, 30).unwrap());
1730 }
1731
1732 #[test]
1733 fn test_create_datetime_zulu_from_int_fail() {
1734 assert!(Value::datetime_zulu_from_int(2012, 1, 0, 3, 30, 30).is_err());
1735 }
1736
1737 #[test]
1738 fn test_create_datetime_zulu_from_str() {
1739 assert_eq!(Value::DateTime(DateTime::new(Date::new_str("2012", "01", "03"), Some(Time::new_str(
1740 "03", "30", "30", None, Some(TimeOffset::Zulu)
1741 )))), Value::datetime_zulu_from_str("2012", "01", "03", "03", "30", "30").unwrap());
1742 }
1743
1744 #[test]
1745 fn test_create_datetime_zulu_from_str_fail() {
1746 assert!(Value::datetime_zulu_from_str("q2012", "01", "03", "03", "30", "30").is_err());
1747 }
1748
1749 #[test]
1750 fn test_create_datetime_full_zulu_from_int() {
1751 assert_eq!(Value::DateTime(DateTime::new(Date::new_str("2012", "01", "03"), Some(Time::new_str(
1752 "03", "30", "30", Some("3030"), Some(TimeOffset::Zulu)
1753 )))), Value::datetime_full_zulu_from_int(2012, 1, 3, 3, 30, 30, 3030).unwrap());
1754 }
1755
1756 #[test]
1757 fn test_create_datetime_full_zulu_from_int_fail() {
1758 assert!(Value::datetime_full_zulu_from_int(2012, 1, 0, 3, 30, 30, 3030).is_err());
1759 }
1760
1761 #[test]
1762 fn test_create_datetime_full_zulu_from_str() {
1763 assert_eq!(Value::DateTime(DateTime::new(Date::new_str("2012", "01", "03"), Some(Time::new_str(
1764 "03", "30", "30", Some("3030"), Some(TimeOffset::Zulu)
1765 )))), Value::datetime_full_zulu_from_str("2012", "01", "03", "03", "30", "30", "3030").unwrap());
1766 }
1767
1768 #[test]
1769 fn test_create_datetime_full_zulu_from_str_fail() {
1770 assert!(Value::datetime_full_zulu_from_str("q2012", "01", "03", "03", "30", "30", "3030").is_err());
1771 }
1772
1773 #[test]
1774 fn test_create_datetime_full_from_int() {
1775 assert_eq!(Value::DateTime(DateTime::new(Date::new_str("2012", "01", "03"), Some(Time::new_str(
1776 "03", "30", "30", Some("3030"), Some(TimeOffset::Time(TimeOffsetAmount::new_str(
1777 "+", "07", "45"
1778 )))
1779 )))), Value::datetime_full_from_int(2012, 1, 3, 3, 30, 30, 3030, '+', 7, 45).unwrap());
1780 }
1781
1782 #[test]
1783 fn test_create_datetime_full_from_int_fail() {
1784 assert!(Value::datetime_full_from_int(2012, 1, 0, 3, 30, 30, 3030, '+', 7, 45).is_err());
1785 assert!(Value::datetime_full_from_int(2012, 13, 0, 3, 30, 30, 3030, '+', 7, 45).is_err());
1786 assert!(Value::datetime_full_from_int(2012, 1, 0, 3, 61, 30, 3030, '+', 7, 45).is_err());
1787 assert!(Value::datetime_full_from_int(2012, 1, 0, 3, 30, 30, 3030, '+', 25, 45).is_err());
1788 assert!(Value::datetime_full_from_int(2012, 1, 0, 3, 30, 30, 3030, 'q', 7, 45).is_err());
1789 }
1790
1791 #[test]
1792 fn test_create_datetime_full_from_str() {
1793 assert_eq!(Value::DateTime(DateTime::new(Date::new_str("2012", "01", "03"), Some(Time::new_str(
1794 "03", "30", "30", Some("3030"), Some(TimeOffset::Time(TimeOffsetAmount::new_str(
1795 "+", "07", "45"
1796 )))
1797 )))), Value::datetime_full_from_str("2012", "01", "03", "03", "30", "30", "3030", "+", "07", "45").unwrap());
1798 }
1799
1800 #[test]
1801 fn test_create_datetime_full_from_str_fail() {
1802 assert!(Value::datetime_full_from_str("2012", "01", "03", "03", "30", "30", "q3030", "+", "07", "45").is_err());
1803 assert!(Value::datetime_full_from_str("2012", "01", "03", "03", "30", "30", "3030", "q", "07", "45").is_err());
1804 }
1805
1806 #[test]
1807 fn test_datetime_parse() {
1808 assert_eq!(Value::DateTime(DateTime::new(Date::new_str("2012", "01", "03"), Some(Time::new_str(
1809 "03", "30", "30", Some("3030"), Some(TimeOffset::Time(TimeOffsetAmount::new_str(
1810 "+", "07", "45"
1811 )))
1812 )))), Value::datetime_parse("2012-01-03T03:30:30.3030+07:45").unwrap());
1813
1814 assert_eq!(Value::DateTime(DateTime::new(Date::new_str("2012", "01", "03"), Some(Time::new_str(
1815 "03", "30", "30", Some("3030"), Some(TimeOffset::Zulu)
1816 )))), Value::datetime_parse("2012-01-03T03:30:30.3030Z").unwrap());
1817
1818 assert_eq!(Value::DateTime(DateTime::new(Date::new_str("2012", "01", "03"), Some(Time::new_str(
1819 "03", "30", "30", None, Some(TimeOffset::Zulu)
1820 )))), Value::datetime_parse("2012-01-03T03:30:30Z").unwrap());
1821
1822 assert_eq!(Value::DateTime(DateTime::new(Date::new_str("2012", "01", "03"), Some(Time::new_str(
1823 "03", "30", "30", None, Some(TimeOffset::Time(TimeOffsetAmount::new_str(
1824 "+", "07", "45"
1825 )))
1826 )))), Value::datetime_parse("2012-01-03T03:30:30+07:45").unwrap());
1827
1828 assert_eq!(Value::DateTime(DateTime::new(Date::new_str("2012", "01", "03"), Some(Time::new_str(
1829 "03", "30", "30", None, None
1830 )))), Value::datetime_parse("2012-01-03T03:30:30").unwrap());
1831
1832 assert_eq!(Value::DateTime(DateTime::new(Date::new_str("2012", "01", "03"), None
1833 )), Value::datetime_parse("2012-01-03").unwrap());
1834 }
1835
1836 #[test]
1837 fn test_datetime_parse_fail() {
1838 assert!(Value::datetime_parse("012-01-03T03:30:30.3030+07:45").is_err());
1839 assert!(Value::datetime_parse("2012-1-03T03:30:30.3030+07:45").is_err());
1840 assert!(Value::datetime_parse("2012-01-3T03:30:30.3030+07:45").is_err());
1841 assert!(Value::datetime_parse("2012-01-03T3:30:30.3030+07:45").is_err());
1842 assert!(Value::datetime_parse("2012-01-03T03:0:30.3030+07:45").is_err());
1843 assert!(Value::datetime_parse("2012-01-03T03:30:0.3030+07:45").is_err());
1844 assert!(Value::datetime_parse("2012-01-03T03:30:30.+07:45").is_err());
1845 assert!(Value::datetime_parse("2012-01-03T03:30:30.303007:45").is_err());
1846 assert!(Value::datetime_parse("2012-01-03T03:30:30.3030+7:45").is_err());
1847 assert!(Value::datetime_parse("2012-01-03T03:30:30.3030+07:5").is_err());
1848 assert!(Value::datetime_parse("20123-01-03T03:30:30.3030+07:45").is_err());
1849 assert!(Value::datetime_parse("2012-013-03T03:30:30.3030+07:45").is_err());
1850 assert!(Value::datetime_parse("2012-01-033T03:30:30.3030+07:45").is_err());
1851 assert!(Value::datetime_parse("2012-01-03T033:30:30.3030+07:45").is_err());
1852 assert!(Value::datetime_parse("2012-01-03T03:303:30.3030+07:45").is_err());
1853 assert!(Value::datetime_parse("2012-01-03T03:30:303.3030+07:45").is_err());
1854 assert!(Value::datetime_parse("2012-01-03T03:30:30.3030+073:45").is_err());
1855 assert!(Value::datetime_parse("2012-01-03T03:30:30.3030+07:453").is_err());
1856 assert!(Value::datetime_parse("2012q01-03T03:30:30.3030+07:45").is_err());
1857 assert!(Value::datetime_parse("2012-01q03T03:30:30.3030+07:45").is_err());
1858 assert!(Value::datetime_parse("2012-01-03q03:30:30.3030+07:45").is_err());
1859 assert!(Value::datetime_parse("2012-01-03T03q30:30.3030+07:45").is_err());
1860 assert!(Value::datetime_parse("2012-01-03T03:30q30.3030+07:45").is_err());
1861 assert!(Value::datetime_parse("2012-01-03T03:30:30q3030+07:45").is_err());
1862 assert!(Value::datetime_parse("2012-01-03T03:30:30.3030q07:45").is_err());
1863 assert!(Value::datetime_parse("2012-01-03T03:30:30.3030+07q45").is_err());
1864 }
1865
1866 #[test]
1867 fn test_create_basic_string() {
1868 assert_eq!(Value::String("foobar".into(), StrType::Basic), Value::basic_string("foobar").unwrap());
1869 }
1870
1871 #[test]
1872 fn test_create_basic_string_fail() {
1873 assert!(Value::basic_string("foo\nbar").is_err());
1874 }
1875
1876 #[test]
1877 fn test_create_ml_basic_string() {
1878 assert_eq!(Value::String("foobar".into(), StrType::MLBasic), Value::ml_basic_string("foobar").unwrap());
1879 }
1880
1881 #[test]
1882 fn test_create_ml_basic_string_fail() {
1883 assert!(Value::ml_basic_string(r#"foo\qbar"#).is_err());
1884 }
1885
1886 #[test]
1887 fn test_create_literal_string() {
1888 assert_eq!(Value::String("foobar".into(), StrType::Literal), Value::literal_string("foobar").unwrap());
1889 }
1890
1891 #[test]
1892 fn test_create_literal_string_fail() {
1893 assert!(Value::literal_string(r#"foo
1894bar"#).is_err());
1895 }
1896
1897 #[test]
1898 fn test_create_ml_literal_string() {
1899 assert_eq!(Value::String("foobar".into(), StrType::MLLiteral), Value::ml_literal_string("foobar").unwrap());
1900 }
1901
1902 #[test]
1903 fn test_create_ml_literal_string_fail() {
1904 assert!(Value::ml_literal_string("foobar").is_err());
1907 }
1908
1909}