为了掌握序列化,我自己实现了一个自己的序列化

116 阅读3分钟

在rust开发过程中,我们总是会用到序列化,反序列化,之前我们就介绍了serde这个优秀的序列化框架,不知道的同学可以看我往期的文章,那么具体是怎么实现序列化和反序列化的我们还不是很清楚,具体怎么工作的也不清楚,我们今天就来解决这个问题

定义序列化trait

序列化最核心的接口就是Serialize和Deserialize两个,其中Deserialize是反序列化trait,具体的trait定义如下:

pub trait Serialize {
    fn serialize(&self-> String;
}

pub trait DeserializeSized {
    fn deserialize(s: &str-> Result<SelfString>;
}

给不同类型实现序列化trait

我们可以为不同的数据类型实现对应的trait实现序列化和反序列化,比如说基本类型以及复合类型,比如说我们Vector中存放一个结构体和枚举

use crate::serialization::{Deserialize, Serialize};
use chrono::NaiveDateTime;
use std::collections::HashSet;
use std::fmt::Debug;

// Example implementation for basic types
impl Serialize for i32 {
    fn serialize(&self) -> String {
        self.to_string()
    }
}

impl Deserialize for i32 {
    fn deserialize(s: &str) -> Result<Self, String> {
        s.parse().map_err(|e| format!("Failed to parse i32: {}", e))
    }
}

impl Serialize for String {
    fn serialize(&self) -> String {
        format!(""{}"", self.replace(""", "\""))
    }
}

impl Deserialize for String {
    fn deserialize(s: &str) -> Result<Self, String> {
        if s.len() >= 2 && s.starts_with('"') && s.ends_with('"') {
            Ok(s[1..s.len() - 1].replace("\"", """))
        } else {
            Err("Invalid string format".to_string())
        }
    }
}

// Example implementation for additional types
impl Serialize for bool {
    fn serialize(&self) -> String {
        self.to_string()
    }
}

impl Deserialize for bool {
    fn deserialize(s: &str) -> Result<Self, String> {
        match s {
            "true" => Ok(true),
            "false" => Ok(false),
            _ => Err("Failed to parse bool".to_string()),
        }
    }
}

impl Serialize for f64 {
    fn serialize(&self) -> String {
        self.to_string()
    }
}

impl Deserialize for f64 {
    fn deserialize(s: &str) -> Result<Self, String> {
        s.parse().map_err(|e| format!("Failed to parse f64: {}", e))
    }
}

impl Serialize for NaiveDateTime {
    fn serialize(&self) -> String {
        self.format("%Y-%m-%d %H:%M:%S").to_string()
    }
}

impl Deserialize for NaiveDateTime {
    fn deserialize(s: &str) -> Result<Self, String> {
        NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S")
            .map_err(|e| format!("Failed to parse NaiveDateTime: {}", e))
    }
}

impl<T> Serialize for Vec<T>
where
    T: Serialize,
{
    fn serialize(&self) -> String {
        let serialized_elements: Vec<String> = self.iter().map(|item| item.serialize()).collect();
        format!("[{}]", serialized_elements.join(","))
    }
}

impl<T> Deserialize for Vec<T>
where
    T: Deserialize,
{
    fn deserialize(s: &str) -> Result<Self, String> {
        let s = s.trim();
        if !s.starts_with('[') || !s.ends_with(']') {
            return Err("Invalid array format".to_string());
        }

        let content = &s[1..s.len() - 1];
        if content.is_empty() {
            return Ok(Vec::new());
        }

        content
            .split(',')
            .map(|item| T::deserialize(item.trim()))
            .collect()
    }
}

impl<T> Serialize for HashSet<T>
where
    T: Serialize + Eq + std::hash::Hash,
{
    fn serialize(&self) -> String {
        let serialized_elements: Vec<String> = self.iter().map(|item| item.serialize()).collect();
        format!("{{{}}}", serialized_elements.join(","))
    }
}

impl<T> Deserialize for HashSet<T>
where
    T: Deserialize + Eq + std::hash::Hash,
{
    fn deserialize(s: &str) -> Result<Self, String> {
        let s = s.trim();
        if !s.starts_with('{') || !s.ends_with('}') {
            return Err("Invalid set format".to_string());
        }

        let content = &s[1..s.len() - 1];
        if content.is_empty() {
            return Ok(HashSet::new());
        }

        content
            .split(',')
            .map(|item| T::deserialize(item.trim()))
            .collect::<Result<HashSet<_>, _>>()
    }
}

例子

mod serialization;
mod serialization_impl;

use chrono::NaiveDateTime;
use serde_json::json;
use serialization::{Deserialize, Serialize};

// Derive macro simulation using a struct
#[derive(Debug)]
struct Person {
    name: String,
    age: i32,
}

impl Serialize for Person {
    fn serialize(&self-> String {
        format!(
            "{{"name":{},"age":{}}}",
            self.name.serialize(),
            self.age.serialize()
        )
    }
}

impl Deserialize for Person {
    fn deserialize(s: &str-> Result<SelfString> {
        // Basic parser for demonstration
        // In a real implementation, you'd want a proper parser
        let s = s.trim();
        if !s.starts_with('{') || !s.ends_with('}') {
            return Err("Invalid object format".to_string());
        }

        let content = &s[1..s.len() - 1];
        let mut name = None;
        let mut age = None;

        for pair in content.split(',') {
            let mut parts = pair.split(':');
            let key = parts.next().ok_or("Missing key")?.trim().trim_matches('"');
            let value = parts.next().ok_or("Missing value")?.trim();

            match key {
                "name" => name = Some(String::deserialize(value)?),
                "age" => age = Some(i32::deserialize(value)?),
                _ => return Err(format!("Unknown field: {}", key)),
            }
        }

        Ok(Person {
            name: name.ok_or("Missing name field")?,
            age: age.ok_or("Missing age field")?,
        })
    }
}

// Example usage in main
fn main() {
    let person = Person {
        name: "John Doe".to_string(),
        age: 30,
    };

    // Serialize
    let serialized = person.serialize();
    println!("Serialized: {}", serialized);

    // Deserialize
    match Person::deserialize(&serialized) {
        Ok(deserialized) => {
            // Format the output as JSON
            let formatted = json!({
                "name": deserialized.name,
                "age": deserialized.age
            });
            println!("Deserialized (formatted): {}", formatted);
        }
        Err(e) => println!("Error: {}", e),
    }

    // Example with NaiveDateTime
    let datetime =
        NaiveDateTime::parse_from_str("2023-01-01 12:00:00""%Y-%m-%d %H:%M:%S").unwrap();
    let serialized_datetime = datetime.serialize();
    println!("Serialized DateTime: {}", serialized_datetime);

    match NaiveDateTime::deserialize(&serialized_datetime) {
        Ok(deserialized_datetime) => println!("Deserialized DateTime: {}", deserialized_datetime),
        Err(e) => println!("Error: {}", e),
    }

    // Example with Vec
    let numbers = vec![12345];
    let serialized_numbers = numbers.serialize();
    println!("Serialized Vec: {}", serialized_numbers);

    match Vec::<i32>::deserialize(&serialized_numbers) {
        Ok(deserialized_numbers) => println!("Deserialized Vec: {:?}", deserialized_numbers),
        Err(e) => println!("Error: {}", e),
    }

    // Example with Vec of Status
    let statuses = vec![Status::Active, Status::Inactive, Status::Pending];
    let serialized_statuses = statuses.serialize();
    println!("Serialized Vec<Status>: {}", serialized_statuses);

    match Vec::<Status>::deserialize(&serialized_statuses) {
        Ok(deserialized_statuses) => {
            println!("Deserialized Vec<Status>: {:?}", deserialized_statuses)
        }
        Err(e) => println!("Error: {}", e),
    }

    // Example with HashSet of Status
}

#[derive(Debug)]
enum Status {
    Active,
    Inactive,
    Pending,
}

impl Serialize for Status {
    fn serialize(&self-> String {
        match self {
            Status::Active => ""Active"".to_string(),
            Status::Inactive => ""Inactive"".to_string(),
            Status::Pending => ""Pending"".to_string(),
        }
    }
}

impl Deserialize for Status {
    fn deserialize(s: &str-> Result<SelfString> {
        match s.trim_matches('"') {
            "Active" => Ok(Status::Active),
            "Inactive" => Ok(Status::Inactive),
            "Pending" => Ok(Status::Pending),
            _ => Err("Unknown status".to_string()),
        }
    }
}

希望大家多多关注我的公众号:花说编程,给你带来rust知识的分享