Add serialization.
[?]
Jun 14, 2021, 6:59 AM
K5VHGRGG3R5M22HJQKALBKGU5Z3X5B45MT7M6ZMBKEKHDLI6NN5ACDependencies
Change contents
- file addition: serialize.rs[3.6]
use std::fmt;pub trait IntoKeyTree {fn to_keytree(&self) -> KeyTreeString;}pub enum Token {KeyToken(KeyToken),KeyValToken(KeyValToken),Comment(Comment),}impl Token {pub fn to_string(&self, max_key_len: usize) -> String {match self {Token::KeyToken(kt) => kt.to_string(max_key_len),Token::KeyValToken(kvt) => kvt.to_string(max_key_len),Token::Comment(c) => c.to_string(max_key_len),}}}pub struct KeyToken {indent: usize,key: String,}impl KeyToken {pub fn to_string(&self, _max_key_len: usize) -> String {let mut s = indent_to(self.indent, &self.key);s.push(':');s}}pub struct KeyValToken {indent: usize,key: String,val: String,}impl KeyValToken {pub fn to_string(&self, max_key_len: usize) -> String {let mut s = indent_to(self.indent, &self.key);s.push_str(": ");append_at_indent(chars_to_indent(max_key_len), &s, &self.val)}}// Takes number of chars and returns minimum indent that is greater than the number of chars.pub fn chars_to_indent(chars: usize) -> usize {// 0 -> 0// 1 -> 1// 2 -> 1// 3 -> 1// 4 -> 1// 5 -> 2(chars + 3) / 4}#[test]fn test_chars_to_indent() {assert_eq!(chars_to_indent(0), 0);assert_eq!(chars_to_indent(1), 1);assert_eq!(chars_to_indent(4), 1);assert_eq!(chars_to_indent(5), 2);}pub struct Comment {indent: usize,comment: String,}impl Comment {pub fn to_string(&self, _max_key_len: usize) -> String {let mut s = indent_to(self.indent, "// ");s.push_str(&self.comment);s}}pub struct KeyTreeString {tokens: Vec<Token>,max_key_len: usize,}impl KeyTreeString {pub fn new() -> Self {KeyTreeString {tokens: Vec::new(),max_key_len: 0,}}/// Push a key token onto the String. The indent value is relative to the root indent.pub fn push_key(&mut self, indent: usize, key: &str) {let key = Token::KeyToken(KeyToken {indent: indent,key: String::from(key),});self.tokens.push(key)}/// Push a key-value token onto the String. The indent value is relative to the root indent.pub fn push_keyvalue(&mut self, indent: usize, key: &str, value: &str) {let kv = Token::KeyValToken(KeyValToken {indent: indent,key: String::from(key),val: String::from(value),});self.tokens.push(kv);// Colon and spacelet key_len = key.chars().count() + (indent * 4) + 2;if key_len > self.max_key_len {self.max_key_len = key_len;};}/// Push a comment onto the String. The indent value is relative to the root indent.pub fn push_comment(&mut self, indent: usize, comment: &str) {let comment = Token::Comment(Comment {indent: indent * 4,comment: String::from(comment),});self.tokens.push(comment)}/// Push a KeyTreeString on to the String. The indent value is relative to the root indent.pub fn push_keytree(&mut self, indent: usize, keytree: KeyTreeString) {for token in keytree.tokens {match token {Token::KeyToken(k) => {self.push_key(k.indent + indent, &k.key);},Token::KeyValToken(kv) => {self.push_keyvalue(kv.indent + indent, &kv.key, &kv.val);},Token::Comment(c) => {self.push_comment(c.indent + indent, &c.comment);}}}}}#[test]fn test_keytree_string1() {let mut kts = KeyTreeString::new();kts.push_key(0, "key");kts.push_key(1, "a_key");kts.push_keyvalue(1, "b_key", "b_val");assert_eq!(kts.to_string(),"key:\n a_key:\n b_key: b_val",)}impl fmt::Display for KeyTreeString {fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {let mut s = String::new();for tok in &self.tokens {s.push_str(&tok.to_string(self.max_key_len));s.push('\n');}s.pop();write!(f, "{}", s)}}/// Append whitespace of length `n` to start of a string.fn indent_to(indent: usize, key: &str) -> String {let mut s = String::new();for _ in 0..(indent * 4) { s.push(' ') };s.push_str(&key);s}#[test]fn test_indent_to() {assert_eq!(indent_to(1, "abc")," abc",)}/// Append string `t` to end of `s` at indent `indent`. Panic if/// strings overlap.fn append_at_indent(indent: usize, key: &str, val: &str) -> String {let mut s = String::from(key);let padding = (indent * 4) - s.chars().count() - 1;for _ in 0..=padding { s.push(' ') };s.push_str(&val);s}#[test]fn test_append_at_indent() {assert_eq!(append_at_indent(3, " abc", "def")," abc def",)} - edit in src/lib.rs at line 13
pub mod serialize; - replacement in src/into.rs at line 59
Some(_) => Err(Error::new(ErrorKind::EUniqueKeyValueFMany)),Some(i) => Err(Error::new(ErrorKind::EUniqueKeyValueFMany(String::from("todo"), *i))), - edit in src/error.rs at line 41
// Can be used by client code.User(String), - replacement in src/error.rs at line 50
// Expected a key/value pair, found many.EUniqueKeyValueFMany,// Expected a key/value pair, found many (token, pos)EUniqueKeyValueFMany(String, usize), - edit in src/error.rs at line 111
ErrorKind::User(_) => None, - replacement in src/error.rs at line 114
ErrorKind::EUniqueKeyValueFMany => None,ErrorKind::EUniqueKeyValueFMany(_,_) => None, - edit in src/error.rs at line 139
ErrorKind::User(msg) => {write!(f,"Error: Client error: \"{}\".",msg,)}ErrorKind::FailedFromStr(token, pos, into_type) => {write!(f,"Error: Couldn't read string into type {} at {}: \"{}\".",into_type,pos,token,)}, - replacement in src/error.rs at line 166
ErrorKind::EUniqueKeyValueFMany => {write!(f, "{}", "expected_unique_key_value_found_many")ErrorKind::EUniqueKeyValueFMany(token, pos) => {write!(f,"token: {}, pos: {}",token,pos,)// "expected_unique_key_value_found_many")