1use colored::Colorize;
173use core::str::Split;
174use std::error::Error;
175use std::fmt::Display;
176use std::ops::Index;
177use std::fmt;
178use std::process::exit;
179
180const INDENTSTEP: usize = 4;
181
182fn spaces(i: usize) -> String {
183 let mut s = String::new();
184 for _n in 0..i { s.push_str(" ") };
185 s
186}
187
188#[derive(Debug, PartialEq)]
190pub enum SmallError {
191 EmptyKey(Token, usize),
196
197 Indent(Token, usize),
202
203 Empty,
207
208 IsKey(Token),
212
213 IsValue(String),
217
218 KeyParse(String),
222
223 MissingToken,
227
228 NoColon(Token, usize),
233
234 NoQuoteAfterKey(Token, usize),
239
240 NoSecondQuote(Token, usize),
245
246 NoSpaceAfterKey(Token),
251
252 NotUnique(usize),
256
257 ParseValue(Token, &'static str),
261
262 QuotemarkInKey(Token, usize), User(String),
272}
273
274impl Error for SmallError {
275}
276
277impl fmt::Display for SmallError {
278
279 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
280 match self {
281 SmallError::Empty => {
282 write!(f, "The input string is empty.")
283 },
284
285 SmallError::EmptyKey(token, pos) => {
286 write!(f, "Line {}:{} Empty key.", token.line, pos)
287 },
288
289 SmallError::Indent(token, _) => {
290 write!(f, "Line {}:{} Indentation should be aligned by {} to the top key ",
291 token.line,
292 token.start_key.unwrap(),
293 INDENTSTEP
294 )
295 },
296
297 SmallError::IsKey(s) => {
298 write!(f, "Expected 'key: value' but found only key \"{}\"", s)
299 },
300
301 SmallError::IsValue(s) => {
302 write!(f, "\"{}\" is a value, not a key.", s)
303 },
304
305 SmallError::ParseValue(token, to_type) => {
306 write!(f, "Line {}:{} [{}] The value could not be parsed into a {}.",
307 token.line,
308 token.start_val.unwrap(),
309 token.text.trim().cyan().bold(),
310 to_type,
311 )
312 },
313
314 SmallError::KeyParse(s) => {
315 write!(f,
316 "\"{}\" cannot be parsed.", s)
317 },
318
319 SmallError::NoColon(token, pos) => {
320 write!(f, "Line {}: [{}] should have a colon after the key at position {}.", token.line, token.text, pos)
321 },
322
323 SmallError::NotUnique(n) => {
324 write!(f,
325 "Resulted in {} keys, but expected 1.", n)
326 },
327
328 SmallError::NoQuoteAfterKey(token, pos) => {
329 write!(f, "Line {}:{} Value must start with double quotemark", token.line, pos)
330 },
331
332 SmallError::NoSecondQuote(token, pos) => {
333 write!(f, "Line {}:{} No second quote.", token.line, pos)
334 },
335
336 SmallError::NoSpaceAfterKey(token) => {
337 write!(f, "Line {}:{} No space after .", token.line, token.end_key.unwrap())
338 },
339
340 SmallError::MissingToken => {
341 write!(f, "Expected another token.")
342 },
343
344 SmallError::QuotemarkInKey(token, pos) => {
345 write!(f, "Line {}:{} Quote mark in key.", token.line, pos)
346 },
347
348 SmallError::User(s) => {
349 write!(f, "{}", s)
350 },
351 }
352 }
353}
354
355#[derive(Debug)]
357pub struct KeyPath<'a>(&'a str, Split<'a, &'a str>);
358
359impl<'a> KeyPath<'a> {
360 pub fn from_str(s: &'a str) -> Result<Self, SmallError> {
361 if s.is_empty() { return Err(SmallError::KeyParse(s.to_owned())) };
362 if s.split("::").any(|k| k.contains(":")) {
363 return Err(SmallError::KeyParse(s.to_owned()))
364 };
365 Ok(KeyPath(s, s.split("::")))
366 }
367}
368
369impl<'a> fmt::Display for KeyPath<'a> {
370 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
371 write!(f, "{}", self.0)
372 }
373}
374
375impl<'a> Iterator for KeyPath<'a> {
376 type Item = &'a str;
377 fn next(&mut self) -> Option<Self::Item> {
378 self.1.next()
379 }
380}
381
382#[derive(Clone, Debug)]
394pub struct Token {
395 text: String,
396 line: usize,
397 start_key: Option<usize>,
398 end_key: Option<usize>,
399 start_val: Option<usize>,
400 end_val: Option<usize>,
401}
402
403impl PartialEq for Token {
406 fn eq(&self, other: &Token) -> bool {
407 self.indentation() == other.indentation() &&
408 self.key() == other.key() &&
409 self.value() == other.value()
410 }
411}
412
413#[derive(Debug)]
415enum PS {
416 BK, IK, RAK, AK, IV, AV, }
423
424impl Token {
425
426 fn new(
429 text: &str,
430 line: usize,
431 start_key: Option<usize>,
432 end_key: Option<usize>,
433 start_val: Option<usize>,
434 end_val: Option<usize>) -> Self {
435
436 Token {
437 text: text.to_string(),
438 line: line,
439 start_key: start_key,
440 end_key: end_key,
441 start_val: start_val,
442 end_val: end_val,
443 }
444 }
445
446 fn indent(&mut self) {
447 self.text = format!(" {}", self.text);
448 self.start_key = self.start_key.map(|sk| sk + INDENTSTEP);
449 self.end_key = self.end_key.map(|ek| ek + INDENTSTEP);
450 self.start_val = self.start_val.map(|sv| sv + INDENTSTEP);
451 self.end_val = self.end_val.map(|ev| ev + INDENTSTEP);
452 }
453
454 fn from_str(s: &str, line: usize, root_indent: usize) -> Result<Self, SmallError> {
458 let mut ps = PS::BK;
459 let mut escape = false;
460 let mut start_key: Option<usize> = None;
461 let mut end_key: Option<usize> = None;
462 let mut start_val: Option<usize> = None;
463 let mut end_val: Option<usize> = None;
464
465 for (pos, c) in s.char_indices() {
466
467 if let PS::BK = ps {
469 if c == ':' {
470 start_key = Some(pos);
471 let token = Token::new(s, line, start_key, end_key, start_val, end_val);
472 return Err(SmallError::EmptyKey(token, pos));
473 };
474 if !c.is_whitespace() {
475 start_key = Some(pos);
476 if (pos - root_indent) % INDENTSTEP != 0 {
477 let token = Token::new(s, line, start_key, end_key, start_val, end_val);
478 return Err(SmallError::Indent(token, root_indent));
479 };
480 ps = PS::IK;
481 };
482 continue; };
484
485 if let PS::IK = ps {
487 if c == '"' {
488 let token = Token::new(s, line, start_key, end_key, start_val, end_val);
489 return Err(SmallError::QuotemarkInKey(token, pos));
490 };
491 if c.is_whitespace() {
492 let token = Token::new(s, line, start_key, end_key, start_val, end_val);
493 return Err(SmallError::NoColon(token, pos));
494 };
495 if c == ':' {
496 if Some(pos) == start_key {
497 let token = Token::new(s, line, start_key, end_key, start_val, end_val);
498 return Err(SmallError::EmptyKey(token, pos))
499 } else {
500 end_key = Some(pos);
501 ps = PS::RAK;
502 continue;
503 };
504 };
505 };
506
507 if let PS::RAK = ps {
509 if !c.is_whitespace() {
510 let token = Token::new(s, line, start_key, end_key, start_val, end_val);
511 return Err(SmallError::NoSpaceAfterKey(token))
512 } else {
513 ps = PS::AK;
514 continue;
515 }
516 };
517
518 if let PS::AK = ps {
520 if c.is_whitespace() {
521 continue;
522 } else {
523 if c != '"' {
524 let token = Token::new(s, line, start_key, end_key, start_val, end_val);
525 return Err(SmallError::NoQuoteAfterKey(token, pos))
526 } else {
527 start_val = Some(pos);
528 ps = PS::IV;
529 continue;
530 }
531 }
532 };
533
534 if let PS::IV = ps {
536 if c == '\\' {
537 escape = true;
538 } else if c == '"' && escape {
539 continue;
540 } else if c == '"' {
541 ps = PS::AV;
542 end_val = Some(pos);
543 } else {
544 escape = false;
545 continue;
546 }
547 };
548
549 if let PS::AV = ps { break };
551 };
552
553 let token = Token::new(s, line, start_key, end_key, start_val, end_val);
554
555 match ps {
556 PS::BK => {
557 panic!("Shouldn't fail here")
558 },
559 PS::IK => { Err(SmallError::NoColon(token, s.char_indices().count())) },
560 PS::RAK => { Ok(token) },
561 PS::AK => { Ok(token) },
562 PS::IV => { return Err(SmallError::NoSecondQuote(token, s.char_indices().count())) },
563 PS::AV => { Ok(token) },
564 }
565 }
566
567 fn key(&self) -> String {
568 self.text[self.start_key.unwrap()..=self.end_key.unwrap() - 1].to_string()
569 }
570
571 fn indentation(&self) -> usize {
573 self.start_key.expect("Bug: start_key was None but should always be Some.")
574 }
575
576 fn line(&self) -> usize {
577 self.line
578 }
579
580 fn is_value(&self) -> bool {
581 if let (Some(_), Some(_), Some(_), Some(_)) =
582 (self.start_key, self.end_key, self.start_val, self.end_val) {
583 true
584 } else {
585 false
586 }
587 }
588
589 pub fn value(&self) -> Result<String, SmallError> {
590 if self.is_value() {
591 Ok(self.text[self.start_val.unwrap() + 1..=self.end_val.unwrap() - 1].to_string())
592 } else {
593 Err(SmallError::IsKey(self.clone()))
594 }
595 }
596}
597
598impl Display for Token {
599 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
600 write!(f, "{}", self.text)
601 }
602}
603
604#[derive(Debug)]
606pub struct SmallString(Vec<Token>);
607
608fn empty_line(line: &str) -> bool {
609 line.starts_with("//") ||
610 !line.chars().any(|c| !c.is_whitespace())
611}
612
613impl SmallString {
614
615 pub fn from_str(s: &str) -> Result<Self, SmallError> {
617
618 let mut v = Vec::new();
619 let mut before_start_line = true;
620 let mut root_indent = 0;
621 let mut line_num = 0;
622
623 for ln in s.lines() {
624 if empty_line(ln) { continue };
625
626 if before_start_line == true {
628 root_indent = ln.chars().position(|c| !c.is_whitespace()).unwrap();
629 before_start_line = false;
630 };
631 v.push(Token::from_str(ln, line_num, root_indent)?);
632 line_num += 1;
633 };
634 if v.is_empty() { Err(SmallError::Empty) } else { Ok(SmallString(v)) }
635 }
636
637 fn indent(&mut self) {
638 for token in self.0.iter_mut() {
639 token.indent();
640 }
641 }
642
643 pub fn to_ref(&self) -> Small {
645 Small {
646 small: self,
647 reduction: vec!(&self.0[..]),
648 }
649 }
650
651 fn max_key_end(&self) -> (usize, usize) {
653 let root_indent = self.0[0].indentation();
654 let max_end_key = self.0.iter().map(|token| token.end_key.unwrap()).max().unwrap();
655 (root_indent, max_end_key - root_indent)
656 }
657}
658
659impl Index<usize> for SmallString {
660 type Output = Token;
661
662 fn index(&self, i: usize) -> &Token {
663 &self.0[i]
664 }
665}
666
667impl fmt::Display for SmallString {
668 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
669 let (root_indent, max_key_end) = self.max_key_end();
670 let mut s = String::new();
671
672 for token in self.0.iter() {
674 let val_shift: Option<i32> = match token.start_val {
675 Some(sv) => Some((max_key_end + 1) as i32 - sv as i32),
676 None => None,
677 };
678 let (start_val, end_val) = match (token.start_val, token.end_val, val_shift) {
679 (Some(sv), Some(ev), Some(vs)) => {
680 (Some((sv as i32 + vs as i32) as usize), Some((ev as i32 + vs as i32) as usize))
681 },
682 _ => {
683 (None, None)
684 },
685 };
686 let new_token = Token {
687 text: token.text.clone(),
688 line: token.line,
689 start_key: Some(token.start_key.unwrap() - root_indent),
690 end_key: Some(token.end_key.unwrap() - root_indent),
691 start_val: start_val,
692 end_val: end_val,
693 };
694 s.push_str(&format!("{}\n", new_token.to_string()));
695 };
696 s.pop();
697 write!(f, "{}", s)
698 }
699}
700
701#[derive(Clone, Debug)]
704pub struct Small<'a> {
705 pub small: &'a SmallString,
706
707 reduction: Vec<&'a [Token]>,
720}
721
722impl<'a> Small<'a> {
723
724 fn tokens(&self) -> Vec<String> {
725 let mut v = Vec::new();
726
727 for key_set in self.reduction.iter() {
728 for token in key_set.iter() {
729 v.push(token.to_string())
730 }
731 }
732 v
733 }
734
735 fn apply_key(self, key: &str) -> Result<Small<'a>, SmallError> {
738 let mut reduction: Vec<&[Token]> = Vec::new();
739
740 for &slice in self.reduction.iter() {
741 let root_indent = slice[0].indentation();
742 let mut i = 0usize;
743 'outer: loop {
744 if slice[i].key() == key && (slice[i].indentation() - root_indent) / INDENTSTEP == 1 {
745 let start_index = i;
746 'inner: loop {
747
748 if (i < slice.len() - 1) &&
751 ((slice[i + 1].indentation() - root_indent) / INDENTSTEP <= 1) {
752 let end_index = i;
753 reduction.push(&slice[start_index..=end_index]);
754 break 'inner;
755 }
756
757 if i == slice.len() - 1 {
759 let end_index = i;
760 reduction.push(&slice[start_index..=end_index]);
761 break 'outer;
762 };
763
764 i += 1
765 }
766 };
767 i += 1;
768 if i == slice.len() { break 'outer };
769 };
770 };
771 Ok(Small {
772 small: self.small,
773 reduction: reduction,
774 })
775 }
776
777 fn apply_path(&self, s: &str) -> Result<Small, SmallError> {
780 let mut reduction = self.clone();
781 for (i, key) in KeyPath::from_str(s)?.enumerate() {
782 if i > 0 {
783 reduction = reduction.apply_key(&key.to_string())?;
784 };
785 }
786 Ok(reduction)
787 }
788}
789
790impl<'a> Display for Small<'a> {
791 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
792 let mut s = String::new();
793 s.push_str("reductions:\n");
794 for slice in self.reduction.iter() {
795 s.push_str("[\n");
796 for token in slice.iter() {
797 s.push_str(&token.to_string());
798 s.push('\n');
799 }
800 s.push_str("]\n");
801 }
802 s.pop();
803 write!(f, "{}", s)
804 }
805}
806
807impl<'a> Small<'a> {
808 pub fn unique_value(&self) -> Result<Token, SmallError> {
810 if self.reduction.is_empty() { return Err(SmallError::MissingToken) };
811 if self.reduction.len() > 1 { return Err(SmallError::NotUnique(self.reduction.len())) };
812 let token = &self.reduction[0][0];
813 if token.is_value() { Ok(token.clone()) } else { Err(SmallError::IsKey(token.clone())) }
814 }
815}
816
817pub trait FromSmall {
819
820 fn from_small(slice: &Small) -> Result<Self, SmallError>
823 where Self: std::marker::Sized;
824
825 fn path(small: &Small, key_path: &str) -> Result<Self, SmallError>
828 where
829 Self: std::marker::Sized
830 {
831 Ok(Self::from_small(&small.apply_path(key_path)?)?)
832 }
833
834 fn from_str(s: &str) -> Result<Self, SmallError>
836 where Self: std::marker::Sized
837 {
838 let small = SmallString::from_str(s)?;
839 let small = Small {
840 small: &small,
841 reduction: vec!(&small.0[..]),
842 };
843 Ok(Self::from_small(&small)?)
844 }
845
846 fn from_str_debug(s: &str) -> Self
849 where Self: std::marker::Sized
850 {
851 match Self::from_str(s) {
852 Ok(s) => s,
853 Err(e) => {
854 match e {
855
856 SmallError::Empty => {
857 eprintln!("The input data string is empty.");
858 }
859
860 SmallError::EmptyKey(token, pos) => {
861 let info = &format!(
862 "{}{} {}",
863 " ".repeat(pos),
864 "^".yellow().bold(),
865 "missing key".yellow().bold(),
866 );
867 in_context(s, info, token.line);
868 },
869
870 SmallError::Indent(token, _) => {
871
872 let info = &format!(
873 "{}{}{}{} {} {} {}",
874 " ".repeat(token.start_key.unwrap() - 4 - (token.start_key.unwrap() % 4)),
875 "|".yellow().bold(),
876 "_".repeat(3).yellow().bold(),
877 "|".yellow().bold(),
878 "indent".yellow().bold(),
879 INDENTSTEP.to_string().yellow().bold(),
880 "spaces only".yellow().bold()
881 );
882 in_context(s, info, token.line);
883 },
884
885 SmallError::NoColon(token, pos) => {
886 let info = &format!(
887 "{}{} {}",
888 " ".repeat(token.start_key.unwrap()),
889 "^".repeat(pos - token.start_key.unwrap()).yellow().bold(),
890 "key requires colon".yellow().bold()
891 );
892 in_context(s, info, token.line);
893 },
894
895 SmallError::NoSecondQuote(token, pos) => {
896 let info = &format!(
897 "{}{} {}",
898 " ".repeat(pos),
899 "^".yellow().bold(),
900 "missing second quotemark".yellow().bold(),
901 );
902 in_context(s, info, token.line);
903 }
904
905 SmallError::NoSpaceAfterKey(token) => {
906 let info = &format!(
907 "{}{}{} {}",
908 " ".repeat(token.start_key.unwrap()),
909 " ".repeat(token.end_key.unwrap() + 1 - token.start_key.unwrap()),
910 "^".yellow().bold(),
911 "requires at least one space after key".yellow().bold()
912 );
913 in_context(s, info, token.line);
914 },
915
916 SmallError::ParseValue(token, to_type) => {
917 let info = &format!(
918 "{}{} {}",
919 " ".repeat(token.start_val.unwrap() + 1),
920 "^".repeat(token.value().unwrap().char_indices().count()).yellow().bold(),
921 format!("number could not be parsed into a {}", to_type).yellow().bold(),
922 );
923 in_context(s, info, token.line);
924 },
925
926 SmallError::QuotemarkInKey(token, pos) => {
927 let info = &format!(
928 "{}{} {}",
929 " ".repeat(pos),
930 "^".yellow().bold(),
931 "no double quotes allowed in key".yellow().bold(),
932 );
933 in_context(s, info, token.line);
934 }
935
936 _ => eprintln!("{}", e.to_string()),
937 };
938 exit(1);
939 },
940 }
941 }
942}
943
944fn in_context(s: &str, info: &str, line: usize) {
945 for (i, ln) in s.lines().take(20).enumerate() {
946 eprintln!("{}", ln);
947 if i == line {
948 eprintln!("{}", info);
949 };
950 };
951}
952
953impl FromSmall for String {
954 fn from_small(small: &Small) -> Result<Self, SmallError> {
955 small.unique_value()?.value()
956 }
957}
958
959impl FromSmall for u8 {
960 fn from_small(small: &Small) -> Result<Self, SmallError> {
961 let token = small.unique_value()?;
962 token
963 .value()?
964 .parse::<u8>()
965 .map_err(|_| SmallError::ParseValue(token, "u8"))
966 }
967}
968
969impl FromSmall for i8 {
970 fn from_small(small: &Small) -> Result<Self, SmallError> {
971 let token = small.unique_value()?;
972 token
973 .value()?
974 .parse::<i8>()
975 .map_err(|_| SmallError::ParseValue(token, "i8"))
976 }
977}
978
979impl FromSmall for u16 {
980 fn from_small(small: &Small) -> Result<Self, SmallError> {
981 let token = small.unique_value()?;
982 token
983 .value()?
984 .parse::<u16>()
985 .map_err(|_| SmallError::ParseValue(token, "u16"))
986 }
987}
988
989impl FromSmall for i16 {
990 fn from_small(small: &Small) -> Result<Self, SmallError> {
991 let token = small.unique_value()?;
992 token
993 .value()?
994 .parse::<i16>()
995 .map_err(|_| SmallError::ParseValue(token, "i16"))
996 }
997}
998
999impl FromSmall for u32 {
1000 fn from_small(small: &Small) -> Result<Self, SmallError> {
1001 let token = small.unique_value()?;
1002 token
1003 .value()?
1004 .parse::<u32>()
1005 .map_err(|_| SmallError::ParseValue(token, "u32"))
1006 }
1007}
1008
1009impl FromSmall for i32 {
1010 fn from_small(small: &Small) -> Result<Self, SmallError> {
1011 let token = small.unique_value()?;
1012 token
1013 .value()?
1014 .parse::<i32>()
1015 .map_err(|_| SmallError::ParseValue(token, "i32"))
1016 }
1017}
1018
1019impl FromSmall for u64 {
1020 fn from_small(small: &Small) -> Result<Self, SmallError> {
1021 let token = small.unique_value()?;
1022 token
1023 .value()?
1024 .parse::<u64>()
1025 .map_err(|_| SmallError::ParseValue(token, "u64"))
1026 }
1027}
1028
1029impl FromSmall for i64 {
1030 fn from_small(small: &Small) -> Result<Self, SmallError> {
1031 let token = small.unique_value()?;
1032 token
1033 .value()?
1034 .parse::<i64>()
1035 .map_err(|_| SmallError::ParseValue(token, "i64"))
1036 }
1037}
1038
1039impl FromSmall for u128 {
1040 fn from_small(small: &Small) -> Result<Self, SmallError> {
1041 let token = small.unique_value()?;
1042 token
1043 .value()?
1044 .parse::<u128>()
1045 .map_err(|_| SmallError::ParseValue(token, "u128"))
1046 }
1047}
1048
1049impl FromSmall for i128 {
1050 fn from_small(small: &Small) -> Result<Self, SmallError> {
1051 let token = small.unique_value()?;
1052 token
1053 .value()?
1054 .parse::<i128>()
1055 .map_err(|_| SmallError::ParseValue(token, "i128"))
1056 }
1057}
1058
1059impl FromSmall for usize {
1060 fn from_small(small: &Small) -> Result<Self, SmallError> {
1061 let token = small.unique_value()?;
1062 token.
1063 value()?
1064 .parse::<usize>()
1065 .map_err(|_| SmallError::ParseValue(token, "usize"))
1066 }
1067}
1068
1069impl FromSmall for isize {
1070 fn from_small(small: &Small) -> Result<Self, SmallError> {
1071 let token = small.unique_value()?;
1072 token.
1073 value()?
1074 .parse::<isize>()
1075 .map_err(|_| SmallError::ParseValue(token, "isize"))
1076 }
1077}
1078
1079impl FromSmall for f32 {
1080 fn from_small(small: &Small) -> Result<Self, SmallError> {
1081 let token = small.unique_value()?;
1082 token
1083 .value()?
1084 .parse::<f32>()
1085 .map_err(|_| SmallError::ParseValue(token, "f32"))
1086 }
1087}
1088
1089impl FromSmall for f64 {
1090 fn from_small(small: &Small) -> Result<Self, SmallError> {
1091 let token = small.unique_value()?;
1092 token
1093 .value()?
1094 .parse::<f64>()
1095 .map_err(|_| SmallError::ParseValue(token, "f64"))
1096 }
1097}
1098
1099impl FromSmall for bool {
1100 fn from_small(small: &Small) -> Result<Self, SmallError> {
1101 let token = small.unique_value()?;
1102 if "false" == &token.value()? {
1103 return Ok(false)
1104 };
1105 if "true" == &token.value()? {
1106 return Ok(true)
1107 };
1108 Err(SmallError::ParseValue(token, "bool"))
1109 }
1110}
1111
1112impl<T> FromSmall for Option<T>
1115where
1116 T: FromSmall
1117{
1118 fn from_small(small: &Small) -> Result<Self, SmallError> {
1119 if small.reduction.is_empty() {
1120 return Ok(None)
1121 } else {
1122 Ok(Some(T::from_small(small)?))
1123 }
1124 }
1125}
1126
1127impl<T>FromSmall for Vec<T>
1128where
1129 T: FromSmall
1130{
1131 fn from_small(s: &Small) -> Result<Self, SmallError> {
1132 let mut v: Vec<T> = Vec::new();
1133 for &slice in s.reduction.iter() {
1134 let dat = Small {
1135 small: s.small,
1136 reduction: vec!(slice),
1137 };
1138 v.push(T::from_small(&dat)?);
1139 };
1140 Ok(v)
1141 }
1142}