Add serialization.

[?]
Jun 14, 2021, 6:59 AM
K5VHGRGG3R5M22HJQKALBKGU5Z3X5B45MT7M6ZMBKEKHDLI6NN5AC

Dependencies

Change contents

  • file addition: serialize.rs (-xw-xw-x--)
    [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 space
    let 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
    [2.4025]
    [3.18953]
    pub mod serialize;
  • replacement in src/into.rs at line 59
    [3.30129][3.30129:30210]()
    Some(_) => Err(Error::new(ErrorKind::EUniqueKeyValueFMany)),
    [3.30129]
    [3.30210]
    Some(i) => Err(Error::new(ErrorKind::EUniqueKeyValueFMany(String::from("todo"), *i))),
  • edit in src/error.rs at line 41
    [3.37477]
    [3.37477]
    // Can be used by client code.
    User(String),
  • replacement in src/error.rs at line 50
    [3.37603][3.37603:37675]()
    // Expected a key/value pair, found many.
    EUniqueKeyValueFMany,
    [3.37603]
    [3.37675]
    // Expected a key/value pair, found many (token, pos)
    EUniqueKeyValueFMany(String, usize),
  • edit in src/error.rs at line 111
    [3.39185]
    [3.39185]
    ErrorKind::User(_) => None,
  • replacement in src/error.rs at line 114
    [3.39307][3.39307:39368]()
    ErrorKind::EUniqueKeyValueFMany => None,
    [3.39307]
    [3.39368]
    ErrorKind::EUniqueKeyValueFMany(_,_) => None,
  • edit in src/error.rs at line 139
    [3.40486]
    [3.40486]
    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
    [3.40731][3.40731:40852]()
    ErrorKind::EUniqueKeyValueFMany => {
    write!(f, "{}", "expected_unique_key_value_found_many")
    [3.40731]
    [3.40852]
    ErrorKind::EUniqueKeyValueFMany(token, pos) => {
    write!(
    f,
    "token: {}, pos: {}",
    token,
    pos,
    )
    // "expected_unique_key_value_found_many")